Merge lp:~freshapplepy/backintime/gtkbuilder into lp:backintime/1.0

Proposed by Isaiah Heyer
Status: Merged
Merged at revision: not available
Proposed branch: lp:~freshapplepy/backintime/gtkbuilder
Merge into: lp:backintime/1.0
Diff against target: 6008 lines
8 files modified
gnome/app.py (+1063/-1053)
gnome/mainwindow.glade (+125/-131)
gnome/messagebox.py (+39/-32)
gnome/settingsdialog.glade (+215/-214)
gnome/settingsdialog.py (+555/-544)
gnome/snapshotsdialog.glade (+93/-82)
gnome/snapshotsdialog.py (+302/-295)
gnome/textinputdialog.glade (+43/-32)
To merge this branch: bzr merge lp:~freshapplepy/backintime/gtkbuilder
Reviewer Review Type Date Requested Status
Bart de Koning (community) Approve
Dan Pending
Review via email: mp+11914@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Bart de Koning (bratdaking) wrote :

Nice rewrite of the GUI to switch from the libglade to the GTKbuilder format!

review: Approve
Revision history for this message
Isaiah Heyer (freshapplepy) wrote :

> Nice rewrite of the GUI to switch from the libglade to the GTKbuilder format!

Has Dan looked at it yet?

616. By Isaiah Heyer

Corrected grammar.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'gnome/app.py'
2--- gnome/app.py 2009-06-17 09:49:51 +0000
3+++ gnome/app.py 2009-10-01 16:35:20 +0000
4@@ -22,7 +22,7 @@
5 import sys
6
7 if len( os.getenv( 'DISPLAY', '' ) ) == 0:
8- os.putenv( 'DISPLAY', ':0.0' )
9+ os.putenv( 'DISPLAY', ':0.0' )
10
11 import pygtk
12 pygtk.require("2.0")
13@@ -30,7 +30,6 @@
14 import pynotify
15 import threading
16 import gobject
17-import gtk.glade
18 import gnome
19 import gnomevfs
20 import datetime
21@@ -57,1061 +56,1072 @@
22 _=gettext.gettext
23
24
25-class AboutDialog( gtk.AboutDialog ):
26- def __init__( self, config, parent ):
27- gtk.AboutDialog.__init__( self )
28-
29- self.connect( 'close', self.on_close )
30- self.connect( 'response', self.on_close )
31-
32- self.set_transient_for( parent )
33-
34- self.set_name( config.APP_NAME )
35- self.set_version( config.VERSION )
36- self.set_copyright( 'Copyright (C) 2008-2009 Oprea Dan' )
37- self.set_website( 'http://backintime.le-web.org' )
38- self.set_website_label( 'http://backintime.le-web.org' )
39- self.set_license( config.get_license() )
40- authors = config.get_authors()
41- if not authors is None:
42- self.set_authors( authors.split( '\n' ) )
43-
44- #extra_translations = _('about-translators').strip()
45- #if extra_translations is None:
46- # extra_translations = ''
47- #elif extra_translations == 'about-translators':
48- # extra_translations = ''
49- #
50- #self.set_translator_credits( config.get_translations() + extra_translations )
51- self.set_translator_credits( config.get_translations() )
52-
53- def on_close( self, *params ):
54- self.destroy()
55-
56-
57-class MainWindow:
58- def __init__( self, config, app_instance ):
59- self.config = config
60- self.app_instance = app_instance
61- self.snapshots = snapshots.Snapshots( config )
62- self.special_background_color = 'lightblue'
63- self.popup_menu = None
64-
65- self.folder_path = None
66- self.snapshot_id = ''
67-
68- self.last_take_snapshot_message = None
69-
70- self.glade = gtk.glade.XML( os.path.join( self.config.get_app_path(), 'gnome', 'mainwindow.glade' ), None, 'backintime' )
71-
72- signals = {
73- 'on_MainWindow_destroy' : gtk.main_quit,
74- 'on_MainWindow_delete_event' : self.on_close,
75- 'on_MainWindow_key_release_event': self.on_key_release_event,
76- 'on_btn_exit_clicked' : self.on_close,
77- 'on_btn_link_clicked' : self.on_btn_link_clicked,
78- 'on_btn_help_clicked' : self.on_btn_help_clicked,
79- 'on_btn_about_clicked' : self.on_btn_about_clicked,
80- 'on_btn_settings_clicked' : self.on_btn_settings_clicked,
81- 'on_btn_backup_clicked' : self.on_btn_backup_clicked,
82- 'on_btn_update_snapshots_clicked' : self.on_btn_update_snapshots_clicked,
83- 'on_btn_snapshot_name_clicked' : self.on_btn_snapshot_name_clicked,
84- 'on_btn_remove_snapshot_clicked' : self.on_btn_remove_snapshot_clicked,
85- 'on_btn_restore_clicked' : self.on_btn_restore_clicked,
86- 'on_btn_copy_clicked' : self.on_btn_copy_clicked,
87- 'on_btn_snapshots_clicked' : self.on_btn_snapshots_clicked,
88- 'on_btn_hidden_files_toggled' : self.on_btn_hidden_files_toggled,
89- 'on_list_places_cursor_changed' : self.on_list_places_cursor_changed,
90- 'on_list_time_line_cursor_changed' : self.on_list_time_line_cursor_changed,
91- 'on_btn_folder_up_clicked' : self.on_btn_fodler_up_clicked,
92- 'on_list_folder_view_row_activated' : self.on_list_folder_view_row_activated,
93- 'on_list_folder_view_popup_menu' : self.on_list_folder_view_popup_menu,
94- 'on_list_folder_view_button_press_event': self.on_list_folder_view_button_press_event,
95- 'on_list_folder_view_drag_data_get': self.on_list_folder_view_drag_data_get,
96- 'on_combo_profiles_changed': self.on_combo_profiles_changed,
97- }
98-
99- self.glade.signal_autoconnect( signals )
100-
101- self.window = self.glade.get_widget( 'MainWindow' )
102- self.window.set_title( self.config.APP_NAME )
103-
104- #icons
105- self.icon_names = fileicons.GnomeFileIcons()
106-
107- #fix a glade bug
108- self.glade.get_widget( 'btn_current_path' ).set_expand( True )
109- #self.glade.get_widget( 'tb_sep_item' ).set_expand( True )
110-
111- #profiles
112- self.disable_combo_changed = True
113- self.first_update_all = True
114-
115- self.store_profiles = gtk.ListStore( str, str )
116-
117- self.combo_profiles = self.glade.get_widget( 'combo_profiles' )
118-
119- text_renderer = gtk.CellRendererText()
120- self.combo_profiles.pack_start( text_renderer, True )
121- self.combo_profiles.add_attribute( text_renderer, 'text', 0 )
122-
123- self.combo_profiles.set_model( self.store_profiles )
124-
125- self.disable_combo_changed = False
126-
127- #lbl snapshot
128- self.lbl_snapshot = self.glade.get_widget( 'lbl_snapshot' )
129-
130- #status bar
131- self.status_bar = self.glade.get_widget( 'status_bar' )
132- self.status_bar.push( 0, _('Done') )
133-
134- #show hidden files
135- self.show_hidden_files = self.config.get_bool_value( 'gnome.show_hidden_files', False )
136- self.btn_hidden_files = self.glade.get_widget( 'btn_hidden_files' )
137- self.btn_hidden_files.set_active( self.show_hidden_files )
138- #self.btn_hidden_files.set_label( _('Hidden files') ) #!!!
139-
140- #setup places view
141- self.list_places = self.glade.get_widget( 'list_places' )
142-
143- pix_renderer = gtk.CellRendererPixbuf()
144- text_renderer = gtk.CellRendererText()
145-
146- column = gtk.TreeViewColumn( _('Shortcuts') )
147- column.pack_start( pix_renderer, False )
148- column.pack_end( text_renderer, True )
149- column.add_attribute( pix_renderer, 'icon-name', 2 )
150- column.add_attribute( text_renderer, 'markup', 0 )
151- column.set_cell_data_func( pix_renderer, self.places_pix_renderer_function, None )
152- column.set_cell_data_func( text_renderer, self.places_text_renderer_function, None )
153- #column.set_alignment( 0.5 )
154- self.list_places.append_column( column )
155-
156- #name, icon, path
157- self.store_places = gtk.ListStore( str, str, str )
158- self.list_places.set_model( self.store_places )
159- self.list_places.get_selection().set_select_function( self.places_select_function, self.store_places )
160-
161- #setup folder view
162- self.list_folder_view_widget = self.glade.get_widget( 'list_folder_view_widget' )
163- self.list_folder_view_shadow = self.glade.get_widget( 'list_folder_view_shadow' )
164- self.list_folder_view = self.glade.get_widget( 'list_folder_view' )
165-
166- pix_renderer = gtk.CellRendererPixbuf()
167- text_renderer = gtk.CellRendererText()
168-
169- column = gtk.TreeViewColumn( _('Name') )
170- column.pack_start( pix_renderer, False )
171- column.pack_end( text_renderer, True )
172- column.add_attribute( pix_renderer, 'icon-name', 2 )
173- column.add_attribute( text_renderer, 'markup', 0 )
174- column.set_expand( True )
175- column.set_sizing( gtk.TREE_VIEW_COLUMN_AUTOSIZE )
176- column.set_sort_column_id( 0 )
177- self.list_folder_view.append_column( column )
178-
179- text_renderer = gtk.CellRendererText()
180- column = gtk.TreeViewColumn( _('Size') )
181- column.pack_end( text_renderer, True )
182- column.add_attribute( text_renderer, 'markup', 4 )
183- column.set_sort_column_id( 1 )
184- self.list_folder_view.append_column( column )
185-
186- text_renderer = gtk.CellRendererText()
187- column = gtk.TreeViewColumn( _('Date') )
188- column.pack_end( text_renderer, True )
189- column.add_attribute( text_renderer, 'markup', 5 )
190- column.set_sort_column_id( 2 )
191- self.list_folder_view.append_column( column )
192-
193- # display name, relative path, icon_name, type (0 - directory, 1 - file), size (str), date, size (int)
194- self.store_folder_view = gtk.ListStore( str, str, str, int, str, str, int )
195- self.store_folder_view.set_sort_func( 0, self.sort_folder_view_by_column, 0 ) #name
196- self.store_folder_view.set_sort_func( 1, self.sort_folder_view_by_column, 6 ) #size
197- self.store_folder_view.set_sort_func( 2, self.sort_folder_view_by_column, 5 ) #date
198- self.store_folder_view.set_sort_column_id( 0, gtk.SORT_ASCENDING )
199-
200- self.list_folder_view.set_model( self.store_folder_view )
201-
202- #setup time line view
203- self.list_time_line = self.glade.get_widget( 'list_time_line' )
204-
205- text_renderer = gtk.CellRendererText()
206- column = gtk.TreeViewColumn( _('Snapshots'), text_renderer, markup = 0 )
207- column.set_cell_data_func( text_renderer, self.places_text_renderer_function, None )
208- self.list_time_line.append_column( column )
209-
210- #display name, id
211- self.store_time_line = gtk.ListStore( str, str )
212- self.list_time_line.set_model( self.store_time_line )
213- self.list_time_line.get_selection().set_select_function( self.places_select_function, self.store_time_line )
214- self.update_time_line = False
215-
216- #calculate specialBackgroundColor
217- style = self.list_time_line.get_style()
218- bg1 = style.bg[gtk.STATE_NORMAL]
219- bg2 = style.bg[gtk.STATE_SELECTED]
220- self.special_background_color = gtk.gdk.Color( (2 * bg1.red + bg2.red) / 3, (2 * bg1.green + bg2.green) / 3,(2 * bg1.blue + bg2.blue) / 3 ).to_string()
221-
222- #restore size & position
223- main_window_x = self.config.get_int_value( 'gnome.main_window.x', -1 )
224- main_window_y = self.config.get_int_value( 'gnome.main_window.y', -1 )
225- if main_window_x >= 0 and main_window_y >= 0:
226- self.window.move( main_window_x, main_window_y )
227-
228- main_window_width = self.config.get_int_value( 'gnome.main_window.width', -1 )
229- main_window_height = self.config.get_int_value( 'gnome.main_window.height', -1 )
230- if main_window_width > 0 and main_window_height > 0:
231- self.window.resize( main_window_width, main_window_height )
232-
233- main_window_hpaned1 = self.config.get_int_value( 'gnome.main_window.hpaned1', -1 )
234- main_window_hpaned2 = self.config.get_int_value( 'gnome.main_window.hpaned2', -1 )
235- if main_window_hpaned1 > 0 and main_window_hpaned2 > 0:
236- self.glade.get_widget('hpaned1').set_position( main_window_hpaned1 )
237- self.glade.get_widget('hpaned2').set_position( main_window_hpaned2 )
238-
239- #prepare popup menu ids
240- gtk.stock_add(
241- [ ('backintime.open', _('Open'), 0, 0, 'backintime' ),
242- ('backintime.copy', _('Copy'), 0, 0, 'backintime' ),
243- ('backintime.snapshots', _('Snapshots'), 0, 0, 'backintime' ),
244- ('backintime.diff', _('Diff'), 0, 0, 'backintime' ),
245- ('backintime.restore', _('Restore'), 0, 0, 'backintime' ) ] )
246-
247- #show main window
248- self.window.show()
249- gnometools.run_gtk_update_loop()
250-
251- self.force_wait_lock_counter = 0
252- gobject.timeout_add( 1000, self.raise_application )
253-
254- if not self.config.is_configured():
255- settingsdialog.SettingsDialog( self.config, self ).run()
256-
257- if not self.config.is_configured():
258- return
259-
260- if not self.config.can_backup():
261- messagebox.show_error( self.window, self.config, _('Can\'t find snapshots folder.\nIf it is on a removable drive please plug it and then press OK') )
262-
263- self.update_profiles()
264- self.update_backup_info()
265- gobject.timeout_add( 1000, self.update_backup_info )
266-
267- def on_combo_profiles_changed( self, *params ):
268- if self.disable_combo_changed:
269- return
270-
271- iter = self.combo_profiles.get_active_iter()
272- if iter is None:
273- return
274-
275- first_update_all = self.first_update_all
276-
277- profile_id = self.store_profiles.get_value( iter, 1 )
278- if not first_update_all and profile_id == self.config.get_current_profile():
279- return
280-
281- self.config.set_current_profile( profile_id )
282- self.first_update_all = False
283- self.update_all( first_update_all )
284-
285- def update_profiles( self ):
286- self.disable_combo_changed = True
287-
288- profiles = self.config.get_profiles_sorted_by_name()
289-
290- select_iter = None
291- self.store_profiles.clear()
292-
293- for profile_id in profiles:
294- iter = self.store_profiles.append( [ self.config.get_profile_name( profile_id ), profile_id ] )
295- if profile_id == self.config.get_current_profile():
296- select_iter = iter
297-
298-
299- self.disable_combo_changed = False
300-
301- if not select_iter is None:
302- self.combo_profiles.set_active_iter( select_iter )
303-
304- #self.update_all( True )
305-
306- def sort_folder_view_by_column( self, treemodel, iter1, iter2, column ):
307- if 0 == column:
308- ascending = 1
309- if self.store_folder_view.get_sort_column_id()[1] != gtk.SORT_ASCENDING:
310- ascending = -1
311-
312- type1 = self.store_folder_view.get_value( iter1, 3 )
313- type2 = self.store_folder_view.get_value( iter2, 3 )
314-
315- if type1 == 0 and type2 != 0:
316- return -1 * ascending
317-
318- if type1 != 0 and type2 == 0:
319- return 1 * ascending
320-
321- data1 = self.store_folder_view.get_value( iter1, column )
322- data2 = self.store_folder_view.get_value( iter2, column )
323-
324- if type(data1) is str:
325- data1 = data1.upper()
326-
327- if type(data2) is str:
328- data2 = data2.upper()
329-
330- #print "sort_folder_view_by_column: " + str( data1 ) + " - " + str( data2 )
331-
332- if data1 < data2:
333- return -1
334-
335- if data1 > data2:
336- return 1
337-
338- return 0
339-
340-
341- def get_default_startup_folder_and_file( self ):
342- last_path = self.config.get_str_value( 'gnome.last_path', '' )
343- if len(last_path) > 0 and os.path.isdir(last_path):
344- return ( last_path, None, False )
345- return ( '/', None, False )
346-
347- def get_cmd_startup_folder_and_file( self, cmd ):
348- if cmd is None:
349- cmd = self.app_instance.raise_cmd
350-
351- if len( cmd ) < 1:
352- return None
353-
354- path = None
355- show_snapshots = False
356-
357- for arg in cmd.split( '\n' ):
358- if len( arg ) < 1:
359- continue
360- if arg == '-s' or arg == '--snapshots':
361- show_snapshots = True
362- continue
363- if arg[0] == '-':
364- continue
365- if path is None:
366- path = arg
367-
368- if path is None:
369- return None
370-
371- if len( path ) < 1:
372- return None
373-
374- path = os.path.expanduser( path )
375- path = os.path.abspath( path )
376-
377- if os.path.isdir( path ):
378- if len( path ) < 1:
379- show_snapshots = False
380-
381- if show_snapshots:
382- return ( os.path.dirname( path ), path, True )
383- else:
384- return ( path, '', False )
385-
386- if os.path.isfile( path ):
387- return ( os.path.dirname( path ), path, show_snapshots )
388-
389- return None
390-
391- def get_startup_folder_and_file( self, cmd = None ):
392- startup_folder = self.get_cmd_startup_folder_and_file( cmd )
393- if startup_folder is None:
394- return self.get_default_startup_folder_and_file()
395- return startup_folder
396-
397- def update_all( self, init ):
398- #fill lists
399- selected_file = None
400- show_snapshots = False
401- if init:
402- self.folder_path, selected_file, show_snapshots = self.get_startup_folder_and_file()
403- self.snapshot_id = '/'
404- self.snapshots_list = []
405-
406- self.fill_places()
407- self.fill_time_line( False )
408- self.update_folder_view( 1, selected_file, show_snapshots )
409-
410- def places_pix_renderer_function( self, column, renderer, model, iter, user_data ):
411- if len( model.get_value( iter, 1 ) ) == 0:
412- renderer.set_property( 'visible', False )
413- else:
414- renderer.set_property( 'visible', True )
415-
416- def places_text_renderer_function( self, column, renderer, model, iter, user_data ):
417- if len( model.get_value( iter, 1 ) ) == 0:
418- renderer.set_property( 'cell-background-set', True )
419- renderer.set_property( 'cell-background', self.special_background_color )
420- else:
421- renderer.set_property( 'cell-background-set', False )
422-
423- def places_select_function( self, info, store ):
424- if len( store.get_value( store.get_iter( info[0] ), 1 ) ) == 0:
425- return False
426- return True
427-
428- def raise_application( self ):
429- raise_cmd = self.app_instance.raise_command()
430- if raise_cmd is None:
431- return True
432-
433- print "Raise cmd: " + raise_cmd
434- self.window.present_with_time( int(time.time()) )
435- self.window.window.focus()
436- #self.window.present()
437-
438- if len( raise_cmd ) == 0:
439- return True
440-
441- print "Check if the main window is the only top level visible window"
442- for window in gtk.window_list_toplevels():
443- if window.get_property( 'visible' ):
444- if window != self.window:
445- print "Failed"
446- return True
447-
448- print "OK"
449-
450- folder_and_file = self.get_cmd_startup_folder_and_file( raise_cmd )
451- if folder_and_file is None:
452- return True
453-
454- folder_path, file_name, show_snapshots = folder_and_file
455-
456- #select now
457- self.snapshot_id = '/'
458- self.list_time_line.get_selection().select_iter( self.store_time_line.get_iter_first() )
459-
460- #select the specified file
461- self.folder_path = folder_path
462- self.update_folder_view( 1, file_name, show_snapshots )
463-
464- return True
465-
466- def update_backup_info( self, force_wait_lock = False ):
467- if None is self.glade.get_widget( 'btn_backup' ):
468- return True
469-
470- #print "forceWaitLock: %s" % forceWaitLock
471-
472- if force_wait_lock:
473- self.force_wait_lock_counter = 10
474-
475- busy = self.snapshots.is_busy()
476- if busy:
477- self.force_wait_lock_counter = 0
478-
479- if self.force_wait_lock_counter > 0:
480- self.force_wait_lock_counter = self.force_wait_lock_counter - 1
481-
482- fake_busy = busy or self.force_wait_lock_counter > 0
483- self.glade.get_widget( 'btn_backup' ).set_sensitive( not fake_busy )
484-
485- if fake_busy:
486- take_snapshot_message = None
487-
488- if busy:
489- take_snapshot_message = self.snapshots.get_take_snapshot_message()
490-
491- if take_snapshot_message is None:
492- take_snapshot_message = ( 0, '...' )
493-
494- if take_snapshot_message != self.last_take_snapshot_message:
495- self.last_take_snapshot_message = take_snapshot_message
496- self.status_bar.push( 0, _('Working:') + ' ' + self.last_take_snapshot_message[1].replace( '\n', ' ' ) )
497-
498- if not self.update_time_line:
499- self.update_time_line = True
500- elif self.update_time_line:
501- self.update_time_line = False
502- snapshots_list = self.snapshots_list
503-
504- self.fill_time_line()
505-
506- #print "New backup: %s" % self.lastBackupList
507- #print "Last backup: %s" % lastBackupList
508-
509- if snapshots_list != self.snapshots_list:
510- self.status_bar.push( 0, _('Done') )
511- else:
512- self.status_bar.push( 0, _('Done, no backup needed') )
513-
514- if not fake_busy:
515- self.last_take_snapshot_message = None
516-
517- return True
518-
519- def fill_places( self ):
520- self.store_places.clear()
521-
522- #add global places
523- self.store_places.append( [ "<b>%s</b>" % _('Global'), '', '' ] )
524- self.store_places.append( [ _('Root'), '/', gtk.STOCK_HARDDISK ] )
525- self.store_places.append( [ _('Home'), os.path.expanduser( '~' ), gtk.STOCK_HOME ] )
526-
527- #add bookmarks
528- rawbookmarks = ''
529-
530- try:
531- file = open( os.path.expanduser('~/.gtk-bookmarks') )
532- rawbookmarks = file.read()
533- file.close()
534- except:
535- pass
536-
537- bookmarks = []
538- for rawbookmark in rawbookmarks.split( '\n' ):
539- if rawbookmark.startswith( 'file://' ):
540- index = rawbookmark.find( ' ' )
541- if index > 0:
542- bookmarks.append( ( gnomevfs.unescape_string_for_display( rawbookmark[ 7 : index ] ), rawbookmark[ index + 1 : ] ) )
543- elif index < 0:
544- index = rawbookmark.rfind( '/' )
545- if index > 0:
546- bookmarks.append( ( gnomevfs.unescape_string_for_display( rawbookmark[ 7 : ] ), gnomevfs.unescape_string_for_display( rawbookmark[ index + 1 : ] ) ) )
547-
548- if len( bookmarks ) > 0:
549- self.store_places.append( [ "<b>%s</b>" % _('Bookmarks'), '', '' ] )
550- for bookmark in bookmarks:
551- self.store_places.append( [ bookmark[1], bookmark[0], self.icon_names.get_icon(bookmark[0]) ] )
552-
553- #add backup folders
554- include_folders = self.config.get_include_folders()
555- if len( include_folders ) > 0:
556- if len( include_folders ) > 0:
557- self.store_places.append( [ "<b>%s</b>" % _('Backup folders'), '', '' ] )
558- for folder in include_folders:
559- self.store_places.append( [ folder[0], folder[0], gtk.STOCK_SAVE ] )
560-
561- def fill_time_line( self, update_folder_view = True ):
562- current_selection = '/'
563- iter = self.list_time_line.get_selection().get_selected()[1]
564- if not iter is None:
565- current_selection = self.store_time_line.get_value( iter, 1 )
566-
567- self.store_time_line.clear()
568- self.store_time_line.append( [ gnometools.get_snapshot_display_markup( self.snapshots, '/' ), '/' ] )
569-
570- self.snapshots_list = self.snapshots.get_snapshots_list()
571-
572- groups = []
573- now = datetime.date.today()
574-
575- #today
576- date = now
577- groups.append( (_('Today'), self.snapshots.get_snapshot_id( date ), []) )
578-
579- #yesterday
580- date = now - datetime.timedelta( days = 1 )
581- groups.append( (_('Yesterday'), self.snapshots.get_snapshot_id( date ), []) )
582-
583- #this week
584- date = now - datetime.timedelta( days = now.weekday() )
585- groups.append( (_('This week'), self.snapshots.get_snapshot_id( date ), []) )
586-
587- #last week
588- date = now - datetime.timedelta( days = now.weekday() + 7 )
589- groups.append( (_('Last week'), self.snapshots.get_snapshot_id( date ), []) )
590-
591- #fill groups
592- for snapshot_id in self.snapshots_list:
593- found = False
594-
595- for group in groups:
596- if snapshot_id >= group[1]:
597- group[2].append( snapshot_id )
598- found = True
599- break
600-
601- if not found:
602- year = int( snapshot_id[ 0 : 4 ] )
603- month = int( snapshot_id[ 4 : 6 ] )
604- date = datetime.date( year, month, 1 )
605-
606- group_name = ''
607- if year == now.year:
608- group_name = date.strftime( '%B' ).capitalize()
609- else:
610- group_name = date.strftime( '%B, %Y' ).capitalize()
611-
612- groups.append( ( group_name, self.snapshots.get_snapshot_id( date ), [ snapshot_id ]) )
613-
614- #fill time_line list
615- for group in groups:
616- if len( group[2] ) > 0:
617- self.store_time_line.append( [ "<b>%s</b>" % group[0], '' ] );
618- for snapshot_id in group[2]:
619- self.store_time_line.append( [ gnometools.get_snapshot_display_markup( self.snapshots, snapshot_id ), snapshot_id ] )
620-
621- #select previous item
622- iter = self.store_time_line.get_iter_first()
623- while not iter is None:
624- if current_selection == self.store_time_line.get_value( iter, 1 ):
625- break
626- iter = self.store_time_line.iter_next( iter )
627-
628- changed = False
629- if iter is None:
630- changed = True
631- iter = self.store_time_line.get_iter_first()
632-
633- self.list_time_line.get_selection().select_iter( iter )
634-
635- if changed and update_folder_view:
636- self.update_folder_view( 2 )
637-
638- def on_close( self, *params ):
639- main_window_x, main_window_y = self.window.get_position()
640- main_window_width, main_window_height = self.window.get_size()
641- main_window_hpaned1 = self.glade.get_widget('hpaned1').get_position()
642- main_window_hpaned2 = self.glade.get_widget('hpaned2').get_position()
643-
644- self.config.set_int_value( 'gnome.main_window.x', main_window_x )
645- self.config.set_int_value( 'gnome.main_window.y', main_window_y )
646- self.config.set_int_value( 'gnome.main_window.width', main_window_width )
647- self.config.set_int_value( 'gnome.main_window.height', main_window_height )
648- self.config.set_int_value( 'gnome.main_window.hpaned1', main_window_hpaned1 )
649- self.config.set_int_value( 'gnome.main_window.hpaned2', main_window_hpaned2 )
650- self.config.set_str_value( 'gnome.last_path', self.folder_path )
651- self.config.set_bool_value( 'gnome.show_hidden_files', self.show_hidden_files )
652-
653- self.config.save()
654- self.window.destroy()
655- return True
656-
657- def on_list_time_line_cursor_changed( self, list ):
658- if list.get_selection().path_is_selected( list.get_cursor()[ 0 ] ):
659- self.update_folder_view( 2 )
660-
661- def on_list_places_cursor_changed( self, list ):
662- if list.get_selection().path_is_selected( list.get_cursor()[ 0 ] ):
663- iter = list.get_selection().get_selected()[1]
664- folder_path = self.store_places.get_value( iter, 1 )
665- if folder_path != self.folder_path:
666- self.folder_path = folder_path
667- self.update_folder_view( 0 )
668-
669- def on_list_folder_view_drag_data_get( self, widget, drag_context, selection_data, info, timestamp, user_param1 = None ):
670- iter = self.list_folder_view.get_selection().get_selected()[1]
671- if not iter is None:
672- path = self.store_folder_view.get_value( iter, 1 )
673- path = self.snapshots.get_snapshot_path_to( self.snapshot_id, path )
674- path = gnomevfs.escape_path_string( path )
675- selection_data.set_uris( [ 'file://' + path ] )
676-
677- def on_list_folder_view_button_press_event( self, list, event ):
678- if event.button != 3:
679- return
680-
681- if len( self.store_folder_view ) <= 0:
682- return
683-
684- path = self.list_folder_view.get_path_at_pos( int( event.x ), int( event.y ) )
685- if path is None:
686- return
687- path = path[0]
688-
689- self.list_folder_view.get_selection().select_path( path )
690- self.show_folder_view_menu_popup( self.list_folder_view, event.button, event.time )
691-
692- def on_list_folder_view_popup_menu( self, list ):
693- self.show_folder_view_menu_popup( list, 1, gtk.get_current_event_time() )
694-
695- def show_folder_view_menu_popup( self, list, button, time ):
696- iter = list.get_selection().get_selected()[1]
697- if iter is None:
698- return
699-
700- #print "popup-menu"
701- self.popup_menu = gtk.Menu()
702-
703- menu_item = gtk.ImageMenuItem( 'backintime.open' )
704- menu_item.set_image( gtk.image_new_from_icon_name( self.store_folder_view.get_value( iter, 2 ), gtk.ICON_SIZE_MENU ) )
705- menu_item.connect( 'activate', self.on_list_folder_view_open_item )
706- self.popup_menu.append( menu_item )
707-
708- self.popup_menu.append( gtk.SeparatorMenuItem() )
709-
710- menu_item = gtk.ImageMenuItem( 'backintime.copy' )
711- menu_item.set_image( gtk.image_new_from_stock( gtk.STOCK_COPY, gtk.ICON_SIZE_MENU ) )
712- menu_item.connect( 'activate', self.on_list_folder_view_copy_item )
713- self.popup_menu.append( menu_item )
714-
715- menu_item = gtk.ImageMenuItem( 'backintime.snapshots' )
716- menu_item.set_image( gtk.image_new_from_stock( gtk.STOCK_INDEX, gtk.ICON_SIZE_MENU ) )
717- menu_item.connect( 'activate', self.on_list_folder_view_snapshots_item )
718- self.popup_menu.append( menu_item )
719-
720- if len( self.snapshot_id ) > 1:
721- menu_item = gtk.ImageMenuItem( 'backintime.restore' )
722- menu_item.set_image( gtk.image_new_from_stock( gtk.STOCK_UNDELETE, gtk.ICON_SIZE_MENU ) )
723- menu_item.connect( 'activate', self.on_list_folder_view_restore_item )
724- self.popup_menu.append( menu_item )
725-
726- self.popup_menu.show_all()
727- self.popup_menu.popup( None, None, None, button, time )
728-
729- def on_list_folder_view_restore_item( self, widget, data = None ):
730- self.on_btn_restore_clicked( self.glade.get_widget( 'btn_restore' ) )
731-
732- def on_list_folder_view_copy_item( self, widget, data = None ):
733- self.on_btn_copy_clicked( self.glade.get_widget( 'btn_copy' ) )
734-
735- def on_list_folder_view_snapshots_item( self, widget, data = None ):
736- self.on_btn_snapshots_clicked( self.glade.get_widget( 'btn_snapshots' ) )
737-
738- def on_list_folder_view_open_item( self, widget, data = None ):
739- iter = self.list_folder_view.get_selection().get_selected()[1]
740- if iter is None:
741- return
742-
743- path = self.store_folder_view.get_value( iter, 1 )
744- path = self.snapshots.get_snapshot_path_to( self.snapshot_id, path )
745- cmd = "gnome-open \"%s\" &" % path
746- print cmd
747- os.system( cmd )
748-
749- def on_list_folder_view_row_activated( self, list, path, column ):
750- iter = list.get_selection().get_selected()[1]
751- path = self.store_folder_view.get_value( iter, 1 )
752-
753- #directory
754- if 0 == self.store_folder_view.get_value( iter, 3 ):
755- self.folder_path = path
756- self.update_folder_view( 1 )
757- return
758-
759- #file
760- path = self.snapshots.get_snapshot_path_to( self.snapshot_id, path )
761- cmd = "gnome-open \"%s\" &" % path
762- print cmd
763- os.system( cmd )
764-
765- def on_btn_fodler_up_clicked( self, button ):
766- if len( self.folder_path ) <= 1:
767- return
768-
769- index = self.folder_path.rfind( '/' )
770- if index < 1:
771- parent_path = "/"
772- else:
773- parent_path = self.folder_path[ : index ]
774-
775- self.folder_path = parent_path
776- self.update_folder_view( 1 )
777-
778- def on_btn_restore_clicked( self, button ):
779- iter = self.list_folder_view.get_selection().get_selected()[1]
780- if not iter is None:
781- button.set_sensitive( False )
782- gnometools.run_gtk_update_loop()
783- self.snapshots.restore( self.snapshot_id, self.store_folder_view.get_value( iter, 1 ) )
784- button.set_sensitive( True )
785-
786- def on_btn_copy_clicked( self, button ):
787- iter = self.list_folder_view.get_selection().get_selected()[1]
788- if iter is None:
789- return
790-
791- path = self.store_folder_view.get_value( iter, 1 )
792- path = self.snapshots.get_snapshot_path_to( self.snapshot_id, path )
793-
794- clipboardtools.clipboard_copy_path( path )
795-
796- def on_btn_hidden_files_toggled( self, button ):
797- if self.folder_path is None:
798- return
799-
800- self.show_hidden_files = button.get_active()
801- self.update_folder_view( 0 )
802-
803- def on_btn_snapshots_clicked( self, button ):
804- iter = self.list_folder_view.get_selection().get_selected()[1]
805- if iter is None:
806- return
807-
808- path = self.store_folder_view.get_value( iter, 1 )
809- icon_name = self.store_folder_view.get_value( iter, 2 )
810-
811- retVal = snapshotsdialog.SnapshotsDialog( self.snapshots, self.window, path, self.snapshots_list, self.snapshot_id, icon_name ).run()
812-
813- #select the specified file
814- if not retVal is None:
815- iter = self.store_time_line.get_iter_first()
816- while not iter is None:
817- snapshot_id = self.store_time_line.get_value( iter, 1 )
818- if snapshot_id == retVal:
819- break
820- iter = self.store_time_line.iter_next( iter )
821-
822- if not iter is None:
823- self.list_time_line.get_selection().select_iter( iter )
824- self.update_folder_view( 2 )
825-
826- def on_btn_about_clicked( self, button ):
827- AboutDialog( self.config, self.window ).run()
828-
829- def on_help( self ):
830- gnome.help_display('backintime')
831-
832- def on_btn_help_clicked( self, button ):
833- self.on_help()
834-
835- def on_btn_link_clicked( self, button ):
836- os.system( "gnome-open http://backintime.le-web.org &" )
837-
838- def on_key_release_event( self, widget, event ):
839- if 'F1' == gtk.gdk.keyval_name( event.keyval ) and ( event.state & (gtk.gdk.CONTROL_MASK | gtk.gdk.MOD1_MASK) ) == 0:
840- self.on_help()
841-
842- def on_btn_settings_clicked( self, button ):
843- snapshots_path = self.config.get_snapshots_path()
844- include_folders = self.config.get_include_folders()
845-
846- settingsdialog.SettingsDialog( self.config, self ).run()
847-
848- if snapshots_path != self.config.get_snapshots_path() or include_folders != self.config.get_include_folders():
849- self.update_all( False )
850-
851- def on_btn_snapshot_name_clicked( self, button ):
852- iter = self.list_time_line.get_selection().get_selected()[1]
853- if iter is None:
854- return
855-
856- snapshot_id = self.store_time_line.get_value( iter, 1 )
857- if len( snapshot_id ) <= 1:
858- return
859-
860- old_name = self.snapshots.get_snapshot_name( snapshot_id )
861- new_name = messagebox.text_input_dialog( self.window, self.config, _('Snapshot Name'), old_name )
862- if new_name is None:
863- return
864-
865- if old_name == new_name:
866- return
867-
868- self.snapshots.set_snapshot_name( snapshot_id, new_name )
869- self.store_time_line.set_value( iter, 0, gnometools.get_snapshot_display_markup( self.snapshots, snapshot_id ) )
870-
871- def on_btn_remove_snapshot_clicked( self, button ):
872- iter = self.list_time_line.get_selection().get_selected()[1]
873- if iter is None:
874- return
875-
876- snapshot_id = self.store_time_line.get_value( iter, 1 )
877- if len( snapshot_id ) <= 1:
878- return
879-
880- if gtk.RESPONSE_YES == messagebox.show_question( self.window, self.config, _('Are you sure you want to remove the snapshot:\n<b>%s</b>') % self.snapshots.get_snapshot_display_name( snapshot_id ) ):
881- print "Remove Snapshot: %s" % snapshot_id
882- self.snapshots.remove_snapshot( snapshot_id )
883- self.fill_time_line()
884-
885- def on_btn_backup_clicked( self, button ):
886- button.set_sensitive( False )
887- self.updatetime_line = True
888-
889- if self.snapshots.is_busy():
890- self.update_backup_info()
891- return
892-
893- backintime.take_snapshot_now_async( self.config )
894- self.update_backup_info( True )
895-
896- def on_btn_update_snapshots_clicked( self, button ):
897- self.fill_time_line( False )
898- self.update_folder_view( 2 )
899-
900- def update_folder_view( self, changed_from, selected_file = None, show_snapshots = False ): #0 - places, 1 - folder view, 2 - time_line
901- #update backup time
902- if 2 == changed_from:
903- iter = self.list_time_line.get_selection().get_selected()[1]
904- self.snapshot_id = self.store_time_line.get_value( iter, 1 )
905- #self.lblTime.set_markup( "<b>%s</b>" % backupTime )
906-
907- tooltip = ''
908- text = ''
909- if len( self.snapshot_id ) > 1:
910- name = self.snapshots.get_snapshot_display_id( self.snapshot_id )
911- text = _('Snapshot: %s') % name
912- tooltip = _('View the snapshot made at %s') % name
913- else:
914- tooltip = _('View the current disk content')
915- text = _('Now')
916-
917- self.lbl_snapshot.set_markup( ' <b>' + text + '</b> ' )
918- self.lbl_snapshot.set_tooltip_text( tooltip )
919-
920- #update selected places item
921- if 1 == changed_from:
922- iter = self.store_places.get_iter_first()
923- while not iter is None:
924- place_path = self.store_places.get_value( iter, 1 )
925- if place_path == self.folder_path:
926- break
927- iter = self.store_places.iter_next( iter )
928-
929- if iter is None:
930- self.list_places.get_selection().unselect_all()
931- else:
932- self.list_places.get_selection().select_iter( iter )
933-
934- #update folder view
935-
936- full_path = self.snapshots.get_snapshot_path_to( self.snapshot_id, self.folder_path )
937- all_files = []
938- files = []
939- folder_exists = os.path.isdir( full_path )
940-
941- if folder_exists:
942- try:
943- all_files = os.listdir( full_path )
944- all_files.sort()
945- except:
946- pass
947-
948- files = []
949- for file in all_files:
950- if len( file ) == 0:
951- continue
952-
953- if not self.show_hidden_files:
954- if file[ 0 ] == '.':
955- continue
956- if file[ -1 ] == '~':
957- continue
958-
959- path = os.path.join( full_path, file )
960-
961- file_size = -1
962- file_date = -1
963-
964- try:
965- file_stat = os.stat( path )
966- file_size = file_stat[stat.ST_SIZE]
967- file_date = file_stat[stat.ST_MTIME]
968- except:
969- pass
970-
971- #format size
972- file_size_int = file_size
973- if file_size_int < 0:
974- file_size_int = 0
975-
976- if file_size < 0:
977- file_size = 'unknown'
978- elif file_size < 1024:
979- file_size = str( file_size ) + ' bytes'
980- elif file_size < 1024 * 1024:
981- file_size = file_size / 1024
982- file_size = str( file_size ) + ' KB'
983- elif file_size < 1024 * 1024 * 1024:
984- file_size = file_size / ( 1024 * 1024 )
985- file_size = str( file_size ) + ' MB'
986- else:
987- file_size = file_size / ( 1024 * 1024 * 1024 )
988- file_size = str( file_size ) + ' GB'
989-
990- #format date
991- if file_date < 0:
992- file_date = 'unknown'
993- else:
994- file_date = datetime.datetime.fromtimestamp(file_date).isoformat(' ')
995-
996- if os.path.isdir( path ):
997- files.append( [ file, file_size, file_date, self.icon_names.get_icon(path), file_size_int, 0 ] )
998- else:
999- files.append( [ file, file_size, file_date, self.icon_names.get_icon(path), file_size_int, 1 ] )
1000-
1001- #try to keep old selected file
1002- if selected_file is None:
1003- selected_file = ''
1004- iter = self.list_folder_view.get_selection().get_selected()[1]
1005- if not iter is None:
1006- selected_file = self.store_folder_view.get_value( iter, 1 )
1007-
1008- self.list_folder_view_widget.show()
1009- self.list_folder_view_shadow.hide()
1010- else:
1011- self.list_folder_view_widget.hide()
1012- self.list_folder_view_shadow.show()
1013-
1014- #populate the list
1015- self.store_folder_view.clear()
1016-
1017- selected_iter = None
1018- for item in files:
1019- rel_path = os.path.join( self.folder_path, item[0] )
1020- new_iter = self.store_folder_view.append( [ item[0], rel_path, item[3], item[5], item[1], item[2], item[4] ] )
1021- if selected_file == rel_path:
1022- selected_iter = new_iter
1023-
1024- #select old item or the first item
1025- if len( files ) > 0:
1026- if selected_iter is None:
1027- selected_iter = self.store_folder_view.get_iter_first()
1028- self.list_folder_view.get_selection().select_iter( selected_iter )
1029- self.list_folder_view.drag_source_set( gtk.gdk.BUTTON1_MASK | gtk.gdk.BUTTON3_MASK, gtk.target_list_add_uri_targets(), gtk.gdk.ACTION_COPY )
1030- else:
1031- self.list_folder_view.drag_source_unset()
1032-
1033- #update folderup button state
1034- self.glade.get_widget( 'btn_folder_up' ).set_sensitive( len( self.folder_path ) > 1 )
1035-
1036- #update restore button state
1037- self.glade.get_widget( 'btn_restore' ).set_sensitive( len( self.snapshot_id ) > 1 and len( self.store_folder_view ) > 0 )
1038-
1039- #update remove/name snapshot buttons
1040- self.glade.get_widget( 'btn_snapshot_name' ).set_sensitive( len( self.snapshot_id ) > 1 )
1041- self.glade.get_widget( 'btn_remove_snapshot' ).set_sensitive( len( self.snapshot_id ) > 1 )
1042-
1043- #update copy button state
1044- self.glade.get_widget( 'btn_copy' ).set_sensitive( len( self.store_folder_view ) > 0 )
1045-
1046- #update snapshots button state
1047- self.glade.get_widget( 'btn_snapshots' ).set_sensitive( len( self.store_folder_view ) > 0 )
1048-
1049- #display current folder
1050- self.glade.get_widget( 'edit_current_path' ).set_text( self.folder_path )
1051-
1052- #show snapshots
1053- if show_snapshots:
1054- self.on_btn_snapshots_clicked( None )
1055+class AboutDialog(gtk.AboutDialog):
1056+
1057+ def __init__( self, config, parent ):
1058+
1059+ gtk.AboutDialog.__init__( self )
1060+
1061+ self.connect( 'close', self.on_close )
1062+ self.connect( 'response', self.on_close )
1063+
1064+ self.set_transient_for( parent )
1065+
1066+ self.set_name( config.APP_NAME )
1067+ self.set_version( config.VERSION )
1068+ self.set_copyright( 'Copyright (C) 2008-2009 Oprea Dan' )
1069+ self.set_website( 'http://backintime.le-web.org' )
1070+ self.set_website_label( 'http://backintime.le-web.org' )
1071+ self.set_license( config.get_license() )
1072+ authors = config.get_authors()
1073+ if not authors is None:
1074+ self.set_authors( authors.split( '\n' ) )
1075+
1076+ #extra_translations = _('about-translators').strip()
1077+ #if extra_translations is None:
1078+ # extra_translations = ''
1079+ #elif extra_translations == 'about-translators':
1080+ # extra_translations = ''
1081+ #
1082+ #self.set_translator_credits( config.get_translations() + extra_translations )
1083+ self.set_translator_credits( config.get_translations() )
1084+
1085+ def on_close( self, *params ):
1086+ self.destroy()
1087+
1088+
1089+class MainWindow(object):
1090+
1091+ def __init__( self, config, app_instance ):
1092+
1093+ self.config = config
1094+ self.app_instance = app_instance
1095+ self.snapshots = snapshots.Snapshots( config )
1096+ self.special_background_color = 'lightblue'
1097+ self.popup_menu = None
1098+
1099+ self.folder_path = None
1100+ self.snapshot_id = ''
1101+
1102+ self.last_take_snapshot_message = None
1103+
1104+
1105+ builder = gtk.Builder()
1106+ self.builder = builder
1107+
1108+ glade_file = os.path.join(self.config.get_app_path(), 'gnome',
1109+ 'mainwindow.glade')
1110+
1111+ builder.add_from_file(glade_file)
1112+
1113+ signals = {
1114+ 'on_MainWindow_destroy' : gtk.main_quit,
1115+ 'on_MainWindow_delete_event' : self.on_close,
1116+ 'on_MainWindow_key_release_event': self.on_key_release_event,
1117+ 'on_btn_exit_clicked' : self.on_close,
1118+ 'on_btn_link_clicked' : self.on_btn_link_clicked,
1119+ 'on_btn_help_clicked' : self.on_btn_help_clicked,
1120+ 'on_btn_about_clicked' : self.on_btn_about_clicked,
1121+ 'on_btn_settings_clicked' : self.on_btn_settings_clicked,
1122+ 'on_btn_backup_clicked' : self.on_btn_backup_clicked,
1123+ 'on_btn_update_snapshots_clicked' : self.on_btn_update_snapshots_clicked,
1124+ 'on_btn_snapshot_name_clicked' : self.on_btn_snapshot_name_clicked,
1125+ 'on_btn_remove_snapshot_clicked' : self.on_btn_remove_snapshot_clicked,
1126+ 'on_btn_restore_clicked' : self.on_btn_restore_clicked,
1127+ 'on_btn_copy_clicked' : self.on_btn_copy_clicked,
1128+ 'on_btn_snapshots_clicked' : self.on_btn_snapshots_clicked,
1129+ 'on_btn_hidden_files_toggled' : self.on_btn_hidden_files_toggled,
1130+ 'on_list_places_cursor_changed' : self.on_list_places_cursor_changed,
1131+ 'on_list_time_line_cursor_changed' : self.on_list_time_line_cursor_changed,
1132+ 'on_btn_folder_up_clicked' : self.on_btn_fodler_up_clicked,
1133+ 'on_list_folder_view_row_activated' : self.on_list_folder_view_row_activated,
1134+ 'on_list_folder_view_popup_menu' : self.on_list_folder_view_popup_menu,
1135+ 'on_list_folder_view_button_press_event': self.on_list_folder_view_button_press_event,
1136+ 'on_list_folder_view_drag_data_get': self.on_list_folder_view_drag_data_get,
1137+ 'on_combo_profiles_changed': self.on_combo_profiles_changed,
1138+ }
1139+
1140+ builder.connect_signals(signals)
1141+
1142+ self.window = self.builder.get_object( 'MainWindow' )
1143+ self.window.set_title( self.config.APP_NAME )
1144+
1145+ #icons
1146+ self.icon_names = fileicons.GnomeFileIcons()
1147+
1148+ #fix a glade bug
1149+ self.builder.get_object( 'btn_current_path' ).set_expand( True )
1150+ #self.builder.get_object( 'tb_sep_item' ).set_expand( True )
1151+
1152+ #profiles
1153+ self.disable_combo_changed = True
1154+ self.first_update_all = True
1155+
1156+ self.store_profiles = gtk.ListStore( str, str )
1157+
1158+ self.combo_profiles = self.builder.get_object( 'combo_profiles' )
1159+
1160+ text_renderer = gtk.CellRendererText()
1161+ self.combo_profiles.pack_start( text_renderer, True )
1162+ self.combo_profiles.add_attribute( text_renderer, 'text', 0 )
1163+
1164+ self.combo_profiles.set_model( self.store_profiles )
1165+
1166+ self.disable_combo_changed = False
1167+
1168+ #lbl snapshot
1169+ self.lbl_snapshot = self.builder.get_object( 'lbl_snapshot' )
1170+
1171+ #status bar
1172+ self.status_bar = self.builder.get_object( 'status_bar' )
1173+ self.status_bar.push( 0, _('Done') )
1174+
1175+ #show hidden files
1176+ self.show_hidden_files = self.config.get_bool_value( 'gnome.show_hidden_files', False )
1177+ self.btn_hidden_files = self.builder.get_object( 'btn_hidden_files' )
1178+ self.btn_hidden_files.set_active( self.show_hidden_files )
1179+ #self.btn_hidden_files.set_label( _('Hidden files') ) #!!!
1180+
1181+ #setup places view
1182+ self.list_places = self.builder.get_object( 'list_places' )
1183+
1184+ pix_renderer = gtk.CellRendererPixbuf()
1185+ text_renderer = gtk.CellRendererText()
1186+
1187+ column = gtk.TreeViewColumn( _('Shortcuts') )
1188+ column.pack_start( pix_renderer, False )
1189+ column.pack_end( text_renderer, True )
1190+ column.add_attribute( pix_renderer, 'icon-name', 2 )
1191+ column.add_attribute( text_renderer, 'markup', 0 )
1192+ column.set_cell_data_func( pix_renderer, self.places_pix_renderer_function, None )
1193+ column.set_cell_data_func( text_renderer, self.places_text_renderer_function, None )
1194+ #column.set_alignment( 0.5 )
1195+ self.list_places.append_column( column )
1196+
1197+ #name, icon, path
1198+ self.store_places = gtk.ListStore( str, str, str )
1199+ self.list_places.set_model( self.store_places )
1200+ self.list_places.get_selection().set_select_function( self.places_select_function, self.store_places )
1201+
1202+ #setup folder view
1203+ self.list_folder_view_widget = self.builder.get_object( 'list_folder_view_widget' )
1204+ self.list_folder_view_shadow = self.builder.get_object( 'list_folder_view_shadow' )
1205+ self.list_folder_view = self.builder.get_object( 'list_folder_view' )
1206+
1207+ pix_renderer = gtk.CellRendererPixbuf()
1208+ text_renderer = gtk.CellRendererText()
1209+
1210+ column = gtk.TreeViewColumn( _('Name') )
1211+ column.pack_start( pix_renderer, False )
1212+ column.pack_end( text_renderer, True )
1213+ column.add_attribute( pix_renderer, 'icon-name', 2 )
1214+ column.add_attribute( text_renderer, 'markup', 0 )
1215+ column.set_expand( True )
1216+ column.set_sizing( gtk.TREE_VIEW_COLUMN_AUTOSIZE )
1217+ column.set_sort_column_id( 0 )
1218+ self.list_folder_view.append_column( column )
1219+
1220+ text_renderer = gtk.CellRendererText()
1221+ column = gtk.TreeViewColumn( _('Size') )
1222+ column.pack_end( text_renderer, True )
1223+ column.add_attribute( text_renderer, 'markup', 4 )
1224+ column.set_sort_column_id( 1 )
1225+ self.list_folder_view.append_column( column )
1226+
1227+ text_renderer = gtk.CellRendererText()
1228+ column = gtk.TreeViewColumn( _('Date') )
1229+ column.pack_end( text_renderer, True )
1230+ column.add_attribute( text_renderer, 'markup', 5 )
1231+ column.set_sort_column_id( 2 )
1232+ self.list_folder_view.append_column( column )
1233+
1234+ # display name, relative path, icon_name, type (0 - directory, 1 - file), size (str), date, size (int)
1235+ self.store_folder_view = gtk.ListStore( str, str, str, int, str, str, int )
1236+ self.store_folder_view.set_sort_func( 0, self.sort_folder_view_by_column, 0 ) #name
1237+ self.store_folder_view.set_sort_func( 1, self.sort_folder_view_by_column, 6 ) #size
1238+ self.store_folder_view.set_sort_func( 2, self.sort_folder_view_by_column, 5 ) #date
1239+ self.store_folder_view.set_sort_column_id( 0, gtk.SORT_ASCENDING )
1240+
1241+ self.list_folder_view.set_model( self.store_folder_view )
1242+
1243+ #setup time line view
1244+ self.list_time_line = self.builder.get_object( 'list_time_line' )
1245+
1246+ text_renderer = gtk.CellRendererText()
1247+ column = gtk.TreeViewColumn( _('Snapshots'), text_renderer, markup = 0 )
1248+ column.set_cell_data_func( text_renderer, self.places_text_renderer_function, None )
1249+ self.list_time_line.append_column( column )
1250+
1251+ #display name, id
1252+ self.store_time_line = gtk.ListStore( str, str )
1253+ self.list_time_line.set_model( self.store_time_line )
1254+ self.list_time_line.get_selection().set_select_function( self.places_select_function, self.store_time_line )
1255+ self.update_time_line = False
1256+
1257+ #calculate specialBackgroundColor
1258+ style = self.list_time_line.get_style()
1259+ bg1 = style.bg[gtk.STATE_NORMAL]
1260+ bg2 = style.bg[gtk.STATE_SELECTED]
1261+ self.special_background_color = gtk.gdk.Color( (2 * bg1.red + bg2.red) / 3, (2 * bg1.green + bg2.green) / 3,(2 * bg1.blue + bg2.blue) / 3 ).to_string()
1262+
1263+ #restore size & position
1264+ main_window_x = self.config.get_int_value( 'gnome.main_window.x', -1 )
1265+ main_window_y = self.config.get_int_value( 'gnome.main_window.y', -1 )
1266+ if main_window_x >= 0 and main_window_y >= 0:
1267+ self.window.move( main_window_x, main_window_y )
1268+
1269+ main_window_width = self.config.get_int_value( 'gnome.main_window.width', -1 )
1270+ main_window_height = self.config.get_int_value( 'gnome.main_window.height', -1 )
1271+ if main_window_width > 0 and main_window_height > 0:
1272+ self.window.resize( main_window_width, main_window_height )
1273+
1274+ main_window_hpaned1 = self.config.get_int_value( 'gnome.main_window.hpaned1', -1 )
1275+ main_window_hpaned2 = self.config.get_int_value( 'gnome.main_window.hpaned2', -1 )
1276+ if main_window_hpaned1 > 0 and main_window_hpaned2 > 0:
1277+ self.builder.get_object('hpaned1').set_position( main_window_hpaned1 )
1278+ self.builder.get_object('hpaned2').set_position( main_window_hpaned2 )
1279+
1280+ #prepare popup menu ids
1281+ gtk.stock_add(
1282+ [ ('backintime.open', _('Open'), 0, 0, 'backintime' ),
1283+ ('backintime.copy', _('Copy'), 0, 0, 'backintime' ),
1284+ ('backintime.snapshots', _('Snapshots'), 0, 0, 'backintime' ),
1285+ ('backintime.diff', _('Diff'), 0, 0, 'backintime' ),
1286+ ('backintime.restore', _('Restore'), 0, 0, 'backintime' ) ] )
1287+
1288+ #show main window
1289+ self.window.show()
1290+ gnometools.run_gtk_update_loop()
1291+
1292+ self.force_wait_lock_counter = 0
1293+ gobject.timeout_add( 1000, self.raise_application )
1294+
1295+ if not self.config.is_configured():
1296+ settingsdialog.SettingsDialog( self.config, self ).run()
1297+
1298+ if not self.config.is_configured():
1299+ return
1300+
1301+ if not self.config.can_backup():
1302+ messagebox.show_error( self.window, self.config, _('Can\'t find snapshots folder.\nIf it is on a removable drive please plug it and then press OK') )
1303+
1304+ self.update_profiles()
1305+ self.update_backup_info()
1306+ gobject.timeout_add( 1000, self.update_backup_info )
1307+
1308+ def on_combo_profiles_changed( self, *params ):
1309+ if self.disable_combo_changed:
1310+ return
1311+
1312+ iter = self.combo_profiles.get_active_iter()
1313+ if iter is None:
1314+ return
1315+
1316+ first_update_all = self.first_update_all
1317+
1318+ profile_id = self.store_profiles.get_value( iter, 1 )
1319+ if not first_update_all and profile_id == self.config.get_current_profile():
1320+ return
1321+
1322+ self.config.set_current_profile( profile_id )
1323+ self.first_update_all = False
1324+ self.update_all( first_update_all )
1325+
1326+ def update_profiles( self ):
1327+ self.disable_combo_changed = True
1328+
1329+ profiles = self.config.get_profiles_sorted_by_name()
1330+
1331+ select_iter = None
1332+ self.store_profiles.clear()
1333+
1334+ for profile_id in profiles:
1335+ iter = self.store_profiles.append( [ self.config.get_profile_name( profile_id ), profile_id ] )
1336+ if profile_id == self.config.get_current_profile():
1337+ select_iter = iter
1338+
1339+
1340+ self.disable_combo_changed = False
1341+
1342+ if not select_iter is None:
1343+ self.combo_profiles.set_active_iter( select_iter )
1344+
1345+ #self.update_all( True )
1346+
1347+ def sort_folder_view_by_column( self, treemodel, iter1, iter2, column ):
1348+ if 0 == column:
1349+ ascending = 1
1350+ if self.store_folder_view.get_sort_column_id()[1] != gtk.SORT_ASCENDING:
1351+ ascending = -1
1352+
1353+ type1 = self.store_folder_view.get_value( iter1, 3 )
1354+ type2 = self.store_folder_view.get_value( iter2, 3 )
1355+
1356+ if type1 == 0 and type2 != 0:
1357+ return -1 * ascending
1358+
1359+ if type1 != 0 and type2 == 0:
1360+ return 1 * ascending
1361+
1362+ data1 = self.store_folder_view.get_value( iter1, column )
1363+ data2 = self.store_folder_view.get_value( iter2, column )
1364+
1365+ if type(data1) is str:
1366+ data1 = data1.upper()
1367+
1368+ if type(data2) is str:
1369+ data2 = data2.upper()
1370+
1371+ #print "sort_folder_view_by_column: " + str( data1 ) + " - " + str( data2 )
1372+
1373+ if data1 < data2:
1374+ return -1
1375+
1376+ if data1 > data2:
1377+ return 1
1378+
1379+ return 0
1380+
1381+
1382+ def get_default_startup_folder_and_file( self ):
1383+ last_path = self.config.get_str_value( 'gnome.last_path', '' )
1384+ if len(last_path) > 0 and os.path.isdir(last_path):
1385+ return ( last_path, None, False )
1386+ return ( '/', None, False )
1387+
1388+ def get_cmd_startup_folder_and_file( self, cmd ):
1389+ if cmd is None:
1390+ cmd = self.app_instance.raise_cmd
1391+
1392+ if len( cmd ) < 1:
1393+ return None
1394+
1395+ path = None
1396+ show_snapshots = False
1397+
1398+ for arg in cmd.split( '\n' ):
1399+ if len( arg ) < 1:
1400+ continue
1401+ if arg == '-s' or arg == '--snapshots':
1402+ show_snapshots = True
1403+ continue
1404+ if arg[0] == '-':
1405+ continue
1406+ if path is None:
1407+ path = arg
1408+
1409+ if path is None:
1410+ return None
1411+
1412+ if len( path ) < 1:
1413+ return None
1414+
1415+ path = os.path.expanduser( path )
1416+ path = os.path.abspath( path )
1417+
1418+ if os.path.isdir( path ):
1419+ if len( path ) < 1:
1420+ show_snapshots = False
1421+
1422+ if show_snapshots:
1423+ return ( os.path.dirname( path ), path, True )
1424+ else:
1425+ return ( path, '', False )
1426+
1427+ if os.path.isfile( path ):
1428+ return ( os.path.dirname( path ), path, show_snapshots )
1429+
1430+ return None
1431+
1432+ def get_startup_folder_and_file( self, cmd = None ):
1433+ startup_folder = self.get_cmd_startup_folder_and_file( cmd )
1434+ if startup_folder is None:
1435+ return self.get_default_startup_folder_and_file()
1436+ return startup_folder
1437+
1438+ def update_all( self, init ):
1439+ #fill lists
1440+ selected_file = None
1441+ show_snapshots = False
1442+ if init:
1443+ self.folder_path, selected_file, show_snapshots = self.get_startup_folder_and_file()
1444+ self.snapshot_id = '/'
1445+ self.snapshots_list = []
1446+
1447+ self.fill_places()
1448+ self.fill_time_line( False )
1449+ self.update_folder_view( 1, selected_file, show_snapshots )
1450+
1451+ def places_pix_renderer_function( self, column, renderer, model, iter, user_data ):
1452+ if len( model.get_value( iter, 1 ) ) == 0:
1453+ renderer.set_property( 'visible', False )
1454+ else:
1455+ renderer.set_property( 'visible', True )
1456+
1457+ def places_text_renderer_function( self, column, renderer, model, iter, user_data ):
1458+ if len( model.get_value( iter, 1 ) ) == 0:
1459+ renderer.set_property( 'cell-background-set', True )
1460+ renderer.set_property( 'cell-background', self.special_background_color )
1461+ else:
1462+ renderer.set_property( 'cell-background-set', False )
1463+
1464+ def places_select_function( self, info, store ):
1465+ if len( store.get_value( store.get_iter( info[0] ), 1 ) ) == 0:
1466+ return False
1467+ return True
1468+
1469+ def raise_application( self ):
1470+ raise_cmd = self.app_instance.raise_command()
1471+ if raise_cmd is None:
1472+ return True
1473+
1474+ print "Raise cmd: " + raise_cmd
1475+ self.window.present_with_time( int(time.time()) )
1476+ self.window.window.focus()
1477+ #self.window.present()
1478+
1479+ if len( raise_cmd ) == 0:
1480+ return True
1481+
1482+ print "Check if the main window is the only top level visible window"
1483+ for window in gtk.window_list_toplevels():
1484+ if window.get_property( 'visible' ):
1485+ if window != self.window:
1486+ print "Failed"
1487+ return True
1488+
1489+ print "OK"
1490+
1491+ folder_and_file = self.get_cmd_startup_folder_and_file( raise_cmd )
1492+ if folder_and_file is None:
1493+ return True
1494+
1495+ folder_path, file_name, show_snapshots = folder_and_file
1496+
1497+ #select now
1498+ self.snapshot_id = '/'
1499+ self.list_time_line.get_selection().select_iter( self.store_time_line.get_iter_first() )
1500+
1501+ #select the specified file
1502+ self.folder_path = folder_path
1503+ self.update_folder_view( 1, file_name, show_snapshots )
1504+
1505+ return True
1506+
1507+ def update_backup_info( self, force_wait_lock = False ):
1508+ if None is self.builder.get_object( 'btn_backup' ):
1509+ return True
1510+
1511+ #print "forceWaitLock: %s" % forceWaitLock
1512+
1513+ if force_wait_lock:
1514+ self.force_wait_lock_counter = 10
1515+
1516+ busy = self.snapshots.is_busy()
1517+ if busy:
1518+ self.force_wait_lock_counter = 0
1519+
1520+ if self.force_wait_lock_counter > 0:
1521+ self.force_wait_lock_counter = self.force_wait_lock_counter - 1
1522+
1523+ fake_busy = busy or self.force_wait_lock_counter > 0
1524+ self.builder.get_object( 'btn_backup' ).set_sensitive( not fake_busy )
1525+
1526+ if fake_busy:
1527+ take_snapshot_message = None
1528+
1529+ if busy:
1530+ take_snapshot_message = self.snapshots.get_take_snapshot_message()
1531+
1532+ if take_snapshot_message is None:
1533+ take_snapshot_message = ( 0, '...' )
1534+
1535+ if take_snapshot_message != self.last_take_snapshot_message:
1536+ self.last_take_snapshot_message = take_snapshot_message
1537+ self.status_bar.push( 0, _('Working:') + ' ' + self.last_take_snapshot_message[1].replace( '\n', ' ' ) )
1538+
1539+ if not self.update_time_line:
1540+ self.update_time_line = True
1541+ elif self.update_time_line:
1542+ self.update_time_line = False
1543+ snapshots_list = self.snapshots_list
1544+
1545+ self.fill_time_line()
1546+
1547+ #print "New backup: %s" % self.lastBackupList
1548+ #print "Last backup: %s" % lastBackupList
1549+
1550+ if snapshots_list != self.snapshots_list:
1551+ self.status_bar.push( 0, _('Done') )
1552+ else:
1553+ self.status_bar.push( 0, _('Done, no backup needed') )
1554+
1555+ if not fake_busy:
1556+ self.last_take_snapshot_message = None
1557+
1558+ return True
1559+
1560+ def fill_places( self ):
1561+ self.store_places.clear()
1562+
1563+ #add global places
1564+ self.store_places.append( [ "<b>%s</b>" % _('Global'), '', '' ] )
1565+ self.store_places.append( [ _('Root'), '/', gtk.STOCK_HARDDISK ] )
1566+ self.store_places.append( [ _('Home'), os.path.expanduser( '~' ), gtk.STOCK_HOME ] )
1567+
1568+ #add bookmarks
1569+ rawbookmarks = ''
1570+
1571+ try:
1572+ file = open( os.path.expanduser('~/.gtk-bookmarks') )
1573+ rawbookmarks = file.read()
1574+ file.close()
1575+ except:
1576+ pass
1577+
1578+ bookmarks = []
1579+ for rawbookmark in rawbookmarks.split( '\n' ):
1580+ if rawbookmark.startswith( 'file://' ):
1581+ index = rawbookmark.find( ' ' )
1582+ if index > 0:
1583+ bookmarks.append( ( gnomevfs.unescape_string_for_display( rawbookmark[ 7 : index ] ), rawbookmark[ index + 1 : ] ) )
1584+ elif index < 0:
1585+ index = rawbookmark.rfind( '/' )
1586+ if index > 0:
1587+ bookmarks.append( ( gnomevfs.unescape_string_for_display( rawbookmark[ 7 : ] ), gnomevfs.unescape_string_for_display( rawbookmark[ index + 1 : ] ) ) )
1588+
1589+ if len( bookmarks ) > 0:
1590+ self.store_places.append( [ "<b>%s</b>" % _('Bookmarks'), '', '' ] )
1591+ for bookmark in bookmarks:
1592+ self.store_places.append( [ bookmark[1], bookmark[0], self.icon_names.get_icon(bookmark[0]) ] )
1593+
1594+ #add backup folders
1595+ include_folders = self.config.get_include_folders()
1596+ if len( include_folders ) > 0:
1597+ if len( include_folders ) > 0:
1598+ self.store_places.append( [ "<b>%s</b>" % _('Backup folders'), '', '' ] )
1599+ for folder in include_folders:
1600+ self.store_places.append( [ folder[0], folder[0], gtk.STOCK_SAVE ] )
1601+
1602+ def fill_time_line( self, update_folder_view = True ):
1603+ current_selection = '/'
1604+ iter = self.list_time_line.get_selection().get_selected()[1]
1605+ if not iter is None:
1606+ current_selection = self.store_time_line.get_value( iter, 1 )
1607+
1608+ self.store_time_line.clear()
1609+ self.store_time_line.append( [ gnometools.get_snapshot_display_markup( self.snapshots, '/' ), '/' ] )
1610+
1611+ self.snapshots_list = self.snapshots.get_snapshots_list()
1612+
1613+ groups = []
1614+ now = datetime.date.today()
1615+
1616+ #today
1617+ date = now
1618+ groups.append( (_('Today'), self.snapshots.get_snapshot_id( date ), []) )
1619+
1620+ #yesterday
1621+ date = now - datetime.timedelta( days = 1 )
1622+ groups.append( (_('Yesterday'), self.snapshots.get_snapshot_id( date ), []) )
1623+
1624+ #this week
1625+ date = now - datetime.timedelta( days = now.weekday() )
1626+ groups.append( (_('This week'), self.snapshots.get_snapshot_id( date ), []) )
1627+
1628+ #last week
1629+ date = now - datetime.timedelta( days = now.weekday() + 7 )
1630+ groups.append( (_('Last week'), self.snapshots.get_snapshot_id( date ), []) )
1631+
1632+ #fill groups
1633+ for snapshot_id in self.snapshots_list:
1634+ found = False
1635+
1636+ for group in groups:
1637+ if snapshot_id >= group[1]:
1638+ group[2].append( snapshot_id )
1639+ found = True
1640+ break
1641+
1642+ if not found:
1643+ year = int( snapshot_id[ 0 : 4 ] )
1644+ month = int( snapshot_id[ 4 : 6 ] )
1645+ date = datetime.date( year, month, 1 )
1646+
1647+ group_name = ''
1648+ if year == now.year:
1649+ group_name = date.strftime( '%B' ).capitalize()
1650+ else:
1651+ group_name = date.strftime( '%B, %Y' ).capitalize()
1652+
1653+ groups.append( ( group_name, self.snapshots.get_snapshot_id( date ), [ snapshot_id ]) )
1654+
1655+ #fill time_line list
1656+ for group in groups:
1657+ if len( group[2] ) > 0:
1658+ self.store_time_line.append( [ "<b>%s</b>" % group[0], '' ] );
1659+ for snapshot_id in group[2]:
1660+ self.store_time_line.append( [ gnometools.get_snapshot_display_markup( self.snapshots, snapshot_id ), snapshot_id ] )
1661+
1662+ #select previous item
1663+ iter = self.store_time_line.get_iter_first()
1664+ while not iter is None:
1665+ if current_selection == self.store_time_line.get_value( iter, 1 ):
1666+ break
1667+ iter = self.store_time_line.iter_next( iter )
1668+
1669+ changed = False
1670+ if iter is None:
1671+ changed = True
1672+ iter = self.store_time_line.get_iter_first()
1673+
1674+ self.list_time_line.get_selection().select_iter( iter )
1675+
1676+ if changed and update_folder_view:
1677+ self.update_folder_view( 2 )
1678+
1679+ def on_close( self, *params ):
1680+ main_window_x, main_window_y = self.window.get_position()
1681+ main_window_width, main_window_height = self.window.get_size()
1682+ main_window_hpaned1 = self.builder.get_object('hpaned1').get_position()
1683+ main_window_hpaned2 = self.builder.get_object('hpaned2').get_position()
1684+
1685+ self.config.set_int_value( 'gnome.main_window.x', main_window_x )
1686+ self.config.set_int_value( 'gnome.main_window.y', main_window_y )
1687+ self.config.set_int_value( 'gnome.main_window.width', main_window_width )
1688+ self.config.set_int_value( 'gnome.main_window.height', main_window_height )
1689+ self.config.set_int_value( 'gnome.main_window.hpaned1', main_window_hpaned1 )
1690+ self.config.set_int_value( 'gnome.main_window.hpaned2', main_window_hpaned2 )
1691+ self.config.set_str_value( 'gnome.last_path', self.folder_path )
1692+ self.config.set_bool_value( 'gnome.show_hidden_files', self.show_hidden_files )
1693+
1694+ self.config.save()
1695+ self.window.destroy()
1696+ return True
1697+
1698+ def on_list_time_line_cursor_changed( self, list ):
1699+ if list.get_selection().path_is_selected( list.get_cursor()[ 0 ] ):
1700+ self.update_folder_view( 2 )
1701+
1702+ def on_list_places_cursor_changed( self, list ):
1703+ if list.get_selection().path_is_selected( list.get_cursor()[ 0 ] ):
1704+ iter = list.get_selection().get_selected()[1]
1705+ folder_path = self.store_places.get_value( iter, 1 )
1706+ if folder_path != self.folder_path:
1707+ self.folder_path = folder_path
1708+ self.update_folder_view( 0 )
1709+
1710+ def on_list_folder_view_drag_data_get( self, widget, drag_context, selection_data, info, timestamp, user_param1 = None ):
1711+ iter = self.list_folder_view.get_selection().get_selected()[1]
1712+ if not iter is None:
1713+ path = self.store_folder_view.get_value( iter, 1 )
1714+ path = self.snapshots.get_snapshot_path_to( self.snapshot_id, path )
1715+ path = gnomevfs.escape_path_string( path )
1716+ selection_data.set_uris( [ 'file://' + path ] )
1717+
1718+ def on_list_folder_view_button_press_event( self, list, event ):
1719+ if event.button != 3:
1720+ return
1721+
1722+ if len( self.store_folder_view ) <= 0:
1723+ return
1724+
1725+ path = self.list_folder_view.get_path_at_pos( int( event.x ), int( event.y ) )
1726+ if path is None:
1727+ return
1728+ path = path[0]
1729+
1730+ self.list_folder_view.get_selection().select_path( path )
1731+ self.show_folder_view_menu_popup( self.list_folder_view, event.button, event.time )
1732+
1733+ def on_list_folder_view_popup_menu( self, list ):
1734+ self.show_folder_view_menu_popup( list, 1, gtk.get_current_event_time() )
1735+
1736+ def show_folder_view_menu_popup( self, list, button, time ):
1737+ iter = list.get_selection().get_selected()[1]
1738+ if iter is None:
1739+ return
1740+
1741+ #print "popup-menu"
1742+ self.popup_menu = gtk.Menu()
1743+
1744+ menu_item = gtk.ImageMenuItem( 'backintime.open' )
1745+ menu_item.set_image( gtk.image_new_from_icon_name( self.store_folder_view.get_value( iter, 2 ), gtk.ICON_SIZE_MENU ) )
1746+ menu_item.connect( 'activate', self.on_list_folder_view_open_item )
1747+ self.popup_menu.append( menu_item )
1748+
1749+ self.popup_menu.append( gtk.SeparatorMenuItem() )
1750+
1751+ menu_item = gtk.ImageMenuItem( 'backintime.copy' )
1752+ menu_item.set_image( gtk.image_new_from_stock( gtk.STOCK_COPY, gtk.ICON_SIZE_MENU ) )
1753+ menu_item.connect( 'activate', self.on_list_folder_view_copy_item )
1754+ self.popup_menu.append( menu_item )
1755+
1756+ menu_item = gtk.ImageMenuItem( 'backintime.snapshots' )
1757+ menu_item.set_image( gtk.image_new_from_stock( gtk.STOCK_INDEX, gtk.ICON_SIZE_MENU ) )
1758+ menu_item.connect( 'activate', self.on_list_folder_view_snapshots_item )
1759+ self.popup_menu.append( menu_item )
1760+
1761+ if len( self.snapshot_id ) > 1:
1762+ menu_item = gtk.ImageMenuItem( 'backintime.restore' )
1763+ menu_item.set_image( gtk.image_new_from_stock( gtk.STOCK_UNDELETE, gtk.ICON_SIZE_MENU ) )
1764+ menu_item.connect( 'activate', self.on_list_folder_view_restore_item )
1765+ self.popup_menu.append( menu_item )
1766+
1767+ self.popup_menu.show_all()
1768+ self.popup_menu.popup( None, None, None, button, time )
1769+
1770+ def on_list_folder_view_restore_item( self, widget, data = None ):
1771+ self.on_btn_restore_clicked( self.builder.get_object( 'btn_restore' ) )
1772+
1773+ def on_list_folder_view_copy_item( self, widget, data = None ):
1774+ self.on_btn_copy_clicked( self.builder.get_object( 'btn_copy' ) )
1775+
1776+ def on_list_folder_view_snapshots_item( self, widget, data = None ):
1777+ self.on_btn_snapshots_clicked( self.builder.get_object( 'btn_snapshots' ) )
1778+
1779+ def on_list_folder_view_open_item( self, widget, data = None ):
1780+ iter = self.list_folder_view.get_selection().get_selected()[1]
1781+ if iter is None:
1782+ return
1783+
1784+ path = self.store_folder_view.get_value( iter, 1 )
1785+ path = self.snapshots.get_snapshot_path_to( self.snapshot_id, path )
1786+ cmd = "gnome-open \"%s\" &" % path
1787+ print cmd
1788+ os.system( cmd )
1789+
1790+ def on_list_folder_view_row_activated( self, list, path, column ):
1791+ iter = list.get_selection().get_selected()[1]
1792+ path = self.store_folder_view.get_value( iter, 1 )
1793+
1794+ #directory
1795+ if 0 == self.store_folder_view.get_value( iter, 3 ):
1796+ self.folder_path = path
1797+ self.update_folder_view( 1 )
1798+ return
1799+
1800+ #file
1801+ path = self.snapshots.get_snapshot_path_to( self.snapshot_id, path )
1802+ cmd = "gnome-open \"%s\" &" % path
1803+ print cmd
1804+ os.system( cmd )
1805+
1806+ def on_btn_fodler_up_clicked( self, button ):
1807+ if len( self.folder_path ) <= 1:
1808+ return
1809+
1810+ index = self.folder_path.rfind( '/' )
1811+ if index < 1:
1812+ parent_path = "/"
1813+ else:
1814+ parent_path = self.folder_path[ : index ]
1815+
1816+ self.folder_path = parent_path
1817+ self.update_folder_view( 1 )
1818+
1819+ def on_btn_restore_clicked( self, button ):
1820+ iter = self.list_folder_view.get_selection().get_selected()[1]
1821+ if not iter is None:
1822+ button.set_sensitive( False )
1823+ gnometools.run_gtk_update_loop()
1824+ self.snapshots.restore( self.snapshot_id, self.store_folder_view.get_value( iter, 1 ) )
1825+ button.set_sensitive( True )
1826+
1827+ def on_btn_copy_clicked( self, button ):
1828+ iter = self.list_folder_view.get_selection().get_selected()[1]
1829+ if iter is None:
1830+ return
1831+
1832+ path = self.store_folder_view.get_value( iter, 1 )
1833+ path = self.snapshots.get_snapshot_path_to( self.snapshot_id, path )
1834+
1835+ clipboardtools.clipboard_copy_path( path )
1836+
1837+ def on_btn_hidden_files_toggled( self, button ):
1838+ if self.folder_path is None:
1839+ return
1840+
1841+ self.show_hidden_files = button.get_active()
1842+ self.update_folder_view( 0 )
1843+
1844+ def on_btn_snapshots_clicked( self, button ):
1845+ iter = self.list_folder_view.get_selection().get_selected()[1]
1846+ if iter is None:
1847+ return
1848+
1849+ path = self.store_folder_view.get_value( iter, 1 )
1850+ icon_name = self.store_folder_view.get_value( iter, 2 )
1851+
1852+ retVal = snapshotsdialog.SnapshotsDialog( self.snapshots, self.window, path, self.snapshots_list, self.snapshot_id, icon_name ).run()
1853+
1854+ #select the specified file
1855+ if not retVal is None:
1856+ iter = self.store_time_line.get_iter_first()
1857+ while not iter is None:
1858+ snapshot_id = self.store_time_line.get_value( iter, 1 )
1859+ if snapshot_id == retVal:
1860+ break
1861+ iter = self.store_time_line.iter_next( iter )
1862+
1863+ if not iter is None:
1864+ self.list_time_line.get_selection().select_iter( iter )
1865+ self.update_folder_view( 2 )
1866+
1867+ def on_btn_about_clicked( self, button ):
1868+ AboutDialog( self.config, self.window ).run()
1869+
1870+ def on_help( self ):
1871+ gnome.help_display('backintime')
1872+
1873+ def on_btn_help_clicked( self, button ):
1874+ self.on_help()
1875+
1876+ def on_btn_link_clicked( self, button ):
1877+ os.system( "gnome-open http://backintime.le-web.org &" )
1878+
1879+ def on_key_release_event( self, widget, event ):
1880+ if 'F1' == gtk.gdk.keyval_name( event.keyval ) and ( event.state & (gtk.gdk.CONTROL_MASK | gtk.gdk.MOD1_MASK) ) == 0:
1881+ self.on_help()
1882+
1883+ def on_btn_settings_clicked( self, button ):
1884+ snapshots_path = self.config.get_snapshots_path()
1885+ include_folders = self.config.get_include_folders()
1886+
1887+ settingsdialog.SettingsDialog( self.config, self ).run()
1888+
1889+ if snapshots_path != self.config.get_snapshots_path() or include_folders != self.config.get_include_folders():
1890+ self.update_all( False )
1891+
1892+ def on_btn_snapshot_name_clicked( self, button ):
1893+ iter = self.list_time_line.get_selection().get_selected()[1]
1894+ if iter is None:
1895+ return
1896+
1897+ snapshot_id = self.store_time_line.get_value( iter, 1 )
1898+ if len( snapshot_id ) <= 1:
1899+ return
1900+
1901+ old_name = self.snapshots.get_snapshot_name( snapshot_id )
1902+ new_name = messagebox.text_input_dialog( self.window, self.config, _('Snapshot Name'), old_name )
1903+ if new_name is None:
1904+ return
1905+
1906+ if old_name == new_name:
1907+ return
1908+
1909+ self.snapshots.set_snapshot_name( snapshot_id, new_name )
1910+ self.store_time_line.set_value( iter, 0, gnometools.get_snapshot_display_markup( self.snapshots, snapshot_id ) )
1911+
1912+ def on_btn_remove_snapshot_clicked( self, button ):
1913+ iter = self.list_time_line.get_selection().get_selected()[1]
1914+ if iter is None:
1915+ return
1916+
1917+ snapshot_id = self.store_time_line.get_value( iter, 1 )
1918+ if len( snapshot_id ) <= 1:
1919+ return
1920+
1921+ if gtk.RESPONSE_YES == messagebox.show_question( self.window, self.config, _('Are you sure you want to remove the snapshot:\n<b>%s</b>') % self.snapshots.get_snapshot_display_name( snapshot_id ) ):
1922+ print "Remove Snapshot: %s" % snapshot_id
1923+ self.snapshots.remove_snapshot( snapshot_id )
1924+ self.fill_time_line()
1925+
1926+ def on_btn_backup_clicked( self, button ):
1927+ button.set_sensitive( False )
1928+ self.updatetime_line = True
1929+
1930+ if self.snapshots.is_busy():
1931+ self.update_backup_info()
1932+ return
1933+
1934+ backintime.take_snapshot_now_async( self.config )
1935+ self.update_backup_info( True )
1936+
1937+ def on_btn_update_snapshots_clicked( self, button ):
1938+ self.fill_time_line( False )
1939+ self.update_folder_view( 2 )
1940+
1941+ def update_folder_view( self, changed_from, selected_file = None, show_snapshots = False ): #0 - places, 1 - folder view, 2 - time_line
1942+ #update backup time
1943+ if 2 == changed_from:
1944+ iter = self.list_time_line.get_selection().get_selected()[1]
1945+ self.snapshot_id = self.store_time_line.get_value( iter, 1 )
1946+ #self.lblTime.set_markup( "<b>%s</b>" % backupTime )
1947+
1948+ tooltip = ''
1949+ text = ''
1950+ if len( self.snapshot_id ) > 1:
1951+ name = self.snapshots.get_snapshot_display_id( self.snapshot_id )
1952+ text = _('Snapshot: %s') % name
1953+ tooltip = _('View the snapshot made at %s') % name
1954+ else:
1955+ tooltip = _('View the current disk content')
1956+ text = _('Now')
1957+
1958+ self.lbl_snapshot.set_markup( ' <b>' + text + '</b> ' )
1959+ self.lbl_snapshot.set_tooltip_text( tooltip )
1960+
1961+ #update selected places item
1962+ if 1 == changed_from:
1963+ iter = self.store_places.get_iter_first()
1964+ while not iter is None:
1965+ place_path = self.store_places.get_value( iter, 1 )
1966+ if place_path == self.folder_path:
1967+ break
1968+ iter = self.store_places.iter_next( iter )
1969+
1970+ if iter is None:
1971+ self.list_places.get_selection().unselect_all()
1972+ else:
1973+ self.list_places.get_selection().select_iter( iter )
1974+
1975+ #update folder view
1976+
1977+ full_path = self.snapshots.get_snapshot_path_to( self.snapshot_id, self.folder_path )
1978+ all_files = []
1979+ files = []
1980+ folder_exists = os.path.isdir( full_path )
1981+
1982+ if folder_exists:
1983+ try:
1984+ all_files = os.listdir( full_path )
1985+ all_files.sort()
1986+ except:
1987+ pass
1988+
1989+ files = []
1990+ for file in all_files:
1991+ if len( file ) == 0:
1992+ continue
1993+
1994+ if not self.show_hidden_files:
1995+ if file[ 0 ] == '.':
1996+ continue
1997+ if file[ -1 ] == '~':
1998+ continue
1999+
2000+ path = os.path.join( full_path, file )
2001+
2002+ file_size = -1
2003+ file_date = -1
2004+
2005+ try:
2006+ file_stat = os.stat( path )
2007+ file_size = file_stat[stat.ST_SIZE]
2008+ file_date = file_stat[stat.ST_MTIME]
2009+ except:
2010+ pass
2011+
2012+ #format size
2013+ file_size_int = file_size
2014+ if file_size_int < 0:
2015+ file_size_int = 0
2016+
2017+ if file_size < 0:
2018+ file_size = 'unknown'
2019+ elif file_size < 1024:
2020+ file_size = str( file_size ) + ' bytes'
2021+ elif file_size < 1024 * 1024:
2022+ file_size = file_size / 1024
2023+ file_size = str( file_size ) + ' KB'
2024+ elif file_size < 1024 * 1024 * 1024:
2025+ file_size = file_size / ( 1024 * 1024 )
2026+ file_size = str( file_size ) + ' MB'
2027+ else:
2028+ file_size = file_size / ( 1024 * 1024 * 1024 )
2029+ file_size = str( file_size ) + ' GB'
2030+
2031+ #format date
2032+ if file_date < 0:
2033+ file_date = 'unknown'
2034+ else:
2035+ file_date = datetime.datetime.fromtimestamp(file_date).isoformat(' ')
2036+
2037+ if os.path.isdir( path ):
2038+ files.append( [ file, file_size, file_date, self.icon_names.get_icon(path), file_size_int, 0 ] )
2039+ else:
2040+ files.append( [ file, file_size, file_date, self.icon_names.get_icon(path), file_size_int, 1 ] )
2041+
2042+ #try to keep old selected file
2043+ if selected_file is None:
2044+ selected_file = ''
2045+ iter = self.list_folder_view.get_selection().get_selected()[1]
2046+ if not iter is None:
2047+ selected_file = self.store_folder_view.get_value( iter, 1 )
2048+
2049+ self.list_folder_view_widget.show()
2050+ self.list_folder_view_shadow.hide()
2051+ else:
2052+ self.list_folder_view_widget.hide()
2053+ self.list_folder_view_shadow.show()
2054+
2055+ #populate the list
2056+ self.store_folder_view.clear()
2057+
2058+ selected_iter = None
2059+ for item in files:
2060+ rel_path = os.path.join( self.folder_path, item[0] )
2061+ new_iter = self.store_folder_view.append( [ item[0], rel_path, item[3], item[5], item[1], item[2], item[4] ] )
2062+ if selected_file == rel_path:
2063+ selected_iter = new_iter
2064+
2065+ #select old item or the first item
2066+ if len( files ) > 0:
2067+ if selected_iter is None:
2068+ selected_iter = self.store_folder_view.get_iter_first()
2069+ self.list_folder_view.get_selection().select_iter( selected_iter )
2070+ self.list_folder_view.drag_source_set( gtk.gdk.BUTTON1_MASK | gtk.gdk.BUTTON3_MASK, gtk.target_list_add_uri_targets(), gtk.gdk.ACTION_COPY )
2071+ else:
2072+ self.list_folder_view.drag_source_unset()
2073+
2074+ #update folderup button state
2075+ self.builder.get_object( 'btn_folder_up' ).set_sensitive( len( self.folder_path ) > 1 )
2076+
2077+ #update restore button state
2078+ self.builder.get_object( 'btn_restore' ).set_sensitive( len( self.snapshot_id ) > 1 and len( self.store_folder_view ) > 0 )
2079+
2080+ #update remove/name snapshot buttons
2081+ self.builder.get_object( 'btn_snapshot_name' ).set_sensitive( len( self.snapshot_id ) > 1 )
2082+ self.builder.get_object( 'btn_remove_snapshot' ).set_sensitive( len( self.snapshot_id ) > 1 )
2083+
2084+ #update copy button state
2085+ self.builder.get_object( 'btn_copy' ).set_sensitive( len( self.store_folder_view ) > 0 )
2086+
2087+ #update snapshots button state
2088+ self.builder.get_object( 'btn_snapshots' ).set_sensitive( len( self.store_folder_view ) > 0 )
2089+
2090+ #display current folder
2091+ self.builder.get_object( 'edit_current_path' ).set_text( self.folder_path )
2092+
2093+ #show snapshots
2094+ if show_snapshots:
2095+ self.on_btn_snapshots_clicked( None )
2096
2097
2098 def open_url( dialog, link, user_data ):
2099- os.system( "gnome-open \"%s\" &" % link )
2100+ os.system( "gnome-open \"%s\" &" % link )
2101
2102
2103 if __name__ == '__main__':
2104- cfg = backintime.start_app( 'backintime-gnome', ['-s', '--snapshots'] )
2105-
2106- raise_cmd = ''
2107- if len( sys.argv ) > 1:
2108- raise_cmd = '\n'.join( sys.argv[ 1 : ] )
2109-
2110- app_instance = guiapplicationinstance.GUIApplicationInstance( cfg.get_app_instance_file(), raise_cmd )
2111-
2112- gnome_props = { gnome.PARAM_APP_DATADIR : '/usr/share' }
2113- gnome.program_init( 'backintime', cfg.VERSION, properties = gnome_props )
2114-
2115- gtk.about_dialog_set_url_hook( open_url, None )
2116-
2117- logger.openlog()
2118- main_window = MainWindow( cfg, app_instance )
2119- if cfg.is_configured():
2120- gtk.main()
2121- logger.closelog()
2122-
2123- app_instance.exit_application()
2124+ cfg = backintime.start_app( 'backintime-gnome', ['-s', '--snapshots'] )
2125+
2126+ raise_cmd = ''
2127+ if len( sys.argv ) > 1:
2128+ raise_cmd = '\n'.join( sys.argv[ 1 : ] )
2129+
2130+ app_instance = guiapplicationinstance.GUIApplicationInstance( cfg.get_app_instance_file(), raise_cmd )
2131+
2132+ gnome_props = { gnome.PARAM_APP_DATADIR : '/usr/share' }
2133+ gnome.program_init( 'backintime', cfg.VERSION, properties = gnome_props )
2134+
2135+ gtk.about_dialog_set_url_hook( open_url, None )
2136+
2137+ logger.openlog()
2138+ main_window = MainWindow( cfg, app_instance )
2139+ if cfg.is_configured():
2140+ gtk.main()
2141+ logger.closelog()
2142+
2143+ app_instance.exit_application()
2144
2145
2146=== modified file 'gnome/mainwindow.glade'
2147--- gnome/mainwindow.glade 2009-05-27 08:45:25 +0000
2148+++ gnome/mainwindow.glade 2009-10-01 16:35:20 +0000
2149@@ -1,8 +1,8 @@
2150 <?xml version="1.0"?>
2151-<glade-interface>
2152- <!-- interface-requires gtk+ 2.16 -->
2153+<interface>
2154+ <requires lib="gtk+" version="2.16"/>
2155 <!-- interface-naming-policy toplevel-contextual -->
2156- <widget class="GtkWindow" id="MainWindow">
2157+ <object class="GtkWindow" id="MainWindow">
2158 <property name="title" translatable="yes">Back In Time</property>
2159 <property name="window_position">center</property>
2160 <property name="icon_name">gtk-save</property>
2161@@ -10,173 +10,173 @@
2162 <signal name="key_release_event" handler="on_MainWindow_key_release_event"/>
2163 <signal name="delete_event" handler="on_MainWindow_delete_event"/>
2164 <child>
2165- <widget class="GtkVBox" id="vbox1">
2166+ <object class="GtkVBox" id="vbox1">
2167 <property name="visible">True</property>
2168 <child>
2169- <widget class="GtkToolbar" id="toolbar1">
2170+ <object class="GtkToolbar" id="toolbar1">
2171 <property name="visible">True</property>
2172 <child>
2173- <widget class="GtkToolButton" id="btn_backup">
2174+ <object class="GtkToolButton" id="btn_backup">
2175 <property name="visible">True</property>
2176- <property name="tooltip" translatable="yes">Take snapshot</property>
2177+ <property name="tooltip_text" translatable="yes">Take snapshot</property>
2178 <property name="label" translatable="yes">Backup Now</property>
2179 <property name="stock_id">gtk-save</property>
2180 <signal name="clicked" handler="on_btn_backup_clicked"/>
2181- </widget>
2182+ </object>
2183 <packing>
2184 <property name="expand">False</property>
2185 <property name="homogeneous">True</property>
2186 </packing>
2187 </child>
2188 <child>
2189- <widget class="GtkToolButton" id="btn_update_snapshots">
2190+ <object class="GtkToolButton" id="btn_update_snapshots">
2191 <property name="visible">True</property>
2192- <property name="tooltip" translatable="yes">Update snapshots</property>
2193+ <property name="tooltip_text" translatable="yes">Update snapshots</property>
2194 <property name="label" translatable="yes">Update snapshots</property>
2195 <property name="stock_id">gtk-refresh</property>
2196 <signal name="clicked" handler="on_btn_update_snapshots_clicked"/>
2197- </widget>
2198+ </object>
2199 <packing>
2200 <property name="expand">False</property>
2201 <property name="homogeneous">True</property>
2202 </packing>
2203 </child>
2204 <child>
2205- <widget class="GtkToolButton" id="btn_snapshot_name">
2206+ <object class="GtkToolButton" id="btn_snapshot_name">
2207 <property name="visible">True</property>
2208- <property name="tooltip" translatable="yes">Snapshot Name</property>
2209+ <property name="tooltip_text" translatable="yes">Snapshot Name</property>
2210 <property name="label" translatable="yes">Snapshot Name</property>
2211 <property name="stock_id">gtk-edit</property>
2212 <signal name="clicked" handler="on_btn_snapshot_name_clicked"/>
2213- </widget>
2214+ </object>
2215 <packing>
2216 <property name="expand">False</property>
2217 <property name="homogeneous">True</property>
2218 </packing>
2219 </child>
2220 <child>
2221- <widget class="GtkToolButton" id="btn_remove_snapshot">
2222+ <object class="GtkToolButton" id="btn_remove_snapshot">
2223 <property name="visible">True</property>
2224- <property name="tooltip" translatable="yes">Remove Snapshot</property>
2225+ <property name="tooltip_text" translatable="yes">Remove Snapshot</property>
2226 <property name="label" translatable="yes">Remove Snapshot</property>
2227 <property name="stock_id">gtk-delete</property>
2228 <signal name="clicked" handler="on_btn_remove_snapshot_clicked"/>
2229- </widget>
2230+ </object>
2231 <packing>
2232 <property name="expand">False</property>
2233 <property name="homogeneous">True</property>
2234 </packing>
2235 </child>
2236 <child>
2237- <widget class="GtkSeparatorToolItem" id="toolbutton1">
2238+ <object class="GtkSeparatorToolItem" id="toolbutton1">
2239 <property name="visible">True</property>
2240- </widget>
2241+ </object>
2242 <packing>
2243 <property name="expand">False</property>
2244 </packing>
2245 </child>
2246 <child>
2247- <widget class="GtkToolButton" id="btn_settings">
2248+ <object class="GtkToolButton" id="btn_settings">
2249 <property name="visible">True</property>
2250- <property name="tooltip" translatable="yes">Settings</property>
2251+ <property name="tooltip_text" translatable="yes">Settings</property>
2252 <property name="label" translatable="yes">Settings</property>
2253 <property name="stock_id">gtk-preferences</property>
2254 <signal name="clicked" handler="on_btn_settings_clicked"/>
2255- </widget>
2256- <packing>
2257- <property name="expand">False</property>
2258- <property name="homogeneous">True</property>
2259- </packing>
2260- </child>
2261- <child>
2262- <widget class="GtkSeparatorToolItem" id="toolbutton5">
2263- <property name="visible">True</property>
2264- </widget>
2265- <packing>
2266- <property name="expand">False</property>
2267- <property name="homogeneous">True</property>
2268- </packing>
2269- </child>
2270- <child>
2271- <widget class="GtkToolButton" id="btn_about">
2272- <property name="visible">True</property>
2273- <property name="tooltip" translatable="yes">About</property>
2274+ </object>
2275+ <packing>
2276+ <property name="expand">False</property>
2277+ <property name="homogeneous">True</property>
2278+ </packing>
2279+ </child>
2280+ <child>
2281+ <object class="GtkSeparatorToolItem" id="toolbutton5">
2282+ <property name="visible">True</property>
2283+ </object>
2284+ <packing>
2285+ <property name="expand">False</property>
2286+ <property name="homogeneous">True</property>
2287+ </packing>
2288+ </child>
2289+ <child>
2290+ <object class="GtkToolButton" id="btn_about">
2291+ <property name="visible">True</property>
2292+ <property name="tooltip_text" translatable="yes">About</property>
2293 <property name="label" translatable="yes">About</property>
2294 <property name="stock_id">gtk-about</property>
2295 <signal name="clicked" handler="on_btn_about_clicked"/>
2296- </widget>
2297+ </object>
2298 <packing>
2299 <property name="expand">False</property>
2300 <property name="homogeneous">True</property>
2301 </packing>
2302 </child>
2303 <child>
2304- <widget class="GtkToolButton" id="btn_help">
2305+ <object class="GtkToolButton" id="btn_help">
2306 <property name="visible">True</property>
2307- <property name="tooltip" translatable="yes">Help</property>
2308+ <property name="tooltip_text" translatable="yes">Help</property>
2309 <property name="label" translatable="yes">Help</property>
2310 <property name="stock_id">gtk-help</property>
2311 <signal name="clicked" handler="on_btn_help_clicked"/>
2312- </widget>
2313+ </object>
2314 <packing>
2315 <property name="expand">False</property>
2316 <property name="homogeneous">True</property>
2317 </packing>
2318 </child>
2319 <child>
2320- <widget class="GtkSeparatorToolItem" id="toolbutton2">
2321+ <object class="GtkSeparatorToolItem" id="toolbutton2">
2322 <property name="visible">True</property>
2323- </widget>
2324+ </object>
2325 <packing>
2326 <property name="expand">False</property>
2327 </packing>
2328 </child>
2329 <child>
2330- <widget class="GtkToolButton" id="btn_exit">
2331+ <object class="GtkToolButton" id="btn_exit">
2332 <property name="visible">True</property>
2333- <property name="tooltip" translatable="yes">Exit</property>
2334+ <property name="tooltip_text" translatable="yes">Exit</property>
2335 <property name="label" translatable="yes">Exit</property>
2336 <property name="stock_id">gtk-quit</property>
2337 <signal name="clicked" handler="on_btn_exit_clicked"/>
2338- </widget>
2339+ </object>
2340 <packing>
2341 <property name="expand">False</property>
2342 <property name="homogeneous">True</property>
2343 </packing>
2344 </child>
2345 <child>
2346- <widget class="GtkSeparatorToolItem" id="toolbutton8">
2347+ <object class="GtkSeparatorToolItem" id="toolbutton8">
2348 <property name="visible">True</property>
2349- </widget>
2350+ </object>
2351 <packing>
2352 <property name="expand">False</property>
2353 <property name="homogeneous">True</property>
2354 </packing>
2355 </child>
2356- </widget>
2357+ </object>
2358 <packing>
2359 <property name="expand">False</property>
2360 <property name="position">0</property>
2361 </packing>
2362 </child>
2363 <child>
2364- <widget class="GtkVBox" id="vbox2">
2365+ <object class="GtkVBox" id="vbox2">
2366 <property name="visible">True</property>
2367 <property name="orientation">vertical</property>
2368 <property name="spacing">2</property>
2369 <child>
2370- <widget class="GtkHBox" id="hbox1">
2371+ <object class="GtkHBox" id="hbox1">
2372 <property name="visible">True</property>
2373 <property name="spacing">5</property>
2374 <child>
2375- <widget class="GtkHBox" id="hbox2">
2376+ <object class="GtkHBox" id="hbox2">
2377 <property name="visible">True</property>
2378 <child>
2379- <widget class="GtkLabel" id="label1">
2380+ <object class="GtkLabel" id="label1">
2381 <property name="visible">True</property>
2382 <property name="label" translatable="yes">Profile:</property>
2383 <property name="single_line_mode">True</property>
2384- </widget>
2385+ </object>
2386 <packing>
2387 <property name="expand">False</property>
2388 <property name="padding">5</property>
2389@@ -184,16 +184,16 @@
2390 </packing>
2391 </child>
2392 <child>
2393- <widget class="GtkComboBox" id="combo_profiles">
2394+ <object class="GtkComboBox" id="combo_profiles">
2395 <property name="visible">True</property>
2396 <signal name="changed" handler="on_combo_profiles_changed"/>
2397- </widget>
2398+ </object>
2399 <packing>
2400 <property name="pack_type">end</property>
2401 <property name="position">1</property>
2402 </packing>
2403 </child>
2404- </widget>
2405+ </object>
2406 <packing>
2407 <property name="position">0</property>
2408 </packing>
2409@@ -202,7 +202,7 @@
2410 <placeholder/>
2411 </child>
2412 <child>
2413- <widget class="GtkLinkButton" id="linkbutton1">
2414+ <object class="GtkLinkButton" id="linkbutton1">
2415 <property name="label">backintime.le-web.org</property>
2416 <property name="visible">True</property>
2417 <property name="can_focus">True</property>
2418@@ -210,28 +210,28 @@
2419 <property name="relief">none</property>
2420 <property name="xalign">1</property>
2421 <property name="uri">http://backintime.le-web.org</property>
2422- </widget>
2423+ </object>
2424 <packing>
2425 <property name="expand">False</property>
2426 <property name="position">2</property>
2427 </packing>
2428 </child>
2429- </widget>
2430+ </object>
2431 <packing>
2432 <property name="expand">False</property>
2433 <property name="position">0</property>
2434 </packing>
2435 </child>
2436 <child>
2437- <widget class="GtkHSeparator" id="hseparator1">
2438+ <object class="GtkHSeparator" id="hseparator1">
2439 <property name="visible">True</property>
2440- </widget>
2441+ </object>
2442 <packing>
2443 <property name="expand">False</property>
2444 <property name="position">1</property>
2445 </packing>
2446 </child>
2447- </widget>
2448+ </object>
2449 <packing>
2450 <property name="expand">False</property>
2451 <property name="padding">2</property>
2452@@ -239,11 +239,11 @@
2453 </packing>
2454 </child>
2455 <child>
2456- <widget class="GtkHPaned" id="hpaned1">
2457+ <object class="GtkHPaned" id="hpaned1">
2458 <property name="visible">True</property>
2459 <property name="can_focus">True</property>
2460 <child>
2461- <widget class="GtkScrolledWindow" id="scrolledwindow1">
2462+ <object class="GtkScrolledWindow" id="scrolledwindow1">
2463 <property name="width_request">200</property>
2464 <property name="visible">True</property>
2465 <property name="can_focus">True</property>
2466@@ -251,131 +251,131 @@
2467 <property name="vscrollbar_policy">automatic</property>
2468 <property name="shadow_type">in</property>
2469 <child>
2470- <widget class="GtkTreeView" id="list_time_line">
2471+ <object class="GtkTreeView" id="list_time_line">
2472 <property name="visible">True</property>
2473 <property name="can_focus">True</property>
2474 <property name="search_column">0</property>
2475 <signal name="cursor_changed" handler="on_list_time_line_cursor_changed"/>
2476- </widget>
2477+ </object>
2478 </child>
2479- </widget>
2480+ </object>
2481 <packing>
2482 <property name="resize">False</property>
2483 <property name="shrink">True</property>
2484 </packing>
2485 </child>
2486 <child>
2487- <widget class="GtkFrame" id="frame5">
2488+ <object class="GtkFrame" id="frame5">
2489 <property name="visible">True</property>
2490 <property name="border_width">3</property>
2491 <property name="label_xalign">0</property>
2492 <child>
2493- <widget class="GtkVBox" id="vbox6">
2494+ <object class="GtkVBox" id="vbox6">
2495 <property name="visible">True</property>
2496 <property name="border_width">5</property>
2497 <child>
2498- <widget class="GtkToolbar" id="toolbar3">
2499+ <object class="GtkToolbar" id="toolbar3">
2500 <property name="visible">True</property>
2501 <child>
2502- <widget class="GtkToolButton" id="btn_folder_up">
2503+ <object class="GtkToolButton" id="btn_folder_up">
2504 <property name="visible">True</property>
2505- <property name="tooltip" translatable="yes">Parent folder</property>
2506+ <property name="tooltip_text" translatable="yes">Parent folder</property>
2507 <property name="label" translatable="yes">Up</property>
2508 <property name="stock_id">gtk-go-up</property>
2509 <signal name="clicked" handler="on_btn_folder_up_clicked"/>
2510- </widget>
2511+ </object>
2512 <packing>
2513 <property name="expand">False</property>
2514 <property name="homogeneous">True</property>
2515 </packing>
2516 </child>
2517 <child>
2518- <widget class="GtkToolItem" id="btn_current_path">
2519+ <object class="GtkToolItem" id="btn_current_path">
2520 <property name="visible">True</property>
2521 <child>
2522- <widget class="GtkEntry" id="edit_current_path">
2523+ <object class="GtkEntry" id="edit_current_path">
2524 <property name="visible">True</property>
2525 <property name="can_focus">True</property>
2526 <property name="editable">False</property>
2527- </widget>
2528+ </object>
2529 </child>
2530- </widget>
2531+ </object>
2532 <packing>
2533 <property name="expand">False</property>
2534 </packing>
2535 </child>
2536 <child>
2537- <widget class="GtkToggleToolButton" id="btn_hidden_files">
2538+ <object class="GtkToggleToolButton" id="btn_hidden_files">
2539 <property name="visible">True</property>
2540- <property name="tooltip" translatable="yes">Show hidden files</property>
2541+ <property name="tooltip_text" translatable="yes">Show hidden files</property>
2542 <property name="label" translatable="yes">Hidden files</property>
2543 <property name="stock_id">gtk-add</property>
2544 <signal name="toggled" handler="on_btn_hidden_files_toggled"/>
2545- </widget>
2546+ </object>
2547 <packing>
2548 <property name="expand">False</property>
2549 <property name="homogeneous">True</property>
2550 </packing>
2551 </child>
2552 <child>
2553- <widget class="GtkSeparatorToolItem" id="toolbutton3">
2554+ <object class="GtkSeparatorToolItem" id="toolbutton3">
2555 <property name="visible">True</property>
2556- </widget>
2557+ </object>
2558 <packing>
2559 <property name="expand">False</property>
2560 </packing>
2561 </child>
2562 <child>
2563- <widget class="GtkToolButton" id="btn_restore">
2564+ <object class="GtkToolButton" id="btn_restore">
2565 <property name="visible">True</property>
2566- <property name="tooltip" translatable="yes">Restore</property>
2567+ <property name="tooltip_text" translatable="yes">Restore</property>
2568 <property name="label" translatable="yes">Restore</property>
2569 <property name="stock_id">gtk-undelete</property>
2570 <signal name="clicked" handler="on_btn_restore_clicked"/>
2571- </widget>
2572+ </object>
2573 <packing>
2574 <property name="expand">False</property>
2575 <property name="homogeneous">True</property>
2576 </packing>
2577 </child>
2578 <child>
2579- <widget class="GtkToolButton" id="btn_copy">
2580+ <object class="GtkToolButton" id="btn_copy">
2581 <property name="visible">True</property>
2582- <property name="tooltip" translatable="yes">Copy</property>
2583+ <property name="tooltip_text" translatable="yes">Copy</property>
2584 <property name="label" translatable="yes">Copy</property>
2585 <property name="stock_id">gtk-copy</property>
2586 <signal name="clicked" handler="on_btn_copy_clicked"/>
2587- </widget>
2588+ </object>
2589 <packing>
2590 <property name="expand">False</property>
2591 <property name="homogeneous">True</property>
2592 </packing>
2593 </child>
2594 <child>
2595- <widget class="GtkToolButton" id="btn_snapshots">
2596+ <object class="GtkToolButton" id="btn_snapshots">
2597 <property name="visible">True</property>
2598- <property name="tooltip" translatable="yes">Snapshots</property>
2599+ <property name="tooltip_text" translatable="yes">Snapshots</property>
2600 <property name="label" translatable="yes">Snapshots</property>
2601 <property name="stock_id">gtk-index</property>
2602 <signal name="clicked" handler="on_btn_snapshots_clicked"/>
2603- </widget>
2604+ </object>
2605 <packing>
2606 <property name="expand">False</property>
2607 <property name="homogeneous">True</property>
2608 </packing>
2609 </child>
2610- </widget>
2611+ </object>
2612 <packing>
2613 <property name="expand">False</property>
2614 <property name="position">0</property>
2615 </packing>
2616 </child>
2617 <child>
2618- <widget class="GtkHPaned" id="hpaned2">
2619+ <object class="GtkHPaned" id="hpaned2">
2620 <property name="visible">True</property>
2621 <property name="can_focus">True</property>
2622 <child>
2623- <widget class="GtkScrolledWindow" id="scrolledwindow">
2624+ <object class="GtkScrolledWindow" id="scrolledwindow">
2625 <property name="width_request">200</property>
2626 <property name="visible">True</property>
2627 <property name="can_focus">True</property>
2628@@ -383,25 +383,25 @@
2629 <property name="vscrollbar_policy">automatic</property>
2630 <property name="shadow_type">in</property>
2631 <child>
2632- <widget class="GtkTreeView" id="list_places">
2633+ <object class="GtkTreeView" id="list_places">
2634 <property name="visible">True</property>
2635 <property name="can_focus">True</property>
2636 <property name="search_column">0</property>
2637 <signal name="cursor_changed" handler="on_list_places_cursor_changed"/>
2638- </widget>
2639+ </object>
2640 </child>
2641- </widget>
2642+ </object>
2643 <packing>
2644 <property name="resize">False</property>
2645 <property name="shrink">True</property>
2646 </packing>
2647 </child>
2648 <child>
2649- <widget class="GtkHBox" id="hbox5">
2650+ <object class="GtkHBox" id="hbox5">
2651 <property name="visible">True</property>
2652 <property name="homogeneous">True</property>
2653 <child>
2654- <widget class="GtkScrolledWindow" id="list_folder_view_widget">
2655+ <object class="GtkScrolledWindow" id="list_folder_view_widget">
2656 <property name="width_request">350</property>
2657 <property name="height_request">400</property>
2658 <property name="visible">True</property>
2659@@ -410,7 +410,7 @@
2660 <property name="vscrollbar_policy">automatic</property>
2661 <property name="shadow_type">in</property>
2662 <child>
2663- <widget class="GtkTreeView" id="list_folder_view">
2664+ <object class="GtkTreeView" id="list_folder_view">
2665 <property name="visible">True</property>
2666 <property name="can_focus">True</property>
2667 <property name="has_focus">True</property>
2668@@ -418,84 +418,78 @@
2669 <signal name="row_activated" handler="on_list_folder_view_row_activated"/>
2670 <signal name="popup_menu" handler="on_list_folder_view_popup_menu"/>
2671 <signal name="drag_data_get" handler="on_list_folder_view_drag_data_get"/>
2672- </widget>
2673+ </object>
2674 </child>
2675- </widget>
2676+ </object>
2677 <packing>
2678 <property name="position">0</property>
2679 </packing>
2680 </child>
2681 <child>
2682- <widget class="GtkFrame" id="list_folder_view_shadow">
2683+ <object class="GtkFrame" id="list_folder_view_shadow">
2684 <property name="label_xalign">0</property>
2685 <property name="shadow_type">in</property>
2686 <child>
2687- <widget class="GtkLabel" id="label17">
2688+ <object class="GtkLabel" id="label17">
2689 <property name="visible">True</property>
2690- <property name="label" translatable="yes">&lt;b&gt;This folder don't exist
2691+ <property name="label" translatable="yes">&lt;b&gt;This folder does not exist
2692 in current snapshot !&lt;/b&gt;</property>
2693 <property name="use_markup">True</property>
2694 <property name="justify">center</property>
2695- </widget>
2696+ </object>
2697 </child>
2698- <child>
2699+ <child type="label_item">
2700 <placeholder/>
2701- <packing>
2702- <property name="type">label_item</property>
2703- </packing>
2704 </child>
2705- </widget>
2706+ </object>
2707 <packing>
2708 <property name="position">1</property>
2709 </packing>
2710 </child>
2711- </widget>
2712+ </object>
2713 <packing>
2714 <property name="resize">True</property>
2715 <property name="shrink">True</property>
2716 </packing>
2717 </child>
2718- </widget>
2719+ </object>
2720 <packing>
2721 <property name="position">1</property>
2722 </packing>
2723 </child>
2724- </widget>
2725+ </object>
2726 </child>
2727- <child>
2728- <widget class="GtkLabel" id="lbl_snapshot">
2729+ <child type="label">
2730+ <object class="GtkLabel" id="lbl_snapshot">
2731 <property name="visible">True</property>
2732 <property name="has_tooltip">True</property>
2733 <property name="use_markup">True</property>
2734- </widget>
2735- <packing>
2736- <property name="type">label_item</property>
2737- </packing>
2738+ </object>
2739 </child>
2740- </widget>
2741+ </object>
2742 <packing>
2743 <property name="resize">True</property>
2744 <property name="shrink">True</property>
2745 </packing>
2746 </child>
2747- </widget>
2748+ </object>
2749 <packing>
2750 <property name="position">3</property>
2751 </packing>
2752 </child>
2753 <child>
2754- <widget class="GtkStatusbar" id="status_bar">
2755+ <object class="GtkStatusbar" id="status_bar">
2756 <property name="visible">True</property>
2757 <property name="has_tooltip">True</property>
2758 <property name="spacing">5</property>
2759- </widget>
2760+ </object>
2761 <packing>
2762 <property name="expand">False</property>
2763 <property name="pack_type">end</property>
2764 <property name="position">1</property>
2765 </packing>
2766 </child>
2767- </widget>
2768+ </object>
2769 </child>
2770- </widget>
2771-</glade-interface>
2772+ </object>
2773+</interface>
2774
2775=== modified file 'gnome/messagebox.py'
2776--- gnome/messagebox.py 2009-06-10 10:16:27 +0000
2777+++ gnome/messagebox.py 2009-10-01 16:35:20 +0000
2778@@ -31,40 +31,47 @@
2779
2780
2781 def show_question( parent, config, message ):
2782- dialog = gtk.MessageDialog( parent, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO )
2783- dialog.set_markup( message )
2784- dialog.set_title( config.APP_NAME )
2785- retVal = dialog.run()
2786- dialog.destroy()
2787- return retVal
2788+ dialog = gtk.MessageDialog( parent, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO )
2789+ dialog.set_markup( message )
2790+ dialog.set_title( config.APP_NAME )
2791+ retVal = dialog.run()
2792+ dialog.destroy()
2793+ return retVal
2794
2795 def show_error( parent, config, message ):
2796- dialog = gtk.MessageDialog( parent, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK )
2797- dialog.set_markup( message )
2798- dialog.set_title( config.APP_NAME )
2799- retVal = dialog.run()
2800- dialog.destroy()
2801- return retVal
2802+ dialog = gtk.MessageDialog( parent, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK )
2803+ dialog.set_markup( message )
2804+ dialog.set_title( config.APP_NAME )
2805+ retVal = dialog.run()
2806+ dialog.destroy()
2807+ return retVal
2808
2809 def text_input_dialog( parent, config, title, default_value = '' ):
2810- glade = gtk.glade.XML( os.path.join( config.get_app_path(), 'gnome', 'textinputdialog.glade' ), None, 'backintime' )
2811- dialog = glade.get_widget( 'TextInputDialog' )
2812- dialog.set_title( title )
2813- dialog.set_transient_for( parent )
2814-
2815- edit = glade.get_widget( 'edit_text' )
2816-
2817- if not default_value is None:
2818- edit.set_text( default_value )
2819-
2820- edit.grab_focus()
2821-
2822- text = None
2823- if gtk.RESPONSE_OK == dialog.run():
2824- text = edit.get_text()
2825- else:
2826- text = default_value
2827-
2828- dialog.destroy()
2829- return text
2830+
2831+ builder = gtk.Builder()
2832+
2833+ glade_file = os.path.join(config.get_app_path(), 'gnome',
2834+ 'textinputdialog.glade')
2835+
2836+ builder.add_from_file(glade_file)
2837+
2838+ dialog = builder.get_object( 'TextInputDialog' )
2839+ dialog.set_title( title )
2840+ dialog.set_transient_for( parent )
2841+
2842+ edit = builder.get_object( 'edit_text' )
2843+
2844+ if not default_value is None:
2845+ edit.set_text( default_value )
2846+
2847+ edit.grab_focus()
2848+
2849+ text = None
2850+ if gtk.RESPONSE_OK == dialog.run():
2851+ text = edit.get_text()
2852+ else:
2853+ text = default_value
2854+
2855+ dialog.destroy()
2856+ return text
2857
2858
2859=== modified file 'gnome/settingsdialog.glade'
2860--- gnome/settingsdialog.glade 2009-05-27 12:43:59 +0000
2861+++ gnome/settingsdialog.glade 2009-10-01 16:35:20 +0000
2862@@ -1,8 +1,8 @@
2863 <?xml version="1.0"?>
2864-<glade-interface>
2865- <!-- interface-requires gtk+ 2.16 -->
2866+<interface>
2867+ <requires lib="gtk+" version="2.16"/>
2868 <!-- interface-naming-policy toplevel-contextual -->
2869- <widget class="GtkDialog" id="SettingsDialog">
2870+ <object class="GtkDialog" id="SettingsDialog">
2871 <property name="border_width">5</property>
2872 <property name="title" translatable="yes">Settings</property>
2873 <property name="modal">True</property>
2874@@ -11,213 +11,206 @@
2875 <property name="icon_name">gtk-preferences</property>
2876 <property name="type_hint">dialog</property>
2877 <property name="has_separator">False</property>
2878- <signal name="response" handler="on_SettingsDialog_response"/>
2879 <child internal-child="vbox">
2880- <widget class="GtkVBox" id="dialog-vbox2">
2881+ <object class="GtkVBox" id="dialog-vbox2">
2882 <property name="visible">True</property>
2883 <property name="spacing">2</property>
2884 <child>
2885- <widget class="GtkHBox" id="hbox5">
2886+ <object class="GtkHBox" id="hbox5">
2887 <property name="visible">True</property>
2888 <property name="spacing">5</property>
2889 <child>
2890- <widget class="GtkLabel" id="label2">
2891+ <object class="GtkLabel" id="label2">
2892 <property name="visible">True</property>
2893 <property name="label" translatable="yes">Profile:</property>
2894- </widget>
2895+ </object>
2896 <packing>
2897 <property name="expand">False</property>
2898 <property name="position">0</property>
2899 </packing>
2900 </child>
2901 <child>
2902- <widget class="GtkComboBox" id="combo_profiles">
2903+ <object class="GtkComboBox" id="combo_profiles">
2904 <property name="visible">True</property>
2905 <signal name="changed" handler="on_combo_profiles_changed"/>
2906- </widget>
2907+ </object>
2908 <packing>
2909 <property name="position">1</property>
2910 </packing>
2911 </child>
2912 <child>
2913- <widget class="GtkHBox" id="hbox6">
2914+ <object class="GtkHBox" id="hbox6">
2915 <property name="visible">True</property>
2916 <property name="spacing">5</property>
2917 <property name="homogeneous">True</property>
2918 <child>
2919- <widget class="GtkButton" id="btn_edit_profile">
2920+ <object class="GtkButton" id="btn_edit_profile">
2921 <property name="label" translatable="yes">gtk-edit</property>
2922 <property name="visible">True</property>
2923 <property name="can_focus">True</property>
2924 <property name="receives_default">True</property>
2925 <property name="use_stock">True</property>
2926 <signal name="clicked" handler="on_btn_edit_profile_clicked"/>
2927- </widget>
2928+ </object>
2929 <packing>
2930 <property name="expand">False</property>
2931 <property name="position">0</property>
2932 </packing>
2933 </child>
2934 <child>
2935- <widget class="GtkButton" id="btn_add_profile">
2936+ <object class="GtkButton" id="btn_add_profile">
2937 <property name="label" translatable="yes">gtk-new</property>
2938 <property name="visible">True</property>
2939 <property name="can_focus">True</property>
2940 <property name="receives_default">True</property>
2941 <property name="use_stock">True</property>
2942 <signal name="clicked" handler="on_btn_add_profile_clicked"/>
2943- </widget>
2944+ </object>
2945 <packing>
2946 <property name="expand">False</property>
2947 <property name="position">1</property>
2948 </packing>
2949 </child>
2950 <child>
2951- <widget class="GtkButton" id="btn_remove_profile">
2952+ <object class="GtkButton" id="btn_remove_profile">
2953 <property name="label" translatable="yes">gtk-delete</property>
2954 <property name="visible">True</property>
2955 <property name="can_focus">True</property>
2956 <property name="receives_default">True</property>
2957 <property name="use_stock">True</property>
2958 <signal name="clicked" handler="on_btn_remove_profile_clicked"/>
2959- </widget>
2960+ </object>
2961 <packing>
2962 <property name="expand">False</property>
2963 <property name="position">2</property>
2964 </packing>
2965 </child>
2966- </widget>
2967+ </object>
2968 <packing>
2969 <property name="expand">False</property>
2970 <property name="position">2</property>
2971 </packing>
2972 </child>
2973- </widget>
2974+ </object>
2975 <packing>
2976 <property name="expand">False</property>
2977 <property name="position">1</property>
2978 </packing>
2979 </child>
2980 <child>
2981- <widget class="GtkHSeparator" id="hseparator1">
2982+ <object class="GtkHSeparator" id="hseparator1">
2983 <property name="visible">True</property>
2984- </widget>
2985+ </object>
2986 <packing>
2987 <property name="expand">False</property>
2988 <property name="position">2</property>
2989 </packing>
2990 </child>
2991 <child>
2992- <widget class="GtkNotebook" id="notebook1">
2993+ <object class="GtkNotebook" id="notebook1">
2994 <property name="visible">True</property>
2995 <property name="can_focus">True</property>
2996 <child>
2997- <widget class="GtkVBox" id="vbox2">
2998+ <object class="GtkVBox" id="vbox2">
2999 <property name="visible">True</property>
3000 <property name="border_width">5</property>
3001 <property name="spacing">5</property>
3002 <child>
3003- <widget class="GtkFrame" id="frame1">
3004+ <object class="GtkFrame" id="frame1">
3005 <property name="visible">True</property>
3006 <property name="label_xalign">0</property>
3007 <property name="shadow_type">none</property>
3008 <child>
3009- <widget class="GtkAlignment" id="alignment1">
3010+ <object class="GtkAlignment" id="alignment1">
3011 <property name="visible">True</property>
3012 <property name="left_padding">12</property>
3013 <child>
3014- <widget class="GtkHBox" id="hbox4">
3015+ <object class="GtkHBox" id="hbox4">
3016 <property name="visible">True</property>
3017 <child>
3018- <widget class="GtkEntry" id="edit_where">
3019+ <object class="GtkEntry" id="edit_where">
3020 <property name="visible">True</property>
3021 <property name="can_focus">True</property>
3022 <property name="editable">False</property>
3023 <property name="invisible_char">&#x25CF;</property>
3024- </widget>
3025+ </object>
3026 <packing>
3027 <property name="position">0</property>
3028 </packing>
3029 </child>
3030 <child>
3031- <widget class="GtkButton" id="btn_where">
3032+ <object class="GtkButton" id="btn_where">
3033 <property name="visible">True</property>
3034 <property name="can_focus">True</property>
3035 <property name="receives_default">True</property>
3036 <signal name="clicked" handler="on_btn_where_clicked"/>
3037 <child>
3038- <widget class="GtkImage" id="image1">
3039+ <object class="GtkImage" id="image1">
3040 <property name="visible">True</property>
3041 <property name="stock">gtk-directory</property>
3042- </widget>
3043+ </object>
3044 </child>
3045- </widget>
3046+ </object>
3047 <packing>
3048 <property name="expand">False</property>
3049 <property name="position">1</property>
3050 </packing>
3051 </child>
3052- </widget>
3053+ </object>
3054 </child>
3055- </widget>
3056+ </object>
3057 </child>
3058- <child>
3059- <widget class="GtkLabel" id="label4">
3060+ <child type="label">
3061+ <object class="GtkLabel" id="label4">
3062 <property name="visible">True</property>
3063 <property name="label" translatable="yes">&lt;b&gt;Where to save snapshots&lt;/b&gt;</property>
3064 <property name="use_markup">True</property>
3065- </widget>
3066- <packing>
3067- <property name="type">label_item</property>
3068- </packing>
3069+ </object>
3070 </child>
3071- </widget>
3072+ </object>
3073 <packing>
3074 <property name="expand">False</property>
3075 <property name="position">0</property>
3076 </packing>
3077 </child>
3078 <child>
3079- <widget class="GtkFrame" id="frame2">
3080+ <object class="GtkFrame" id="frame2">
3081 <property name="visible">True</property>
3082 <property name="label_xalign">0</property>
3083 <property name="shadow_type">none</property>
3084 <child>
3085- <widget class="GtkAlignment" id="alignment2">
3086+ <object class="GtkAlignment" id="alignment2">
3087 <property name="visible">True</property>
3088 <property name="left_padding">12</property>
3089 <child>
3090- <widget class="GtkComboBox" id="cb_backup_mode">
3091+ <object class="GtkComboBox" id="cb_backup_mode">
3092 <property name="visible">True</property>
3093- </widget>
3094+ </object>
3095 </child>
3096- </widget>
3097+ </object>
3098 </child>
3099- <child>
3100- <widget class="GtkLabel" id="lbl_schedule">
3101+ <child type="label">
3102+ <object class="GtkLabel" id="lbl_schedule">
3103 <property name="visible">True</property>
3104 <property name="label" translatable="yes">&lt;b&gt;Schedule&lt;/b&gt;</property>
3105 <property name="use_markup">True</property>
3106- </widget>
3107- <packing>
3108- <property name="type">label_item</property>
3109- </packing>
3110+ </object>
3111 </child>
3112- </widget>
3113+ </object>
3114 <packing>
3115 <property name="expand">False</property>
3116 <property name="position">1</property>
3117 </packing>
3118 </child>
3119 <child>
3120- <widget class="GtkHBox" id="hbox1">
3121+ <object class="GtkHBox" id="hbox1">
3122 <property name="visible">True</property>
3123 <child>
3124- <widget class="GtkLabel" id="label3">
3125+ <object class="GtkLabel" id="label3">
3126 <property name="visible">True</property>
3127 <property name="xalign">0</property>
3128 <property name="yalign">0.49000000953674316</property>
3129- </widget>
3130+ </object>
3131 <packing>
3132 <property name="expand">False</property>
3133 <property name="position">0</property>
3134@@ -226,30 +219,29 @@
3135 <child>
3136 <placeholder/>
3137 </child>
3138- </widget>
3139+ </object>
3140 <packing>
3141 <property name="position">2</property>
3142 </packing>
3143 </child>
3144- </widget>
3145+ </object>
3146 </child>
3147- <child>
3148- <widget class="GtkLabel" id="label11">
3149+ <child type="tab">
3150+ <object class="GtkLabel" id="label11">
3151 <property name="visible">True</property>
3152 <property name="label" translatable="yes">General</property>
3153- </widget>
3154+ </object>
3155 <packing>
3156 <property name="tab_fill">False</property>
3157- <property name="type">tab</property>
3158 </packing>
3159 </child>
3160 <child>
3161- <widget class="GtkVBox" id="vbox7">
3162+ <object class="GtkVBox" id="vbox7">
3163 <property name="visible">True</property>
3164 <property name="border_width">5</property>
3165 <property name="spacing">5</property>
3166 <child>
3167- <widget class="GtkScrolledWindow" id="scrolledwindow4">
3168+ <object class="GtkScrolledWindow" id="scrolledwindow4">
3169 <property name="width_request">300</property>
3170 <property name="height_request">250</property>
3171 <property name="visible">True</property>
3172@@ -258,78 +250,77 @@
3173 <property name="vscrollbar_policy">automatic</property>
3174 <property name="shadow_type">in</property>
3175 <child>
3176- <widget class="GtkTreeView" id="list_include">
3177+ <object class="GtkTreeView" id="list_include">
3178 <property name="visible">True</property>
3179 <property name="can_focus">True</property>
3180- </widget>
3181+ </object>
3182 </child>
3183- </widget>
3184+ </object>
3185 <packing>
3186 <property name="position">0</property>
3187 </packing>
3188 </child>
3189 <child>
3190- <widget class="GtkHBox" id="hbox2">
3191+ <object class="GtkHBox" id="hbox2">
3192 <property name="visible">True</property>
3193 <property name="spacing">5</property>
3194 <property name="homogeneous">True</property>
3195 <child>
3196- <widget class="GtkButton" id="btn_add_include">
3197+ <object class="GtkButton" id="btn_add_include">
3198 <property name="label" translatable="yes">gtk-add</property>
3199 <property name="visible">True</property>
3200 <property name="can_focus">True</property>
3201 <property name="receives_default">True</property>
3202 <property name="use_stock">True</property>
3203 <signal name="clicked" handler="on_btn_add_include_clicked"/>
3204- </widget>
3205+ </object>
3206 <packing>
3207 <property name="expand">False</property>
3208 <property name="position">0</property>
3209 </packing>
3210 </child>
3211 <child>
3212- <widget class="GtkButton" id="btn_remove_include">
3213+ <object class="GtkButton" id="btn_remove_include">
3214 <property name="label" translatable="yes">gtk-remove</property>
3215 <property name="visible">True</property>
3216 <property name="can_focus">True</property>
3217 <property name="receives_default">True</property>
3218 <property name="use_stock">True</property>
3219 <signal name="clicked" handler="on_btn_remove_include_clicked"/>
3220- </widget>
3221+ </object>
3222 <packing>
3223 <property name="expand">False</property>
3224 <property name="position">1</property>
3225 </packing>
3226 </child>
3227- </widget>
3228+ </object>
3229 <packing>
3230 <property name="expand">False</property>
3231 <property name="position">1</property>
3232 </packing>
3233 </child>
3234- </widget>
3235+ </object>
3236 <packing>
3237 <property name="position">1</property>
3238 </packing>
3239 </child>
3240- <child>
3241- <widget class="GtkLabel" id="label12">
3242+ <child type="tab">
3243+ <object class="GtkLabel" id="label12">
3244 <property name="visible">True</property>
3245 <property name="label" translatable="yes">Include</property>
3246- </widget>
3247+ </object>
3248 <packing>
3249 <property name="position">1</property>
3250 <property name="tab_fill">False</property>
3251- <property name="type">tab</property>
3252 </packing>
3253 </child>
3254 <child>
3255- <widget class="GtkVBox" id="vbox8">
3256+ <object class="GtkVBox" id="vbox8">
3257 <property name="visible">True</property>
3258 <property name="border_width">5</property>
3259 <property name="spacing">5</property>
3260 <child>
3261- <widget class="GtkScrolledWindow" id="scrolledwindow5">
3262+ <object class="GtkScrolledWindow" id="scrolledwindow5">
3263 <property name="width_request">180</property>
3264 <property name="height_request">120</property>
3265 <property name="visible">True</property>
3266@@ -338,97 +329,96 @@
3267 <property name="vscrollbar_policy">automatic</property>
3268 <property name="shadow_type">in</property>
3269 <child>
3270- <widget class="GtkTreeView" id="list_exclude">
3271+ <object class="GtkTreeView" id="list_exclude">
3272 <property name="visible">True</property>
3273 <property name="can_focus">True</property>
3274- </widget>
3275+ </object>
3276 </child>
3277- </widget>
3278+ </object>
3279 <packing>
3280 <property name="position">0</property>
3281 </packing>
3282 </child>
3283 <child>
3284- <widget class="GtkHBox" id="hbox3">
3285+ <object class="GtkHBox" id="hbox3">
3286 <property name="visible">True</property>
3287 <property name="spacing">5</property>
3288 <property name="homogeneous">True</property>
3289 <child>
3290- <widget class="GtkButton" id="btn_add_exclude">
3291+ <object class="GtkButton" id="btn_add_exclude">
3292 <property name="label" translatable="yes">gtk-add</property>
3293 <property name="visible">True</property>
3294 <property name="can_focus">True</property>
3295 <property name="receives_default">True</property>
3296 <property name="use_stock">True</property>
3297 <signal name="clicked" handler="on_btn_add_exclude_clicked"/>
3298- </widget>
3299+ </object>
3300 <packing>
3301 <property name="expand">False</property>
3302 <property name="position">0</property>
3303 </packing>
3304 </child>
3305 <child>
3306- <widget class="GtkButton" id="btn_add_exclude_file">
3307+ <object class="GtkButton" id="btn_add_exclude_file">
3308 <property name="label" translatable="yes">Add file</property>
3309 <property name="visible">True</property>
3310 <property name="can_focus">True</property>
3311 <property name="receives_default">True</property>
3312 <signal name="clicked" handler="on_btn_add_exclude_file_clicked"/>
3313- </widget>
3314+ </object>
3315 <packing>
3316 <property name="position">1</property>
3317 </packing>
3318 </child>
3319 <child>
3320- <widget class="GtkButton" id="btn_add_exclude_folder">
3321+ <object class="GtkButton" id="btn_add_exclude_folder">
3322 <property name="label" translatable="yes">Add folder</property>
3323 <property name="visible">True</property>
3324 <property name="can_focus">True</property>
3325 <property name="receives_default">True</property>
3326 <signal name="clicked" handler="on_btn_add_exclude_folder_clicked"/>
3327- </widget>
3328+ </object>
3329 <packing>
3330 <property name="position">2</property>
3331 </packing>
3332 </child>
3333 <child>
3334- <widget class="GtkButton" id="btn_remove_exclude">
3335+ <object class="GtkButton" id="btn_remove_exclude">
3336 <property name="label" translatable="yes">gtk-remove</property>
3337 <property name="visible">True</property>
3338 <property name="can_focus">True</property>
3339 <property name="receives_default">True</property>
3340 <property name="use_stock">True</property>
3341 <signal name="clicked" handler="on_btn_remove_exclude_clicked"/>
3342- </widget>
3343+ </object>
3344 <packing>
3345 <property name="expand">False</property>
3346 <property name="position">3</property>
3347 </packing>
3348 </child>
3349- </widget>
3350+ </object>
3351 <packing>
3352 <property name="expand">False</property>
3353 <property name="position">1</property>
3354 </packing>
3355 </child>
3356- </widget>
3357+ </object>
3358 <packing>
3359 <property name="position">2</property>
3360 </packing>
3361 </child>
3362- <child>
3363- <widget class="GtkLabel" id="label13">
3364+ <child type="tab">
3365+ <object class="GtkLabel" id="label13">
3366 <property name="visible">True</property>
3367 <property name="label" translatable="yes">Exclude</property>
3368- </widget>
3369+ </object>
3370 <packing>
3371 <property name="position">2</property>
3372 <property name="tab_fill">False</property>
3373- <property name="type">tab</property>
3374 </packing>
3375 </child>
3376 <child>
3377- <widget class="GtkTable" id="table2">
3378+ <object class="GtkTable" id="table2">
3379 <property name="visible">True</property>
3380 <property name="border_width">5</property>
3381 <property name="n_rows">5</property>
3382@@ -436,13 +426,13 @@
3383 <property name="column_spacing">5</property>
3384 <property name="row_spacing">5</property>
3385 <child>
3386- <widget class="GtkCheckButton" id="cb_dont_remove_named_snapshots">
3387+ <object class="GtkCheckButton" id="cb_dont_remove_named_snapshots">
3388 <property name="label" translatable="yes">Don't remove named snapshots</property>
3389 <property name="visible">True</property>
3390 <property name="can_focus">True</property>
3391 <property name="receives_default">False</property>
3392 <property name="draw_indicator">True</property>
3393- </widget>
3394+ </object>
3395 <packing>
3396 <property name="right_attach">3</property>
3397 <property name="top_attach">4</property>
3398@@ -451,77 +441,77 @@
3399 </packing>
3400 </child>
3401 <child>
3402- <widget class="GtkComboBox" id="cb_min_free_space_unit">
3403- <property name="visible">True</property>
3404- </widget>
3405- <packing>
3406- <property name="left_attach">2</property>
3407- <property name="right_attach">3</property>
3408- <property name="top_attach">1</property>
3409- <property name="bottom_attach">2</property>
3410- <property name="y_options">GTK_FILL</property>
3411- </packing>
3412- </child>
3413- <child>
3414- <widget class="GtkComboBox" id="cb_remove_old_backup_unit">
3415- <property name="visible">True</property>
3416- </widget>
3417- <packing>
3418- <property name="left_attach">2</property>
3419- <property name="right_attach">3</property>
3420- <property name="y_options">GTK_FILL</property>
3421- </packing>
3422- </child>
3423- <child>
3424- <widget class="GtkSpinButton" id="edit_remove_old_backup_value">
3425- <property name="visible">True</property>
3426- <property name="can_focus">True</property>
3427- <property name="adjustment">1 1 1000 1 0 0</property>
3428- <property name="numeric">True</property>
3429- </widget>
3430- <packing>
3431- <property name="left_attach">1</property>
3432- <property name="right_attach">2</property>
3433- <property name="y_options">GTK_FILL</property>
3434- </packing>
3435- </child>
3436- <child>
3437- <widget class="GtkSpinButton" id="edit_min_free_space_value">
3438- <property name="visible">True</property>
3439- <property name="can_focus">True</property>
3440- <property name="adjustment">1 1 1000 1 0 0</property>
3441- <property name="numeric">True</property>
3442- </widget>
3443- <packing>
3444- <property name="left_attach">1</property>
3445- <property name="right_attach">2</property>
3446- <property name="top_attach">1</property>
3447- <property name="bottom_attach">2</property>
3448- <property name="y_options">GTK_FILL</property>
3449- </packing>
3450- </child>
3451- <child>
3452- <widget class="GtkCheckButton" id="cb_remove_old_backup">
3453+ <object class="GtkComboBox" id="cb_min_free_space_unit">
3454+ <property name="visible">True</property>
3455+ </object>
3456+ <packing>
3457+ <property name="left_attach">2</property>
3458+ <property name="right_attach">3</property>
3459+ <property name="top_attach">1</property>
3460+ <property name="bottom_attach">2</property>
3461+ <property name="y_options">GTK_FILL</property>
3462+ </packing>
3463+ </child>
3464+ <child>
3465+ <object class="GtkComboBox" id="cb_remove_old_backup_unit">
3466+ <property name="visible">True</property>
3467+ </object>
3468+ <packing>
3469+ <property name="left_attach">2</property>
3470+ <property name="right_attach">3</property>
3471+ <property name="y_options">GTK_FILL</property>
3472+ </packing>
3473+ </child>
3474+ <child>
3475+ <object class="GtkSpinButton" id="edit_remove_old_backup_value">
3476+ <property name="visible">True</property>
3477+ <property name="can_focus">True</property>
3478+ <property name="adjustment">adjustment2</property>
3479+ <property name="numeric">True</property>
3480+ </object>
3481+ <packing>
3482+ <property name="left_attach">1</property>
3483+ <property name="right_attach">2</property>
3484+ <property name="y_options">GTK_FILL</property>
3485+ </packing>
3486+ </child>
3487+ <child>
3488+ <object class="GtkSpinButton" id="edit_min_free_space_value">
3489+ <property name="visible">True</property>
3490+ <property name="can_focus">True</property>
3491+ <property name="adjustment">adjustment1</property>
3492+ <property name="numeric">True</property>
3493+ </object>
3494+ <packing>
3495+ <property name="left_attach">1</property>
3496+ <property name="right_attach">2</property>
3497+ <property name="top_attach">1</property>
3498+ <property name="bottom_attach">2</property>
3499+ <property name="y_options">GTK_FILL</property>
3500+ </packing>
3501+ </child>
3502+ <child>
3503+ <object class="GtkCheckButton" id="cb_remove_old_backup">
3504 <property name="label" translatable="yes">Older than:</property>
3505 <property name="visible">True</property>
3506 <property name="can_focus">True</property>
3507 <property name="receives_default">False</property>
3508 <property name="draw_indicator">True</property>
3509 <signal name="toggled" handler="on_cb_remove_old_backup_toggled"/>
3510- </widget>
3511+ </object>
3512 <packing>
3513 <property name="y_options">GTK_FILL</property>
3514 </packing>
3515 </child>
3516 <child>
3517- <widget class="GtkCheckButton" id="cb_min_free_space">
3518+ <object class="GtkCheckButton" id="cb_min_free_space">
3519 <property name="label" translatable="yes">If free space is less than:</property>
3520 <property name="visible">True</property>
3521 <property name="can_focus">True</property>
3522 <property name="receives_default">False</property>
3523 <property name="draw_indicator">True</property>
3524 <signal name="toggled" handler="on_cb_min_free_space_toggled"/>
3525- </widget>
3526+ </object>
3527 <packing>
3528 <property name="top_attach">1</property>
3529 <property name="bottom_attach">2</property>
3530@@ -529,13 +519,13 @@
3531 </packing>
3532 </child>
3533 <child>
3534- <widget class="GtkCheckButton" id="cb_smart_remove">
3535+ <object class="GtkCheckButton" id="cb_smart_remove">
3536 <property name="label" translatable="yes">Smart remove</property>
3537 <property name="visible">True</property>
3538 <property name="can_focus">True</property>
3539 <property name="receives_default">False</property>
3540 <property name="draw_indicator">True</property>
3541- </widget>
3542+ </object>
3543 <packing>
3544 <property name="right_attach">3</property>
3545 <property name="top_attach">2</property>
3546@@ -544,14 +534,14 @@
3547 </packing>
3548 </child>
3549 <child>
3550- <widget class="GtkLabel" id="label10">
3551+ <object class="GtkLabel" id="label10">
3552 <property name="visible">True</property>
3553 <property name="xalign">0</property>
3554 <property name="label" translatable="yes">- keep all snapshots from today and yesterday
3555 - keep one snapshot for the last week and one for two weeks ago
3556 - keep one snapshot per month for all previous months of this year
3557 - keep one snapshot per year for all previous years</property>
3558- </widget>
3559+ </object>
3560 <packing>
3561 <property name="right_attach">3</property>
3562 <property name="top_attach">3</property>
3563@@ -560,35 +550,34 @@
3564 <property name="x_padding">20</property>
3565 </packing>
3566 </child>
3567- </widget>
3568+ </object>
3569 <packing>
3570 <property name="position">3</property>
3571 </packing>
3572 </child>
3573- <child>
3574- <widget class="GtkLabel" id="label14">
3575+ <child type="tab">
3576+ <object class="GtkLabel" id="label14">
3577 <property name="visible">True</property>
3578 <property name="label" translatable="yes">Auto-remove</property>
3579- </widget>
3580+ </object>
3581 <packing>
3582 <property name="position">3</property>
3583 <property name="tab_fill">False</property>
3584- <property name="type">tab</property>
3585 </packing>
3586 </child>
3587 <child>
3588- <widget class="GtkVBox" id="vbox5">
3589+ <object class="GtkVBox" id="vbox5">
3590 <property name="visible">True</property>
3591 <property name="border_width">5</property>
3592 <property name="spacing">5</property>
3593 <child>
3594- <widget class="GtkCheckButton" id="cb_enable_notifications">
3595+ <object class="GtkCheckButton" id="cb_enable_notifications">
3596 <property name="label" translatable="yes">Enable notifications</property>
3597 <property name="visible">True</property>
3598 <property name="can_focus">True</property>
3599 <property name="receives_default">False</property>
3600 <property name="draw_indicator">True</property>
3601- </widget>
3602+ </object>
3603 <packing>
3604 <property name="expand">False</property>
3605 <property name="position">0</property>
3606@@ -597,33 +586,32 @@
3607 <child>
3608 <placeholder/>
3609 </child>
3610- </widget>
3611+ </object>
3612 <packing>
3613 <property name="position">4</property>
3614 </packing>
3615 </child>
3616- <child>
3617- <widget class="GtkLabel" id="label1">
3618+ <child type="tab">
3619+ <object class="GtkLabel" id="label1">
3620 <property name="visible">True</property>
3621 <property name="label" translatable="yes">Options</property>
3622- </widget>
3623+ </object>
3624 <packing>
3625 <property name="position">4</property>
3626 <property name="tab_fill">False</property>
3627- <property name="type">tab</property>
3628 </packing>
3629 </child>
3630 <child>
3631- <widget class="GtkVBox" id="vbox9">
3632+ <object class="GtkVBox" id="vbox9">
3633 <property name="visible">True</property>
3634 <property name="border_width">5</property>
3635 <property name="spacing">5</property>
3636 <child>
3637- <widget class="GtkLabel" id="label15">
3638+ <object class="GtkLabel" id="label15">
3639 <property name="visible">True</property>
3640 <property name="label" translatable="yes">&lt;b&gt;Change this options only if you really know what you are doing !&lt;/b&gt;</property>
3641 <property name="use_markup">True</property>
3642- </widget>
3643+ </object>
3644 <packing>
3645 <property name="expand">False</property>
3646 <property name="padding">10</property>
3647@@ -631,102 +619,115 @@
3648 </packing>
3649 </child>
3650 <child>
3651- <widget class="GtkCheckButton" id="cb_per_directory_schedule">
3652+ <object class="GtkCheckButton" id="cb_per_directory_schedule">
3653 <property name="label" translatable="yes">Enable schedule per included folder (see Include tab; default: disabled)</property>
3654 <property name="visible">True</property>
3655 <property name="can_focus">True</property>
3656 <property name="receives_default">False</property>
3657 <property name="draw_indicator">True</property>
3658 <signal name="toggled" handler="on_cb_per_directory_schedule_toggled"/>
3659- </widget>
3660+ </object>
3661 <packing>
3662 <property name="expand">False</property>
3663 <property name="position">1</property>
3664 </packing>
3665 </child>
3666 <child>
3667- <widget class="GtkCheckButton" id="cb_run_nice_from_cron">
3668+ <object class="GtkCheckButton" id="cb_run_nice_from_cron">
3669 <property name="label" translatable="yes">Run 'nice' as cron job (default: enabled)</property>
3670 <property name="visible">True</property>
3671 <property name="can_focus">True</property>
3672 <property name="receives_default">False</property>
3673 <property name="draw_indicator">True</property>
3674- </widget>
3675+ </object>
3676 <packing>
3677 <property name="expand">False</property>
3678 <property name="position">2</property>
3679 </packing>
3680 </child>
3681 <child>
3682- <widget class="GtkLabel" id="label16">
3683+ <object class="GtkLabel" id="label16">
3684 <property name="visible">True</property>
3685- </widget>
3686+ </object>
3687 <packing>
3688 <property name="position">3</property>
3689 </packing>
3690 </child>
3691- </widget>
3692+ </object>
3693 <packing>
3694 <property name="position">5</property>
3695 </packing>
3696 </child>
3697- <child>
3698- <widget class="GtkLabel" id="label6">
3699+ <child type="tab">
3700+ <object class="GtkLabel" id="label6">
3701 <property name="visible">True</property>
3702 <property name="label" translatable="yes">Expert Options</property>
3703- </widget>
3704+ </object>
3705 <packing>
3706 <property name="position">5</property>
3707 <property name="tab_fill">False</property>
3708- <property name="type">tab</property>
3709 </packing>
3710 </child>
3711- </widget>
3712+ </object>
3713 <packing>
3714 <property name="position">3</property>
3715 </packing>
3716 </child>
3717 <child internal-child="action_area">
3718- <widget class="GtkHButtonBox" id="dialog-action_area2">
3719+ <object class="GtkHButtonBox" id="dialog-action_area2">
3720 <property name="layout_style">end</property>
3721 <child>
3722- <widget class="GtkButton" id="btn_ok">
3723+ <object class="GtkButton" id="btn_cancel">
3724+ <property name="label" translatable="yes">gtk-cancel</property>
3725+ <property name="visible">True</property>
3726+ <property name="can_focus">True</property>
3727+ <property name="receives_default">True</property>
3728+ <property name="use_stock">True</property>
3729+ </object>
3730+ <packing>
3731+ <property name="expand">False</property>
3732+ <property name="fill">False</property>
3733+ <property name="position">0</property>
3734+ </packing>
3735+ </child>
3736+ <child>
3737+ <object class="GtkButton" id="btn_ok">
3738 <property name="label" translatable="yes">gtk-ok</property>
3739- <property name="response_id">-5</property>
3740- <property name="visible">True</property>
3741- <property name="can_focus">True</property>
3742- <property name="receives_default">True</property>
3743- <property name="use_stock">True</property>
3744- </widget>
3745- <packing>
3746- <property name="expand">False</property>
3747- <property name="fill">False</property>
3748- <property name="position">0</property>
3749- </packing>
3750- </child>
3751- <child>
3752- <widget class="GtkButton" id="btn_cancel">
3753- <property name="label" translatable="yes">gtk-cancel</property>
3754- <property name="response_id">-6</property>
3755- <property name="visible">True</property>
3756- <property name="can_focus">True</property>
3757- <property name="receives_default">True</property>
3758- <property name="use_stock">True</property>
3759- </widget>
3760+ <property name="visible">True</property>
3761+ <property name="can_focus">True</property>
3762+ <property name="receives_default">True</property>
3763+ <property name="use_stock">True</property>
3764+ </object>
3765 <packing>
3766 <property name="expand">False</property>
3767 <property name="fill">False</property>
3768 <property name="position">1</property>
3769 </packing>
3770 </child>
3771- </widget>
3772+ </object>
3773 <packing>
3774 <property name="expand">False</property>
3775 <property name="pack_type">end</property>
3776 <property name="position">0</property>
3777 </packing>
3778 </child>
3779- </widget>
3780+ </object>
3781 </child>
3782- </widget>
3783-</glade-interface>
3784+ <action-widgets>
3785+ <action-widget response="-6">btn_cancel</action-widget>
3786+ <action-widget response="-5">btn_ok</action-widget>
3787+ </action-widgets>
3788+ </object>
3789+ <object class="GtkAdjustment" id="adjustment1">
3790+ <property name="value">1</property>
3791+ <property name="lower">1</property>
3792+ <property name="upper">1000</property>
3793+ <property name="step_increment">1</property>
3794+ </object>
3795+ <object class="GtkAdjustment" id="adjustment2">
3796+ <property name="value">1</property>
3797+ <property name="lower">1</property>
3798+ <property name="upper">1000</property>
3799+ <property name="step_increment">1</property>
3800+ </object>
3801+</interface>
3802
3803=== modified file 'gnome/settingsdialog.py'
3804--- gnome/settingsdialog.py 2009-06-10 11:33:16 +0000
3805+++ gnome/settingsdialog.py 2009-10-01 16:35:20 +0000
3806@@ -24,7 +24,6 @@
3807 pygtk.require("2.0")
3808 import gtk
3809 import gobject
3810-import gtk.glade
3811 import datetime
3812 import gettext
3813
3814@@ -36,546 +35,558 @@
3815 _=gettext.gettext
3816
3817
3818-class SettingsDialog:
3819- def __init__( self, config, parent ):
3820- self.config = config
3821- self.parent = parent
3822-
3823- self.glade = gtk.glade.XML( os.path.join( self.config.get_app_path(), 'gnome', 'settingsdialog.glade' ), None, 'backintime' )
3824- self.dialog = self.glade.get_widget( 'SettingsDialog' )
3825- self.dialog.set_transient_for( parent.window )
3826-
3827- signals = {
3828- 'on_btn_add_profile_clicked' : self.on_add_profile,
3829- 'on_btn_edit_profile_clicked' : self.on_edit_profile,
3830- 'on_btn_remove_profile_clicked' : self.on_remove_profile,
3831- 'on_btn_add_include_clicked' : self.on_add_include,
3832- 'on_btn_remove_include_clicked' : self.on_remove_include,
3833- 'on_btn_add_exclude_clicked' : self.on_add_exclude,
3834- 'on_btn_add_exclude_file_clicked' : self.on_add_exclude_file,
3835- 'on_btn_add_exclude_folder_clicked' : self.on_add_exclude_folder,
3836- 'on_btn_remove_exclude_clicked' : self.on_remove_exclude,
3837- 'on_cb_remove_old_backup_toggled' : self.update_remove_old_backups,
3838- 'on_cb_min_free_space_toggled' : self.update_min_free_space,
3839- 'on_cb_per_directory_schedule_toggled' : self.on_cb_per_directory_schedule_toggled,
3840- 'on_combo_profiles_changed': self.on_combo_profiles_changed,
3841- 'on_btn_where_clicked': self.on_btn_where_clicked,
3842- }
3843-
3844- self.glade.signal_autoconnect( signals )
3845-
3846- #profiles
3847- self.btn_edit_profile = self.glade.get_widget( 'btn_edit_profile' )
3848- self.btn_add_profile = self.glade.get_widget( 'btn_add_profile' )
3849- self.btn_remove_profile = self.glade.get_widget( 'btn_remove_profile' )
3850- self.combo_profiles = self.glade.get_widget( 'combo_profiles' )
3851-
3852- self.disable_combo_changed = True
3853-
3854- self.store_profiles = gtk.ListStore( str, str )
3855-
3856- self.combo_profiles = self.glade.get_widget( 'combo_profiles' )
3857-
3858- text_renderer = gtk.CellRendererText()
3859- self.combo_profiles.pack_start( text_renderer, True )
3860- self.combo_profiles.add_attribute( text_renderer, 'text', 0 )
3861-
3862- self.combo_profiles.set_model( self.store_profiles )
3863-
3864- self.disable_combo_changed = False
3865-
3866- #set current folder
3867- #self.fcb_where = self.glade.get_widget( 'fcb_where' )
3868- #self.fcb_where.set_show_hidden( self.parent.show_hidden_files )
3869- self.edit_where = self.glade.get_widget( 'edit_where' )
3870-
3871- #automatic backup mode store
3872- self.store_backup_mode = gtk.ListStore( str, int )
3873- default_automatic_backup_mode_index = 0
3874- map = self.config.AUTOMATIC_BACKUP_MODES
3875- self.rev_automatic_backup_modes = {}
3876- keys = map.keys()
3877- keys.sort()
3878- for key in keys:
3879- self.rev_automatic_backup_modes[ map[key] ] = key
3880- self.store_backup_mode.append( [ map[key], key ] )
3881-
3882- #per directory schedule
3883- self.cb_per_directory_schedule = self.glade.get_widget( 'cb_per_directory_schedule' )
3884- self.lbl_schedule = self.glade.get_widget( 'lbl_schedule' )
3885-
3886- #setup include folders
3887- self.list_include = self.glade.get_widget( 'list_include' )
3888-
3889- pix_renderer = gtk.CellRendererPixbuf()
3890- text_renderer = gtk.CellRendererText()
3891-
3892- column = gtk.TreeViewColumn( _('Include folders') )
3893- column.pack_start( pix_renderer, False )
3894- column.pack_end( text_renderer, True )
3895- column.add_attribute( pix_renderer, 'stock-id', 1 )
3896- column.add_attribute( text_renderer, 'markup', 0 )
3897- self.list_include.append_column( column )
3898-
3899- column = gtk.TreeViewColumn( _('Schedule') )
3900- combo_renderer = gtk.CellRendererCombo()
3901- combo_renderer.set_property( 'editable', True )
3902- combo_renderer.set_property( 'has-entry', False )
3903- combo_renderer.set_property( 'model', self.store_backup_mode )
3904- combo_renderer.set_property( 'text-column', 0 )
3905- combo_renderer.connect( 'edited', self.on_automatic_backup_mode_changed )
3906- column.pack_end( combo_renderer, True )
3907- column.add_attribute( combo_renderer, 'text', 2 )
3908-
3909- self.include_schedule_column = column
3910-
3911- self.store_include = gtk.ListStore( str, str, str, int )
3912- self.list_include.set_model( self.store_include )
3913-
3914- #setup exclude patterns
3915- self.list_exclude = self.glade.get_widget( 'list_exclude' )
3916-
3917- pix_renderer = gtk.CellRendererPixbuf()
3918- text_renderer = gtk.CellRendererText()
3919-
3920- column = gtk.TreeViewColumn( _('Patterns, files or folders') )
3921- column.pack_start( pix_renderer, False )
3922- column.pack_end( text_renderer, True )
3923- column.add_attribute( pix_renderer, 'stock-id', 1 )
3924- column.add_attribute( text_renderer, 'markup', 0 )
3925- self.list_exclude.append_column( column )
3926-
3927- self.store_exclude = gtk.ListStore( str, str )
3928- self.list_exclude.set_model( self.store_exclude )
3929-
3930- #setup automatic backup mode
3931- self.cb_backup_mode = self.glade.get_widget( 'cb_backup_mode' )
3932- self.cb_backup_mode.set_model( self.store_backup_mode )
3933-
3934- self.cb_backup_mode.clear()
3935- renderer = gtk.CellRendererText()
3936- self.cb_backup_mode.pack_start( renderer, True )
3937- self.cb_backup_mode.add_attribute( renderer, 'text', 0 )
3938-
3939- #setup remove old backups older than
3940- self.edit_remove_old_backup_value = self.glade.get_widget( 'edit_remove_old_backup_value' )
3941- self.cb_remove_old_backup_unit = self.glade.get_widget( 'cb_remove_old_backup_unit' )
3942-
3943- self.store_remove_old_backup_unit = gtk.ListStore( str, int )
3944- self.cb_remove_old_backup_unit.set_model( self.store_remove_old_backup_unit )
3945-
3946- renderer = gtk.CellRendererText()
3947- self.cb_remove_old_backup_unit.pack_start( renderer, True )
3948- self.cb_remove_old_backup_unit.add_attribute( renderer, 'text', 0 )
3949-
3950- self.store_remove_old_backup_unit.clear()
3951- map = self.config.REMOVE_OLD_BACKUP_UNITS
3952- keys = map.keys()
3953- keys.sort()
3954- for key in keys:
3955- self.store_remove_old_backup_unit.append( [ map[ key ], key ] )
3956-
3957- self.cb_remove_old_backup = self.glade.get_widget( 'cb_remove_old_backup' )
3958-
3959- #setup min free space
3960- self.edit_min_free_space_value = self.glade.get_widget( 'edit_min_free_space_value' )
3961- self.cb_min_free_space_unit = self.glade.get_widget( 'cb_min_free_space_unit' )
3962-
3963- self.store_min_free_space_unit = gtk.ListStore( str, int )
3964- self.cb_min_free_space_unit.set_model( self.store_min_free_space_unit )
3965-
3966- renderer = gtk.CellRendererText()
3967- self.cb_min_free_space_unit.pack_start( renderer, True )
3968- self.cb_min_free_space_unit.add_attribute( renderer, 'text', 0 )
3969-
3970- self.store_min_free_space_unit.clear()
3971- map = self.config.MIN_FREE_SPACE_UNITS
3972- keys = map.keys()
3973- keys.sort()
3974- for key in keys:
3975- self.store_min_free_space_unit.append( [ map[ key ], key ] )
3976-
3977- self.cb_min_free_space = self.glade.get_widget( 'cb_min_free_space' )
3978-
3979- #don't remove named snapshots
3980- self.cb_dont_remove_named_snapshots = self.glade.get_widget( 'cb_dont_remove_named_snapshots' )
3981- self.cb_dont_remove_named_snapshots.set_active( self.config.get_dont_remove_named_snapshots() )
3982-
3983- #smart remove
3984- self.cb_smart_remove = self.glade.get_widget( 'cb_smart_remove' )
3985-
3986- #enable notifications
3987- self.cb_enable_notifications = self.glade.get_widget( 'cb_enable_notifications' )
3988-
3989- self.update_profiles()
3990-
3991- def error_handler( self, message ):
3992- messagebox.show_error( self.dialog, self.config, message )
3993-
3994- def question_handler( self, message ):
3995- return gtk.RESPONSE_YES == messagebox.show_question( self.dialog, self.config, message )
3996-
3997- def on_automatic_backup_mode_changed( self, renderer, path, new_text ):
3998- iter = self.store_include.get_iter(path)
3999- self.store_include.set_value( iter, 2, new_text )
4000- self.store_include.set_value( iter, 3, self.rev_automatic_backup_modes[new_text] )
4001-
4002- def on_btn_where_clicked( self, button ):
4003- path = self.edit_where.get_text()
4004-
4005- fcd = gtk.FileChooserDialog( _('Snapshots folder'), self.dialog, gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER, (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK) )
4006- if len( path ) > 0:
4007- fcd.set_filename( path )
4008-
4009- if fcd.run() == gtk.RESPONSE_OK:
4010- new_path = tools.prepare_path( fcd.get_filename() )
4011- fcd.destroy()
4012- if len( path ) > 0 and new_path != path:
4013- if not self.question_handler( _('Are you sure you want to change snapshots folder ?') ):
4014- return
4015- self.edit_where.set_text( new_path )
4016- else:
4017- fcd.destroy()
4018-
4019- def on_combo_profiles_changed( self, *params ):
4020- if self.disable_combo_changed:
4021- return
4022-
4023- iter = self.combo_profiles.get_active_iter()
4024- if iter is None:
4025- return
4026-
4027- profile_id = self.store_profiles.get_value( iter, 1 )
4028- if profile_id != self.config.get_current_profile():
4029- self.save_profile()
4030- self.config.set_current_profile( profile_id )
4031-
4032- self.update_profile()
4033-
4034- def update_profiles( self ):
4035- self.disable_combo_changed = True
4036-
4037- profiles = self.config.get_profiles_sorted_by_name()
4038-
4039- select_iter = None
4040- self.store_profiles.clear()
4041-
4042- for profile_id in profiles:
4043- iter = self.store_profiles.append( [ self.config.get_profile_name( profile_id ), profile_id ] )
4044- if profile_id == self.config.get_current_profile():
4045- select_iter = iter
4046-
4047- self.disable_combo_changed = False
4048-
4049- if not select_iter is None:
4050- self.combo_profiles.set_active_iter( select_iter )
4051-
4052- def update_profile( self ):
4053- if self.config.get_current_profile() == '1':
4054- self.btn_edit_profile.set_sensitive( False )
4055- self.btn_remove_profile.set_sensitive( False )
4056- else:
4057- self.btn_edit_profile.set_sensitive( True )
4058- self.btn_remove_profile.set_sensitive( True )
4059-
4060- #set current folder
4061- #self.fcb_where.set_filename( self.config.get_snapshots_path() )
4062- self.edit_where.set_text( self.config.get_snapshots_path() )
4063-
4064- #per directory schedule
4065- self.cb_per_directory_schedule.set_active( self.config.get_per_directory_schedule() )
4066-
4067- #setup include folders
4068- self.update_per_directory_option()
4069-
4070- self.store_include.clear()
4071- include_folders = self.config.get_include_folders()
4072- if len( include_folders ) > 0:
4073- for include_folder in include_folders:
4074- self.store_include.append( [include_folder[0], gtk.STOCK_DIRECTORY, self.config.AUTOMATIC_BACKUP_MODES[include_folder[1]], include_folder[1] ] )
4075-
4076- #setup exclude patterns
4077- self.store_exclude.clear()
4078- exclude_patterns = self.config.get_exclude_patterns()
4079- if len( exclude_patterns ) > 0:
4080- for exclude_pattern in exclude_patterns:
4081- self.store_exclude.append( [exclude_pattern, gtk.STOCK_DELETE] )
4082-
4083- #setup automatic backup mode
4084- i = 0
4085- iter = self.store_backup_mode.get_iter_first()
4086- default_mode = self.config.get_automatic_backup_mode()
4087- while not iter is None:
4088- if self.store_backup_mode.get_value( iter, 1 ) == default_mode:
4089- self.cb_backup_mode.set_active( i )
4090- break
4091- iter = self.store_backup_mode.iter_next( iter )
4092- i = i + 1
4093-
4094- #setup remove old backups older than
4095- enabled, value, unit = self.config.get_remove_old_snapshots()
4096-
4097- self.edit_remove_old_backup_value.set_value( float( value ) )
4098-
4099- i = 0
4100- iter = self.store_remove_old_backup_unit.get_iter_first()
4101- while not iter is None:
4102- if self.store_remove_old_backup_unit.get_value( iter, 1 ) == unit:
4103- self.cb_remove_old_backup_unit.set_active( i )
4104- break
4105- iter = self.store_remove_old_backup_unit.iter_next( iter )
4106- i = i + 1
4107-
4108- self.cb_remove_old_backup.set_active( enabled )
4109- self.update_remove_old_backups( self.cb_remove_old_backup )
4110-
4111- #setup min free space
4112- enabled, value, unit = self.config.get_min_free_space()
4113-
4114- self.edit_min_free_space_value.set_value( float(value) )
4115-
4116- i = 0
4117- iter = self.store_min_free_space_unit.get_iter_first()
4118- while not iter is None:
4119- if self.store_min_free_space_unit.get_value( iter, 1 ) == unit:
4120- self.cb_min_free_space_unit.set_active( i )
4121- break
4122- iter = self.store_min_free_space_unit.iter_next( iter )
4123- i = i + 1
4124-
4125- self.cb_min_free_space.set_active( enabled )
4126- self.update_min_free_space( self.cb_min_free_space )
4127-
4128- #don't remove named snapshots
4129- self.cb_dont_remove_named_snapshots.set_active( self.config.get_dont_remove_named_snapshots() )
4130-
4131- #smart remove
4132- self.cb_smart_remove.set_active( self.config.get_smart_remove() )
4133-
4134- #enable notifications
4135- self.cb_enable_notifications.set_active( self.config.is_notify_enabled() )
4136-
4137- #run 'nice' from cron
4138- self.cb_run_nice_from_cron = self.glade.get_widget( 'cb_run_nice_from_cron' )
4139- self.cb_run_nice_from_cron.set_active( self.config.is_run_nice_from_cron_enabled() )
4140-
4141- def save_profile( self ):
4142- #snapshots path
4143- snapshots_path = self.edit_where.get_text()
4144-
4145- #hack
4146- if snapshots_path.startswith( '//' ):
4147- snapshots_path = snapshots_path[ 1 : ]
4148-
4149- #include list
4150- include_list = []
4151- iter = self.store_include.get_iter_first()
4152- while not iter is None:
4153- include_list.append( ( self.store_include.get_value( iter, 0 ), self.store_include.get_value( iter, 3 ) ) )
4154- iter = self.store_include.iter_next( iter )
4155-
4156- #exclude patterns
4157- exclude_list = []
4158- iter = self.store_exclude.get_iter_first()
4159- while not iter is None:
4160- exclude_list.append( self.store_exclude.get_value( iter, 0 ) )
4161- iter = self.store_exclude.iter_next( iter )
4162-
4163- #check if back folder changed
4164- #if len( self.config.get_snapshots_path() ) > 0 and self.config.get_snapshots_path() != snapshots_path:
4165- # if gtk.RESPONSE_YES != messagebox.show_question( self.dialog, self.config, _('Are you sure you want to change snapshots folder ?') ):
4166- # return False
4167-
4168- #ok let's save to config
4169- self.config.set_snapshots_path( snapshots_path )
4170- #if not msg is None:
4171- # messagebox.show_error( self.dialog, self.config, msg )
4172- # return False
4173-
4174- self.config.set_include_folders( include_list )
4175- self.config.set_exclude_patterns( exclude_list )
4176-
4177- #global schedule
4178- self.config.set_automatic_backup_mode( self.store_backup_mode.get_value( self.cb_backup_mode.get_active_iter(), 1 ) )
4179-
4180- #auto-remove snapshots
4181- self.config.set_remove_old_snapshots(
4182- self.cb_remove_old_backup.get_active(),
4183- int( self.edit_remove_old_backup_value.get_value() ),
4184- self.store_remove_old_backup_unit.get_value( self.cb_remove_old_backup_unit.get_active_iter(), 1 ) )
4185- self.config.set_min_free_space(
4186- self.cb_min_free_space.get_active(),
4187- int( self.edit_min_free_space_value.get_value() ),
4188- self.store_min_free_space_unit.get_value( self.cb_min_free_space_unit.get_active_iter(), 1 ) )
4189- self.config.set_dont_remove_named_snapshots( self.cb_dont_remove_named_snapshots.get_active() )
4190- self.config.set_smart_remove( self.cb_smart_remove.get_active() )
4191-
4192- #options
4193- self.config.set_notify_enabled( self.cb_enable_notifications.get_active() )
4194-
4195- #expert options
4196- self.config.set_per_directory_schedule( self.cb_per_directory_schedule.get_active() )
4197- self.config.set_run_nice_from_cron_enabled( self.cb_run_nice_from_cron.get_active() )
4198-
4199- def update_remove_old_backups( self, button ):
4200- enabled = self.cb_remove_old_backup.get_active()
4201- self.edit_remove_old_backup_value.set_sensitive( enabled )
4202- self.cb_remove_old_backup_unit.set_sensitive( enabled )
4203-
4204- def update_min_free_space( self, button ):
4205- enabled = self.cb_min_free_space.get_active()
4206- self.edit_min_free_space_value.set_sensitive( enabled )
4207- self.cb_min_free_space_unit.set_sensitive( enabled )
4208-
4209- def on_cb_per_directory_schedule_toggled( self, button ):
4210- self.update_per_directory_option()
4211-
4212- def update_per_directory_option( self ):
4213- if self.cb_per_directory_schedule.get_active():
4214- if self.list_include.get_column(1) == None:
4215- self.list_include.append_column( self.include_schedule_column )
4216- self.cb_backup_mode.hide()
4217- self.lbl_schedule.hide()
4218- else:
4219- if self.list_include.get_column(1) != None:
4220- self.list_include.remove_column( self.include_schedule_column )
4221- self.lbl_schedule.show()
4222- self.cb_backup_mode.show()
4223-
4224- def run( self ):
4225- self.config.set_question_handler( self.question_handler )
4226- self.config.set_error_handler( self.error_handler )
4227-
4228- self.config_copy_dict = copy.copy( self.config.dict )
4229- self.current_profile_org = self.config.get_current_profile()
4230-
4231- while True:
4232- if gtk.RESPONSE_OK == self.dialog.run():
4233- if not self.validate():
4234- continue
4235- else:
4236- self.config.dict = self.config_copy_dict
4237-
4238- break
4239-
4240- self.config.set_current_profile( self.current_profile_org )
4241- self.config.clear_handlers()
4242-
4243- self.dialog.destroy()
4244-
4245- def on_add_profile( self, button ):
4246- name = messagebox.text_input_dialog( self.dialog, self.config, _('New profile'), None )
4247- if name is None:
4248- return
4249- if len( name ) <= 0:
4250- return
4251-
4252- if not self.config.add_profile( name ):
4253- return
4254-
4255- self.update_profiles()
4256-
4257- def on_edit_profile( self, button ):
4258- name = messagebox.text_input_dialog( self.dialog, self.config, _('Rename profile'), None )
4259- if name is None:
4260- return
4261- if len( name ) <= 0:
4262- return
4263-
4264- if not self.config.set_profile_name( name ):
4265- return
4266-
4267- self.update_profiles()
4268-
4269- def on_remove_profile( self, button ):
4270- if gtk.RESPONSE_YES == messagebox.show_question( self.dialog, self.config, _('Are you sure you want to delete the profile "%s" ?') % self.config.get_profile_name() ):
4271- self.config.remove_profile()
4272- self.update_profiles()
4273-
4274- def on_add_include( self, button ):
4275- fcd = gtk.FileChooserDialog( _('Include folder'), self.dialog, gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER, (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK) )
4276- fcd.set_show_hidden( self.parent.show_hidden_files )
4277-
4278- if fcd.run() == gtk.RESPONSE_OK:
4279- include_folder = tools.prepare_path( fcd.get_filename() )
4280-
4281- iter = self.store_include.get_iter_first()
4282- while not iter is None:
4283- if self.store_include.get_value( iter, 0 ) == include_folder:
4284- break
4285- iter = self.store_include.iter_next( iter )
4286-
4287- if iter is None:
4288- self.store_include.append( [include_folder, gtk.STOCK_DIRECTORY, self.config.AUTOMATIC_BACKUP_MODES[self.config.NONE], self.config.NONE ] )
4289-
4290- fcd.destroy()
4291-
4292- def on_remove_include( self, button ):
4293- store, iter = self.list_include.get_selection().get_selected()
4294- if not iter is None:
4295- store.remove( iter )
4296-
4297- def add_exclude_( self, pattern ):
4298- pattern = pattern.strip()
4299- if len( pattern ) == 0:
4300- return
4301-
4302- iter = self.store_exclude.get_iter_first()
4303- while not iter is None:
4304- if self.store_exclude.get_value( iter, 0 ) == pattern:
4305- return
4306- iter = self.store_exclude.iter_next( iter )
4307-
4308- self.store_exclude.append( [pattern, gtk.STOCK_DELETE] )
4309-
4310- def on_add_exclude( self, button ):
4311- pattern = messagebox.text_input_dialog( self.dialog, self.config, _('Exclude pattern') )
4312- if pattern is None:
4313- return
4314-
4315- if pattern.find( ':' ) >= 0:
4316- messagebox.show_error( self.dialog, self.config, _('Exclude patterns can\'t contain \':\' char !') )
4317- return
4318-
4319- self.add_exclude_( pattern )
4320-
4321- def on_add_exclude_file( self, button ):
4322- fcd = gtk.FileChooserDialog( _('Exclude file'), self.dialog, gtk.FILE_CHOOSER_ACTION_OPEN, (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK) )
4323- fcd.set_show_hidden( self.parent.show_hidden_files )
4324-
4325- if fcd.run() == gtk.RESPONSE_OK:
4326- pattern = tools.prepare_path( fcd.get_filename() )
4327- self.add_exclude_( pattern )
4328-
4329- fcd.destroy()
4330-
4331- def on_add_exclude_folder( self, button ):
4332- fcd = gtk.FileChooserDialog( _('Exclude folder'), self.dialog, gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER, (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK) )
4333- fcd.set_show_hidden( self.parent.show_hidden_files )
4334-
4335- if fcd.run() == gtk.RESPONSE_OK:
4336- pattern = tools.prepare_path( fcd.get_filename() )
4337- self.add_exclude_( pattern )
4338-
4339- fcd.destroy()
4340-
4341- def on_remove_exclude( self, button ):
4342- store, iter = self.list_exclude.get_selection().get_selected()
4343- if not iter is None:
4344- store.remove( iter )
4345-
4346- def on_cancel( self, button ):
4347- self.dialog.destroy()
4348-
4349- def validate( self ):
4350- self.save_profile()
4351-
4352- if not self.config.check_config():
4353- return False
4354-
4355- if not self.config.setup_cron():
4356- return False
4357-
4358- self.config.save()
4359- return True
4360-
4361+class SettingsDialog(object):
4362+
4363+ def __init__( self, config, parent ):
4364+
4365+ self.config = config
4366+ self.parent = parent
4367+
4368+ builder = gtk.Builder()
4369+ self.builder = builder
4370+
4371+ glade_file = os.path.join(self.config.get_app_path(),
4372+ 'gnome', 'settingsdialog.glade')
4373+
4374+ builder.add_from_file(glade_file)
4375+
4376+ get = builder.get_object
4377+
4378+ self.dialog = get('SettingsDialog')
4379+ self.dialog.set_transient_for( parent.window )
4380+
4381+ signals = {
4382+ 'on_btn_add_profile_clicked' : self.on_add_profile,
4383+ 'on_btn_edit_profile_clicked' : self.on_edit_profile,
4384+ 'on_btn_remove_profile_clicked' : self.on_remove_profile,
4385+ 'on_btn_add_include_clicked' : self.on_add_include,
4386+ 'on_btn_remove_include_clicked' : self.on_remove_include,
4387+ 'on_btn_add_exclude_clicked' : self.on_add_exclude,
4388+ 'on_btn_add_exclude_file_clicked' : self.on_add_exclude_file,
4389+ 'on_btn_add_exclude_folder_clicked' : self.on_add_exclude_folder,
4390+ 'on_btn_remove_exclude_clicked' : self.on_remove_exclude,
4391+ 'on_cb_remove_old_backup_toggled' : self.update_remove_old_backups,
4392+ 'on_cb_min_free_space_toggled' : self.update_min_free_space,
4393+ 'on_cb_per_directory_schedule_toggled' : self.on_cb_per_directory_schedule_toggled,
4394+ 'on_combo_profiles_changed': self.on_combo_profiles_changed,
4395+ 'on_btn_where_clicked': self.on_btn_where_clicked,
4396+ }
4397+
4398+ builder.connect_signals(signals)
4399+
4400+ #profiles
4401+ self.btn_edit_profile = get( 'btn_edit_profile' )
4402+ self.btn_add_profile = get( 'btn_add_profile' )
4403+ self.btn_remove_profile = get( 'btn_remove_profile' )
4404+ self.combo_profiles = get( 'combo_profiles' )
4405+
4406+ self.disable_combo_changed = True
4407+
4408+ self.store_profiles = gtk.ListStore( str, str )
4409+
4410+ self.combo_profiles = get( 'combo_profiles' )
4411+
4412+ text_renderer = gtk.CellRendererText()
4413+ self.combo_profiles.pack_start( text_renderer, True )
4414+ self.combo_profiles.add_attribute( text_renderer, 'text', 0 )
4415+
4416+ self.combo_profiles.set_model( self.store_profiles )
4417+
4418+ self.disable_combo_changed = False
4419+
4420+ #set current folder
4421+ #self.fcb_where = get( 'fcb_where' )
4422+ #self.fcb_where.set_show_hidden( self.parent.show_hidden_files )
4423+ self.edit_where = get( 'edit_where' )
4424+
4425+ #automatic backup mode store
4426+ self.store_backup_mode = gtk.ListStore( str, int )
4427+ default_automatic_backup_mode_index = 0
4428+ map = self.config.AUTOMATIC_BACKUP_MODES
4429+ self.rev_automatic_backup_modes = {}
4430+ keys = map.keys()
4431+ keys.sort()
4432+ for key in keys:
4433+ self.rev_automatic_backup_modes[ map[key] ] = key
4434+ self.store_backup_mode.append( [ map[key], key ] )
4435+
4436+ #per directory schedule
4437+ self.cb_per_directory_schedule = get( 'cb_per_directory_schedule' )
4438+ self.lbl_schedule = get( 'lbl_schedule' )
4439+
4440+ #setup include folders
4441+ self.list_include = get( 'list_include' )
4442+
4443+ pix_renderer = gtk.CellRendererPixbuf()
4444+ text_renderer = gtk.CellRendererText()
4445+
4446+ column = gtk.TreeViewColumn( _('Include folders') )
4447+ column.pack_start( pix_renderer, False )
4448+ column.pack_end( text_renderer, True )
4449+ column.add_attribute( pix_renderer, 'stock-id', 1 )
4450+ column.add_attribute( text_renderer, 'markup', 0 )
4451+ self.list_include.append_column( column )
4452+
4453+ column = gtk.TreeViewColumn( _('Schedule') )
4454+ combo_renderer = gtk.CellRendererCombo()
4455+ combo_renderer.set_property( 'editable', True )
4456+ combo_renderer.set_property( 'has-entry', False )
4457+ combo_renderer.set_property( 'model', self.store_backup_mode )
4458+ combo_renderer.set_property( 'text-column', 0 )
4459+ combo_renderer.connect( 'edited', self.on_automatic_backup_mode_changed )
4460+ column.pack_end( combo_renderer, True )
4461+ column.add_attribute( combo_renderer, 'text', 2 )
4462+
4463+ self.include_schedule_column = column
4464+
4465+ self.store_include = gtk.ListStore( str, str, str, int )
4466+ self.list_include.set_model( self.store_include )
4467+
4468+ #setup exclude patterns
4469+ self.list_exclude = get( 'list_exclude' )
4470+
4471+ pix_renderer = gtk.CellRendererPixbuf()
4472+ text_renderer = gtk.CellRendererText()
4473+
4474+ column = gtk.TreeViewColumn( _('Patterns, files or folders') )
4475+ column.pack_start( pix_renderer, False )
4476+ column.pack_end( text_renderer, True )
4477+ column.add_attribute( pix_renderer, 'stock-id', 1 )
4478+ column.add_attribute( text_renderer, 'markup', 0 )
4479+ self.list_exclude.append_column( column )
4480+
4481+ self.store_exclude = gtk.ListStore( str, str )
4482+ self.list_exclude.set_model( self.store_exclude )
4483+
4484+ #setup automatic backup mode
4485+ self.cb_backup_mode = get( 'cb_backup_mode' )
4486+ self.cb_backup_mode.set_model( self.store_backup_mode )
4487+
4488+ self.cb_backup_mode.clear()
4489+ renderer = gtk.CellRendererText()
4490+ self.cb_backup_mode.pack_start( renderer, True )
4491+ self.cb_backup_mode.add_attribute( renderer, 'text', 0 )
4492+
4493+ #setup remove old backups older than
4494+ self.edit_remove_old_backup_value = get( 'edit_remove_old_backup_value' )
4495+ self.cb_remove_old_backup_unit = get( 'cb_remove_old_backup_unit' )
4496+
4497+ self.store_remove_old_backup_unit = gtk.ListStore( str, int )
4498+ self.cb_remove_old_backup_unit.set_model( self.store_remove_old_backup_unit )
4499+
4500+ renderer = gtk.CellRendererText()
4501+ self.cb_remove_old_backup_unit.pack_start( renderer, True )
4502+ self.cb_remove_old_backup_unit.add_attribute( renderer, 'text', 0 )
4503+
4504+ self.store_remove_old_backup_unit.clear()
4505+ map = self.config.REMOVE_OLD_BACKUP_UNITS
4506+ keys = map.keys()
4507+ keys.sort()
4508+ for key in keys:
4509+ self.store_remove_old_backup_unit.append( [ map[ key ], key ] )
4510+
4511+ self.cb_remove_old_backup = get( 'cb_remove_old_backup' )
4512+
4513+ #setup min free space
4514+ self.edit_min_free_space_value = get( 'edit_min_free_space_value' )
4515+ self.cb_min_free_space_unit = get( 'cb_min_free_space_unit' )
4516+
4517+ self.store_min_free_space_unit = gtk.ListStore( str, int )
4518+ self.cb_min_free_space_unit.set_model( self.store_min_free_space_unit )
4519+
4520+ renderer = gtk.CellRendererText()
4521+ self.cb_min_free_space_unit.pack_start( renderer, True )
4522+ self.cb_min_free_space_unit.add_attribute( renderer, 'text', 0 )
4523+
4524+ self.store_min_free_space_unit.clear()
4525+ map = self.config.MIN_FREE_SPACE_UNITS
4526+ keys = map.keys()
4527+ keys.sort()
4528+ for key in keys:
4529+ self.store_min_free_space_unit.append( [ map[ key ], key ] )
4530+
4531+ self.cb_min_free_space = get( 'cb_min_free_space' )
4532+
4533+ #don't remove named snapshots
4534+ self.cb_dont_remove_named_snapshots = get( 'cb_dont_remove_named_snapshots' )
4535+ self.cb_dont_remove_named_snapshots.set_active( self.config.get_dont_remove_named_snapshots() )
4536+
4537+ #smart remove
4538+ self.cb_smart_remove = get( 'cb_smart_remove' )
4539+
4540+ #enable notifications
4541+ self.cb_enable_notifications = get( 'cb_enable_notifications' )
4542+
4543+ self.update_profiles()
4544+
4545+ def error_handler( self, message ):
4546+ messagebox.show_error( self.dialog, self.config, message )
4547+
4548+ def question_handler( self, message ):
4549+ return gtk.RESPONSE_YES == messagebox.show_question( self.dialog, self.config, message )
4550+
4551+ def on_automatic_backup_mode_changed( self, renderer, path, new_text ):
4552+ iter = self.store_include.get_iter(path)
4553+ self.store_include.set_value( iter, 2, new_text )
4554+ self.store_include.set_value( iter, 3, self.rev_automatic_backup_modes[new_text] )
4555+
4556+ def on_btn_where_clicked( self, button ):
4557+ path = self.edit_where.get_text()
4558+
4559+ fcd = gtk.FileChooserDialog( _('Snapshots folder'), self.dialog, gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER, (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK) )
4560+ if len( path ) > 0:
4561+ fcd.set_filename( path )
4562+
4563+ if fcd.run() == gtk.RESPONSE_OK:
4564+ new_path = tools.prepare_path( fcd.get_filename() )
4565+ fcd.destroy()
4566+ if len( path ) > 0 and new_path != path:
4567+ if not self.question_handler( _('Are you sure you want to change snapshots folder ?') ):
4568+ return
4569+ self.edit_where.set_text( new_path )
4570+ else:
4571+ fcd.destroy()
4572+
4573+ def on_combo_profiles_changed( self, *params ):
4574+ if self.disable_combo_changed:
4575+ return
4576+
4577+ iter = self.combo_profiles.get_active_iter()
4578+ if iter is None:
4579+ return
4580+
4581+ profile_id = self.store_profiles.get_value( iter, 1 )
4582+ if profile_id != self.config.get_current_profile():
4583+ self.save_profile()
4584+ self.config.set_current_profile( profile_id )
4585+
4586+ self.update_profile()
4587+
4588+ def update_profiles( self ):
4589+ self.disable_combo_changed = True
4590+
4591+ profiles = self.config.get_profiles_sorted_by_name()
4592+
4593+ select_iter = None
4594+ self.store_profiles.clear()
4595+
4596+ for profile_id in profiles:
4597+ iter = self.store_profiles.append( [ self.config.get_profile_name( profile_id ), profile_id ] )
4598+ if profile_id == self.config.get_current_profile():
4599+ select_iter = iter
4600+
4601+ self.disable_combo_changed = False
4602+
4603+ if not select_iter is None:
4604+ self.combo_profiles.set_active_iter( select_iter )
4605+
4606+ def update_profile( self ):
4607+ if self.config.get_current_profile() == '1':
4608+ self.btn_edit_profile.set_sensitive( False )
4609+ self.btn_remove_profile.set_sensitive( False )
4610+ else:
4611+ self.btn_edit_profile.set_sensitive( True )
4612+ self.btn_remove_profile.set_sensitive( True )
4613+
4614+ #set current folder
4615+ #self.fcb_where.set_filename( self.config.get_snapshots_path() )
4616+ self.edit_where.set_text( self.config.get_snapshots_path() )
4617+
4618+ #per directory schedule
4619+ self.cb_per_directory_schedule.set_active( self.config.get_per_directory_schedule() )
4620+
4621+ #setup include folders
4622+ self.update_per_directory_option()
4623+
4624+ self.store_include.clear()
4625+ include_folders = self.config.get_include_folders()
4626+ if len( include_folders ) > 0:
4627+ for include_folder in include_folders:
4628+ self.store_include.append( [include_folder[0], gtk.STOCK_DIRECTORY, self.config.AUTOMATIC_BACKUP_MODES[include_folder[1]], include_folder[1] ] )
4629+
4630+ #setup exclude patterns
4631+ self.store_exclude.clear()
4632+ exclude_patterns = self.config.get_exclude_patterns()
4633+ if len( exclude_patterns ) > 0:
4634+ for exclude_pattern in exclude_patterns:
4635+ self.store_exclude.append( [exclude_pattern, gtk.STOCK_DELETE] )
4636+
4637+ #setup automatic backup mode
4638+ i = 0
4639+ iter = self.store_backup_mode.get_iter_first()
4640+ default_mode = self.config.get_automatic_backup_mode()
4641+ while not iter is None:
4642+ if self.store_backup_mode.get_value( iter, 1 ) == default_mode:
4643+ self.cb_backup_mode.set_active( i )
4644+ break
4645+ iter = self.store_backup_mode.iter_next( iter )
4646+ i = i + 1
4647+
4648+ #setup remove old backups older than
4649+ enabled, value, unit = self.config.get_remove_old_snapshots()
4650+
4651+ self.edit_remove_old_backup_value.set_value( float( value ) )
4652+
4653+ i = 0
4654+ iter = self.store_remove_old_backup_unit.get_iter_first()
4655+ while not iter is None:
4656+ if self.store_remove_old_backup_unit.get_value( iter, 1 ) == unit:
4657+ self.cb_remove_old_backup_unit.set_active( i )
4658+ break
4659+ iter = self.store_remove_old_backup_unit.iter_next( iter )
4660+ i = i + 1
4661+
4662+ self.cb_remove_old_backup.set_active( enabled )
4663+ self.update_remove_old_backups( self.cb_remove_old_backup )
4664+
4665+ #setup min free space
4666+ enabled, value, unit = self.config.get_min_free_space()
4667+
4668+ self.edit_min_free_space_value.set_value( float(value) )
4669+
4670+ i = 0
4671+ iter = self.store_min_free_space_unit.get_iter_first()
4672+ while not iter is None:
4673+ if self.store_min_free_space_unit.get_value( iter, 1 ) == unit:
4674+ self.cb_min_free_space_unit.set_active( i )
4675+ break
4676+ iter = self.store_min_free_space_unit.iter_next( iter )
4677+ i = i + 1
4678+
4679+ self.cb_min_free_space.set_active( enabled )
4680+ self.update_min_free_space( self.cb_min_free_space )
4681+
4682+ #don't remove named snapshots
4683+ self.cb_dont_remove_named_snapshots.set_active( self.config.get_dont_remove_named_snapshots() )
4684+
4685+ #smart remove
4686+ self.cb_smart_remove.set_active( self.config.get_smart_remove() )
4687+
4688+ #enable notifications
4689+ self.cb_enable_notifications.set_active( self.config.is_notify_enabled() )
4690+
4691+ #run 'nice' from cron
4692+ self.cb_run_nice_from_cron = self.builder.get_object('cb_run_nice_from_cron')
4693+ self.cb_run_nice_from_cron.set_active(self.config.is_run_nice_from_cron_enabled())
4694+
4695+ def save_profile( self ):
4696+ #snapshots path
4697+ snapshots_path = self.edit_where.get_text()
4698+
4699+ #hack
4700+ if snapshots_path.startswith( '//' ):
4701+ snapshots_path = snapshots_path[ 1 : ]
4702+
4703+ #include list
4704+ include_list = []
4705+ iter = self.store_include.get_iter_first()
4706+ while not iter is None:
4707+ include_list.append( ( self.store_include.get_value( iter, 0 ), self.store_include.get_value( iter, 3 ) ) )
4708+ iter = self.store_include.iter_next( iter )
4709+
4710+ #exclude patterns
4711+ exclude_list = []
4712+ iter = self.store_exclude.get_iter_first()
4713+ while not iter is None:
4714+ exclude_list.append( self.store_exclude.get_value( iter, 0 ) )
4715+ iter = self.store_exclude.iter_next( iter )
4716+
4717+ #check if back folder changed
4718+ #if len( self.config.get_snapshots_path() ) > 0 and self.config.get_snapshots_path() != snapshots_path:
4719+ # if gtk.RESPONSE_YES != messagebox.show_question( self.dialog, self.config, _('Are you sure you want to change snapshots folder ?') ):
4720+ # return False
4721+
4722+ #ok let's save to config
4723+ self.config.set_snapshots_path( snapshots_path )
4724+ #if not msg is None:
4725+ # messagebox.show_error( self.dialog, self.config, msg )
4726+ # return False
4727+
4728+ self.config.set_include_folders( include_list )
4729+ self.config.set_exclude_patterns( exclude_list )
4730+
4731+ #global schedule
4732+ self.config.set_automatic_backup_mode( self.store_backup_mode.get_value( self.cb_backup_mode.get_active_iter(), 1 ) )
4733+
4734+ #auto-remove snapshots
4735+ self.config.set_remove_old_snapshots(
4736+ self.cb_remove_old_backup.get_active(),
4737+ int( self.edit_remove_old_backup_value.get_value() ),
4738+ self.store_remove_old_backup_unit.get_value( self.cb_remove_old_backup_unit.get_active_iter(), 1 ) )
4739+ self.config.set_min_free_space(
4740+ self.cb_min_free_space.get_active(),
4741+ int( self.edit_min_free_space_value.get_value() ),
4742+ self.store_min_free_space_unit.get_value( self.cb_min_free_space_unit.get_active_iter(), 1 ) )
4743+ self.config.set_dont_remove_named_snapshots( self.cb_dont_remove_named_snapshots.get_active() )
4744+ self.config.set_smart_remove( self.cb_smart_remove.get_active() )
4745+
4746+ #options
4747+ self.config.set_notify_enabled( self.cb_enable_notifications.get_active() )
4748+
4749+ #expert options
4750+ self.config.set_per_directory_schedule( self.cb_per_directory_schedule.get_active() )
4751+ self.config.set_run_nice_from_cron_enabled( self.cb_run_nice_from_cron.get_active() )
4752+
4753+ def update_remove_old_backups( self, button ):
4754+ enabled = self.cb_remove_old_backup.get_active()
4755+ self.edit_remove_old_backup_value.set_sensitive( enabled )
4756+ self.cb_remove_old_backup_unit.set_sensitive( enabled )
4757+
4758+ def update_min_free_space( self, button ):
4759+ enabled = self.cb_min_free_space.get_active()
4760+ self.edit_min_free_space_value.set_sensitive( enabled )
4761+ self.cb_min_free_space_unit.set_sensitive( enabled )
4762+
4763+ def on_cb_per_directory_schedule_toggled( self, button ):
4764+ self.update_per_directory_option()
4765+
4766+ def update_per_directory_option( self ):
4767+ if self.cb_per_directory_schedule.get_active():
4768+ if self.list_include.get_column(1) == None:
4769+ self.list_include.append_column( self.include_schedule_column )
4770+ self.cb_backup_mode.hide()
4771+ self.lbl_schedule.hide()
4772+ else:
4773+ if self.list_include.get_column(1) != None:
4774+ self.list_include.remove_column( self.include_schedule_column )
4775+ self.lbl_schedule.show()
4776+ self.cb_backup_mode.show()
4777+
4778+ def run( self ):
4779+ self.config.set_question_handler( self.question_handler )
4780+ self.config.set_error_handler( self.error_handler )
4781+
4782+ self.config_copy_dict = copy.copy( self.config.dict )
4783+ self.current_profile_org = self.config.get_current_profile()
4784+
4785+ while True:
4786+ if gtk.RESPONSE_OK == self.dialog.run():
4787+ if not self.validate():
4788+ continue
4789+ else:
4790+ self.config.dict = self.config_copy_dict
4791+
4792+ break
4793+
4794+ self.config.set_current_profile( self.current_profile_org )
4795+ self.config.clear_handlers()
4796+
4797+ self.dialog.destroy()
4798+
4799+ def on_add_profile(self, button, data=None):
4800+
4801+ name = messagebox.text_input_dialog( self.dialog, self.config, _('New profile'), None )
4802+ if name is None:
4803+ return
4804+ if len( name ) <= 0:
4805+ return
4806+
4807+ if not self.config.add_profile( name ):
4808+ return
4809+
4810+ self.update_profiles()
4811+
4812+ def on_edit_profile( self, button ):
4813+ name = messagebox.text_input_dialog( self.dialog, self.config, _('Rename profile'), None )
4814+ if name is None:
4815+ return
4816+ if len( name ) <= 0:
4817+ return
4818+
4819+ if not self.config.set_profile_name( name ):
4820+ return
4821+
4822+ self.update_profiles()
4823+
4824+ def on_remove_profile( self, button ):
4825+ if gtk.RESPONSE_YES == messagebox.show_question( self.dialog, self.config, _('Are you sure you want to delete the profile "%s" ?') % self.config.get_profile_name() ):
4826+ self.config.remove_profile()
4827+ self.update_profiles()
4828+
4829+ def on_add_include( self, button ):
4830+ fcd = gtk.FileChooserDialog( _('Include folder'), self.dialog, gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER, (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK) )
4831+ fcd.set_show_hidden( self.parent.show_hidden_files )
4832+
4833+ if fcd.run() == gtk.RESPONSE_OK:
4834+ include_folder = tools.prepare_path( fcd.get_filename() )
4835+
4836+ iter = self.store_include.get_iter_first()
4837+ while not iter is None:
4838+ if self.store_include.get_value( iter, 0 ) == include_folder:
4839+ break
4840+ iter = self.store_include.iter_next( iter )
4841+
4842+ if iter is None:
4843+ self.store_include.append( [include_folder, gtk.STOCK_DIRECTORY, self.config.AUTOMATIC_BACKUP_MODES[self.config.NONE], self.config.NONE ] )
4844+
4845+ fcd.destroy()
4846+
4847+ def on_remove_include( self, button ):
4848+ store, iter = self.list_include.get_selection().get_selected()
4849+ if not iter is None:
4850+ store.remove( iter )
4851+
4852+ def add_exclude_( self, pattern ):
4853+ pattern = pattern.strip()
4854+ if len( pattern ) == 0:
4855+ return
4856+
4857+ iter = self.store_exclude.get_iter_first()
4858+ while not iter is None:
4859+ if self.store_exclude.get_value( iter, 0 ) == pattern:
4860+ return
4861+ iter = self.store_exclude.iter_next( iter )
4862+
4863+ self.store_exclude.append( [pattern, gtk.STOCK_DELETE] )
4864+
4865+ def on_add_exclude( self, button ):
4866+ pattern = messagebox.text_input_dialog( self.dialog, self.config, _('Exclude pattern') )
4867+ if pattern is None:
4868+ return
4869+
4870+ if pattern.find( ':' ) >= 0:
4871+ messagebox.show_error( self.dialog, self.config, _('Exclude patterns can\'t contain \':\' char !') )
4872+ return
4873+
4874+ self.add_exclude_( pattern )
4875+
4876+ def on_add_exclude_file( self, button ):
4877+ fcd = gtk.FileChooserDialog( _('Exclude file'), self.dialog, gtk.FILE_CHOOSER_ACTION_OPEN, (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK) )
4878+ fcd.set_show_hidden( self.parent.show_hidden_files )
4879+
4880+ if fcd.run() == gtk.RESPONSE_OK:
4881+ pattern = tools.prepare_path( fcd.get_filename() )
4882+ self.add_exclude_( pattern )
4883+
4884+ fcd.destroy()
4885+
4886+ def on_add_exclude_folder( self, button ):
4887+ fcd = gtk.FileChooserDialog( _('Exclude folder'), self.dialog, gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER, (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK) )
4888+ fcd.set_show_hidden( self.parent.show_hidden_files )
4889+
4890+ if fcd.run() == gtk.RESPONSE_OK:
4891+ pattern = tools.prepare_path( fcd.get_filename() )
4892+ self.add_exclude_( pattern )
4893+
4894+ fcd.destroy()
4895+
4896+ def on_remove_exclude( self, button ):
4897+ store, iter = self.list_exclude.get_selection().get_selected()
4898+ if not iter is None:
4899+ store.remove( iter )
4900+
4901+ def on_cancel( self, button ):
4902+ self.dialog.destroy()
4903+
4904+ def validate( self ):
4905+ self.save_profile()
4906+
4907+ if not self.config.check_config():
4908+ return False
4909+
4910+ if not self.config.setup_cron():
4911+ return False
4912+
4913+ self.config.save()
4914+ return True
4915+
4916
4917=== modified file 'gnome/snapshotsdialog.glade'
4918--- gnome/snapshotsdialog.glade 2009-04-27 13:43:00 +0000
4919+++ gnome/snapshotsdialog.glade 2009-10-01 16:35:20 +0000
4920@@ -1,176 +1,176 @@
4921-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
4922-<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
4923-<!--Generated with glade3 3.4.5 on Mon Apr 27 12:51:19 2009 -->
4924-<glade-interface>
4925- <widget class="GtkDialog" id="SnapshotsDialog">
4926+<?xml version="1.0"?>
4927+<interface>
4928+ <requires lib="gtk+" version="2.16"/>
4929+ <!-- interface-naming-policy toplevel-contextual -->
4930+ <object class="GtkDialog" id="SnapshotsDialog">
4931 <property name="border_width">5</property>
4932 <property name="title" translatable="yes">Snapshots</property>
4933 <property name="modal">True</property>
4934- <property name="window_position">GTK_WIN_POS_CENTER_ON_PARENT</property>
4935- <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
4936+ <property name="window_position">center-on-parent</property>
4937+ <property name="type_hint">dialog</property>
4938 <property name="skip_taskbar_hint">True</property>
4939 <property name="skip_pager_hint">True</property>
4940- <property name="transient_for">MainWindow</property>
4941 <property name="has_separator">False</property>
4942 <child internal-child="vbox">
4943- <widget class="GtkVBox" id="dialog-vbox3">
4944+ <object class="GtkVBox" id="dialog-vbox3">
4945 <property name="visible">True</property>
4946 <property name="spacing">2</property>
4947 <child>
4948- <widget class="GtkVBox" id="vbox3">
4949+ <object class="GtkVBox" id="vbox3">
4950 <property name="visible">True</property>
4951 <property name="spacing">2</property>
4952 <child>
4953- <widget class="GtkEntry" id="edit_path">
4954+ <object class="GtkEntry" id="edit_path">
4955 <property name="visible">True</property>
4956 <property name="can_focus">True</property>
4957 <property name="editable">False</property>
4958- </widget>
4959+ </object>
4960 <packing>
4961 <property name="expand">False</property>
4962 <property name="padding">2</property>
4963+ <property name="position">0</property>
4964 </packing>
4965 </child>
4966 <child>
4967- <widget class="GtkToolbar" id="toolbar2">
4968+ <object class="GtkToolbar" id="toolbar2">
4969 <property name="visible">True</property>
4970 <child>
4971- <widget class="GtkToolButton" id="btn_copy_snapshot">
4972+ <object class="GtkToolButton" id="btn_copy_snapshot">
4973 <property name="visible">True</property>
4974- <property name="tooltip" translatable="yes">Copy</property>
4975+ <property name="tooltip_text" translatable="yes">Copy</property>
4976 <property name="label" translatable="yes">Copy</property>
4977 <property name="stock_id">gtk-copy</property>
4978 <signal name="clicked" handler="on_btn_copy_snapshot_clicked"/>
4979- </widget>
4980+ </object>
4981 <packing>
4982+ <property name="expand">False</property>
4983 <property name="homogeneous">True</property>
4984 </packing>
4985 </child>
4986 <child>
4987- <widget class="GtkToolButton" id="btn_restore_snapshot">
4988+ <object class="GtkToolButton" id="btn_restore_snapshot">
4989 <property name="visible">True</property>
4990- <property name="tooltip" translatable="yes">Restore</property>
4991+ <property name="tooltip_text" translatable="yes">Restore</property>
4992 <property name="label" translatable="yes">Restore</property>
4993 <property name="stock_id">gtk-undelete</property>
4994 <signal name="clicked" handler="on_btn_restore_snapshot_clicked"/>
4995- </widget>
4996+ </object>
4997 <packing>
4998+ <property name="expand">False</property>
4999 <property name="homogeneous">True</property>
5000 </packing>
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches