2
# Copyright (C) 2008-2009 Oprea Dan
4
# This program is free software; you can redistribute it and/or modify
5
# it under the terms of the GNU General Public License as published by
6
# the Free Software Foundation; either version 2 of the License, or
7
# (at your option) any later version.
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
# GNU General Public License for more details.
14
# You should have received a copy of the GNU General Public License along
15
# with this program; if not, write to the Free Software Foundation, Inc.,
16
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24
if len( os.getenv( 'DISPLAY', '' ) ) == 0:
25
os.putenv( 'DISPLAY', ':0.0' )
40
sys.path = [os.path.join( os.path.dirname( os.path.abspath( os.path.dirname( __file__ ) ) ), 'common' )] + sys.path
46
import guiapplicationinstance
50
import snapshotsdialog
60
class AboutDialog( gtk.AboutDialog ):
61
def __init__( self, config, parent ):
62
gtk.AboutDialog.__init__( self )
64
self.connect( 'close', self.on_close )
65
self.connect( 'response', self.on_close )
67
self.set_transient_for( parent )
69
self.set_name( config.APP_NAME )
70
self.set_version( config.VERSION )
71
self.set_copyright( 'Copyright (C) 2008-2009 Oprea Dan' )
72
self.set_website( 'http://backintime.le-web.org' )
73
self.set_website_label( 'http://backintime.le-web.org' )
74
self.set_license( config.get_license() )
75
authors = config.get_authors()
76
if not authors is None:
77
self.set_authors( authors.split( '\n' ) )
79
extra_translations = _('about-translators').strip()
80
if extra_translations == 'about-translators':
81
extra_translations = ''
83
self.set_translator_credits( config.get_translations() + extra_translations )
85
def on_close( self, *params ):
90
def __init__( self, config, app_instance ):
92
self.app_instance = app_instance
93
self.snapshots = snapshots.Snapshots( config )
94
self.special_background_color = 'lightblue'
95
self.popup_menu = None
97
self.folder_path = None
100
self.last_take_snapshot_message = None
102
self.glade = gtk.glade.XML( os.path.join( self.config.get_app_path(), 'gnome', 'mainwindow.glade' ), None, 'backintime' )
105
'on_MainWindow_destroy' : gtk.main_quit,
106
'on_MainWindow_delete_event' : self.on_close,
107
'on_MainWindow_key_release_event': self.on_key_release_event,
108
'on_btn_exit_clicked' : self.on_close,
109
'on_btn_link_clicked' : self.on_btn_link_clicked,
110
'on_btn_help_clicked' : self.on_btn_help_clicked,
111
'on_btn_about_clicked' : self.on_btn_about_clicked,
112
'on_btn_settings_clicked' : self.on_btn_settings_clicked,
113
'on_btn_backup_clicked' : self.on_btn_backup_clicked,
114
'on_btn_update_snapshots_clicked' : self.on_btn_update_snapshots_clicked,
115
'on_btn_snapshot_name_clicked' : self.on_btn_snapshot_name_clicked,
116
'on_btn_remove_snapshot_clicked' : self.on_btn_remove_snapshot_clicked,
117
'on_btn_restore_clicked' : self.on_btn_restore_clicked,
118
'on_btn_copy_clicked' : self.on_btn_copy_clicked,
119
'on_btn_snapshots_clicked' : self.on_btn_snapshots_clicked,
120
'on_btn_hidden_files_toggled' : self.on_btn_hidden_files_toggled,
121
'on_list_places_cursor_changed' : self.on_list_places_cursor_changed,
122
'on_list_time_line_cursor_changed' : self.on_list_time_line_cursor_changed,
123
'on_btn_folder_up_clicked' : self.on_btn_fodler_up_clicked,
124
'on_list_folder_view_row_activated' : self.on_list_folder_view_row_activated,
125
'on_list_folder_view_popup_menu' : self.on_list_folder_view_popup_menu,
126
'on_list_folder_view_button_press_event': self.on_list_folder_view_button_press_event,
127
'on_list_folder_view_drag_data_get': self.on_list_folder_view_drag_data_get
130
self.glade.signal_autoconnect( signals )
132
self.window = self.glade.get_widget( 'MainWindow' )
133
self.window.set_title( self.config.APP_NAME )
136
self.icon_names = fileicons.GnomeFileIcons()
139
self.glade.get_widget( 'btn_current_path' ).set_expand( True )
140
self.glade.get_widget( 'tb_sep_item' ).set_expand( True )
143
self.lbl_snapshot = self.glade.get_widget( 'lbl_snapshot' )
146
self.status_bar = self.glade.get_widget( 'status_bar' )
147
self.status_bar.push( 0, _('Done') )
150
self.show_hidden_files = self.config.get_bool_value( 'gnome.show_hidden_files', False )
151
self.btn_hidden_files = self.glade.get_widget( 'btn_hidden_files' )
152
self.btn_hidden_files.set_active( self.show_hidden_files )
153
#self.btn_hidden_files.set_label( _('Hidden files') ) #!!!
156
self.list_places = self.glade.get_widget( 'list_places' )
158
pix_renderer = gtk.CellRendererPixbuf()
159
text_renderer = gtk.CellRendererText()
161
column = gtk.TreeViewColumn( _('Shortcuts') )
162
column.pack_start( pix_renderer, False )
163
column.pack_end( text_renderer, True )
164
column.add_attribute( pix_renderer, 'icon-name', 2 )
165
column.add_attribute( text_renderer, 'markup', 0 )
166
column.set_cell_data_func( pix_renderer, self.places_pix_renderer_function, None )
167
column.set_cell_data_func( text_renderer, self.places_text_renderer_function, None )
168
#column.set_alignment( 0.5 )
169
self.list_places.append_column( column )
172
self.store_places = gtk.ListStore( str, str, str )
173
self.list_places.set_model( self.store_places )
174
self.list_places.get_selection().set_select_function( self.places_select_function, self.store_places )
177
self.list_folder_view_widget = self.glade.get_widget( 'list_folder_view_widget' )
178
self.list_folder_view_shadow = self.glade.get_widget( 'list_folder_view_shadow' )
179
self.list_folder_view = self.glade.get_widget( 'list_folder_view' )
181
pix_renderer = gtk.CellRendererPixbuf()
182
text_renderer = gtk.CellRendererText()
184
column = gtk.TreeViewColumn( _('Name') )
185
column.pack_start( pix_renderer, False )
186
column.pack_end( text_renderer, True )
187
column.add_attribute( pix_renderer, 'icon-name', 2 )
188
column.add_attribute( text_renderer, 'markup', 0 )
189
column.set_expand( True )
190
column.set_sizing( gtk.TREE_VIEW_COLUMN_AUTOSIZE )
191
column.set_sort_column_id( 0 )
192
self.list_folder_view.append_column( column )
194
text_renderer = gtk.CellRendererText()
195
column = gtk.TreeViewColumn( _('Size') )
196
column.pack_end( text_renderer, True )
197
column.add_attribute( text_renderer, 'markup', 4 )
198
column.set_sort_column_id( 1 )
199
self.list_folder_view.append_column( column )
201
text_renderer = gtk.CellRendererText()
202
column = gtk.TreeViewColumn( _('Date') )
203
column.pack_end( text_renderer, True )
204
column.add_attribute( text_renderer, 'markup', 5 )
205
column.set_sort_column_id( 2 )
206
self.list_folder_view.append_column( column )
208
# display name, relative path, icon_name, type (0 - directory, 1 - file), size (str), date, size (int)
209
self.store_folder_view = gtk.ListStore( str, str, str, int, str, str, int )
210
self.store_folder_view.set_sort_func( 0, self.sort_folder_view_by_column, 0 ) #name
211
self.store_folder_view.set_sort_func( 1, self.sort_folder_view_by_column, 6 ) #size
212
self.store_folder_view.set_sort_func( 2, self.sort_folder_view_by_column, 5 ) #date
213
self.store_folder_view.set_sort_column_id( 0, gtk.SORT_ASCENDING )
215
self.list_folder_view.set_model( self.store_folder_view )
217
#setup time line view
218
self.list_time_line = self.glade.get_widget( 'list_time_line' )
220
text_renderer = gtk.CellRendererText()
221
column = gtk.TreeViewColumn( _('Snapshots'), text_renderer, markup = 0 )
222
column.set_cell_data_func( text_renderer, self.places_text_renderer_function, None )
223
self.list_time_line.append_column( column )
226
self.store_time_line = gtk.ListStore( str, str )
227
self.list_time_line.set_model( self.store_time_line )
228
self.list_time_line.get_selection().set_select_function( self.places_select_function, self.store_time_line )
229
self.update_time_line = False
231
#calculate specialBackgroundColor
232
style = self.list_time_line.get_style()
233
bg1 = style.bg[gtk.STATE_NORMAL]
234
bg2 = style.bg[gtk.STATE_SELECTED]
235
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()
237
#restore size & position
238
main_window_x = self.config.get_int_value( 'gnome.main_window.x', -1 )
239
main_window_y = self.config.get_int_value( 'gnome.main_window.y', -1 )
240
if main_window_x >= 0 and main_window_y >= 0:
241
self.window.move( main_window_x, main_window_y )
243
main_window_width = self.config.get_int_value( 'gnome.main_window.width', -1 )
244
main_window_height = self.config.get_int_value( 'gnome.main_window.height', -1 )
245
if main_window_width > 0 and main_window_height > 0:
246
self.window.resize( main_window_width, main_window_height )
248
main_window_hpaned1 = self.config.get_int_value( 'gnome.main_window.hpaned1', -1 )
249
main_window_hpaned2 = self.config.get_int_value( 'gnome.main_window.hpaned2', -1 )
250
if main_window_hpaned1 > 0 and main_window_hpaned2 > 0:
251
self.glade.get_widget('hpaned1').set_position( main_window_hpaned1 )
252
self.glade.get_widget('hpaned2').set_position( main_window_hpaned2 )
254
#prepare popup menu ids
256
[ ('backintime.open', _('Open'), 0, 0, 'backintime' ),
257
('backintime.copy', _('Copy'), 0, 0, 'backintime' ),
258
('backintime.snapshots', _('Snapshots'), 0, 0, 'backintime' ),
259
('backintime.diff', _('Diff'), 0, 0, 'backintime' ),
260
('backintime.restore', _('Restore'), 0, 0, 'backintime' ) ] )
264
gnometools.run_gtk_update_loop()
266
self.force_wait_lock_counter = 0
267
gobject.timeout_add( 1000, self.raise_application )
269
if not self.config.is_configured():
270
settingsdialog.SettingsDialog( self.config, self.window ).run()
272
if not self.config.is_configured():
275
if not self.config.can_backup():
276
messagebox.show_error( self.window, self.config, _('Can\'t find snapshots directory.\nIf it is on a removable drive please plug it and then press OK') )
278
self.update_all( True )
280
self.update_backup_info()
281
gobject.timeout_add( 1000, self.update_backup_info )
283
def sort_folder_view_by_column( self, treemodel, iter1, iter2, column ):
286
if self.store_folder_view.get_sort_column_id()[1] != gtk.SORT_ASCENDING:
289
type1 = self.store_folder_view.get_value( iter1, 3 )
290
type2 = self.store_folder_view.get_value( iter2, 3 )
292
if type1 == 0 and type2 != 0:
293
return -1 * ascending
295
if type1 != 0 and type2 == 0:
298
data1 = self.store_folder_view.get_value( iter1, column )
299
data2 = self.store_folder_view.get_value( iter2, column )
301
if type(data1) is str:
302
data1 = data1.upper()
304
if type(data2) is str:
305
data2 = data2.upper()
307
#print "sort_folder_view_by_column: " + str( data1 ) + " - " + str( data2 )
318
def get_default_startup_folder_and_file( self ):
319
last_path = self.config.get_str_value( 'gnome.last_path', '' )
320
if len(last_path) > 0 and os.path.isdir(last_path):
321
return ( last_path, None, False )
322
return ( '/', None, False )
324
def get_cmd_startup_folder_and_file( self, cmd ):
326
cmd = self.app_instance.raise_cmd
332
show_snapshots = False
334
for arg in cmd.split( '\n' ):
337
if arg == '-s' or arg == '--snapshots':
338
show_snapshots = True
351
path = os.path.expanduser( path )
352
path = os.path.abspath( path )
354
if os.path.isdir( path ):
356
show_snapshots = False
359
return ( os.path.dirname( path ), path, True )
361
return ( path, '', False )
363
if os.path.isfile( path ):
364
return ( os.path.dirname( path ), path, show_snapshots )
368
def get_startup_folder_and_file( self, cmd = None ):
369
startup_folder = self.get_cmd_startup_folder_and_file( cmd )
370
if startup_folder is None:
371
return self.get_default_startup_folder_and_file()
372
return startup_folder
374
def update_all( self, init ):
377
show_snapshots = False
379
self.folder_path, selected_file, show_snapshots = self.get_startup_folder_and_file()
380
self.snapshot_id = '/'
381
self.snapshots_list = []
384
self.fill_time_line( False )
385
self.update_folder_view( 1, selected_file, show_snapshots )
387
def places_pix_renderer_function( self, column, renderer, model, iter, user_data ):
388
if len( model.get_value( iter, 1 ) ) == 0:
389
renderer.set_property( 'visible', False )
391
renderer.set_property( 'visible', True )
393
def places_text_renderer_function( self, column, renderer, model, iter, user_data ):
394
if len( model.get_value( iter, 1 ) ) == 0:
395
renderer.set_property( 'cell-background-set', True )
396
renderer.set_property( 'cell-background', self.special_background_color )
398
renderer.set_property( 'cell-background-set', False )
400
def places_select_function( self, info, store ):
401
if len( store.get_value( store.get_iter( info[0] ), 1 ) ) == 0:
405
def raise_application( self ):
406
raise_cmd = self.app_instance.raise_command()
407
if raise_cmd is None:
410
print "Raise cmd: " + raise_cmd
411
self.window.present_with_time( int(time.time()) )
412
self.window.window.focus()
413
#self.window.present()
415
if len( raise_cmd ) == 0:
418
print "Check if the main window is the only top level visible window"
419
for window in gtk.window_list_toplevels():
420
if window.get_property( 'visible' ):
421
if window != self.window:
427
folder_and_file = self.get_cmd_startup_folder_and_file( raise_cmd )
428
if folder_and_file is None:
431
folder_path, file_name, show_snapshots = folder_and_file
434
self.snapshot_id = '/'
435
self.list_time_line.get_selection().select_iter( self.store_time_line.get_iter_first() )
437
#select the specified file
438
self.folder_path = folder_path
439
self.update_folder_view( 1, file_name, show_snapshots )
443
def update_backup_info( self, force_wait_lock = False ):
444
if None is self.glade.get_widget( 'btn_backup' ):
447
#print "forceWaitLock: %s" % forceWaitLock
450
self.force_wait_lock_counter = 10
452
busy = self.snapshots.is_busy()
454
self.force_wait_lock_counter = 0
456
if self.force_wait_lock_counter > 0:
457
self.force_wait_lock_counter = self.force_wait_lock_counter - 1
459
fake_busy = busy or self.force_wait_lock_counter > 0
460
self.glade.get_widget( 'btn_backup' ).set_sensitive( not fake_busy )
463
take_snapshot_message = None
466
take_snapshot_message = self.snapshots.get_take_snapshot_message()
468
if take_snapshot_message is None:
469
take_snapshot_message = ( 0, '...' )
471
if take_snapshot_message != self.last_take_snapshot_message:
472
self.last_take_snapshot_message = take_snapshot_message
473
self.status_bar.push( 0, _('Working:') + ' ' + self.last_take_snapshot_message[1].replace( '\n', ' ' ) )
475
if not self.update_time_line:
476
self.update_time_line = True
477
elif self.update_time_line:
478
self.update_time_line = False
479
snapshots_list = self.snapshots_list
481
self.fill_time_line()
483
#print "New backup: %s" % self.lastBackupList
484
#print "Last backup: %s" % lastBackupList
486
if snapshots_list != self.snapshots_list:
487
self.status_bar.push( 0, _('Done') )
489
self.status_bar.push( 0, _('Done, no backup needed') )
492
self.last_take_snapshot_message = None
496
def fill_places( self ):
497
self.store_places.clear()
500
self.store_places.append( [ "<b>%s</b>" % _('Global'), '', '' ] )
501
self.store_places.append( [ _('Root'), '/', gtk.STOCK_HARDDISK ] )
502
self.store_places.append( [ _('Home'), os.path.expanduser( '~' ), gtk.STOCK_HOME ] )
508
file = open( os.path.expanduser('~/.gtk-bookmarks') )
509
rawbookmarks = file.read()
515
for rawbookmark in rawbookmarks.split( '\n' ):
516
if rawbookmark.startswith( 'file://' ):
517
index = rawbookmark.find( ' ' )
519
bookmarks.append( ( gnomevfs.unescape_string_for_display( rawbookmark[ 7 : index ] ), rawbookmark[ index + 1 : ] ) )
521
index = rawbookmark.rfind( '/' )
523
bookmarks.append( ( gnomevfs.unescape_string_for_display( rawbookmark[ 7 : ] ), gnomevfs.unescape_string_for_display( rawbookmark[ index + 1 : ] ) ) )
525
if len( bookmarks ) > 0:
526
self.store_places.append( [ "<b>%s</b>" % _('Bookmarks'), '', '' ] )
527
for bookmark in bookmarks:
528
self.store_places.append( [ bookmark[1], bookmark[0], self.icon_names.get_icon(bookmark[0]) ] )
531
include_folders = self.config.get_include_folders()
532
if len( include_folders ) > 0:
533
if len( include_folders ) > 0:
534
self.store_places.append( [ "<b>%s</b>" % _('Backup Directories'), '', '' ] )
535
for folder in include_folders:
536
self.store_places.append( [ folder[0], folder[0], gtk.STOCK_SAVE ] )
538
def fill_time_line( self, update_folder_view = True ):
539
current_selection = '/'
540
iter = self.list_time_line.get_selection().get_selected()[1]
542
current_selection = self.store_time_line.get_value( iter, 1 )
544
self.store_time_line.clear()
545
self.store_time_line.append( [ gnometools.get_snapshot_display_markup( self.snapshots, '/' ), '/' ] )
547
self.snapshots_list = self.snapshots.get_snapshots_list()
550
now = datetime.date.today()
554
groups.append( (_('Today'), self.snapshots.get_snapshot_id( date ), []) )
557
date = now - datetime.timedelta( days = 1 )
558
groups.append( (_('Yesterday'), self.snapshots.get_snapshot_id( date ), []) )
561
date = now - datetime.timedelta( days = now.weekday() )
562
groups.append( (_('This week'), self.snapshots.get_snapshot_id( date ), []) )
565
date = now - datetime.timedelta( days = now.weekday() + 7 )
566
groups.append( (_('Last week'), self.snapshots.get_snapshot_id( date ), []) )
569
for snapshot_id in self.snapshots_list:
573
if snapshot_id >= group[1]:
574
group[2].append( snapshot_id )
579
year = int( snapshot_id[ 0 : 4 ] )
580
month = int( snapshot_id[ 4 : 6 ] )
581
date = datetime.date( year, month, 1 )
585
group_name = date.strftime( '%B' ).capitalize()
587
group_name = date.strftime( '%B, %Y' ).capitalize()
589
groups.append( ( group_name, self.snapshots.get_snapshot_id( date ), [ snapshot_id ]) )
593
if len( group[2] ) > 0:
594
self.store_time_line.append( [ "<b>%s</b>" % group[0], '' ] );
595
for snapshot_id in group[2]:
596
self.store_time_line.append( [ gnometools.get_snapshot_display_markup( self.snapshots, snapshot_id ), snapshot_id ] )
598
#select previous item
599
iter = self.store_time_line.get_iter_first()
600
while not iter is None:
601
if current_selection == self.store_time_line.get_value( iter, 1 ):
603
iter = self.store_time_line.iter_next( iter )
608
iter = self.store_time_line.get_iter_first()
610
self.list_time_line.get_selection().select_iter( iter )
612
if changed and update_folder_view:
613
self.update_folder_view( 2 )
615
def on_close( self, *params ):
616
main_window_x, main_window_y = self.window.get_position()
617
main_window_width, main_window_height = self.window.get_size()
618
main_window_hpaned1 = self.glade.get_widget('hpaned1').get_position()
619
main_window_hpaned2 = self.glade.get_widget('hpaned2').get_position()
621
self.config.set_int_value( 'gnome.main_window.x', main_window_x )
622
self.config.set_int_value( 'gnome.main_window.y', main_window_y )
623
self.config.set_int_value( 'gnome.main_window.width', main_window_width )
624
self.config.set_int_value( 'gnome.main_window.height', main_window_height )
625
self.config.set_int_value( 'gnome.main_window.hpaned1', main_window_hpaned1 )
626
self.config.set_int_value( 'gnome.main_window.hpaned2', main_window_hpaned2 )
627
self.config.set_str_value( 'gnome.last_path', self.folder_path )
628
self.config.set_bool_value( 'gnome.show_hidden_files', self.show_hidden_files )
631
self.window.destroy()
634
def on_list_time_line_cursor_changed( self, list ):
635
if list.get_selection().path_is_selected( list.get_cursor()[ 0 ] ):
636
self.update_folder_view( 2 )
638
def on_list_places_cursor_changed( self, list ):
639
if list.get_selection().path_is_selected( list.get_cursor()[ 0 ] ):
640
iter = list.get_selection().get_selected()[1]
641
folder_path = self.store_places.get_value( iter, 1 )
642
if folder_path != self.folder_path:
643
self.folder_path = folder_path
644
self.update_folder_view( 0 )
646
def on_list_folder_view_drag_data_get( self, widget, drag_context, selection_data, info, timestamp, user_param1 = None ):
647
iter = self.list_folder_view.get_selection().get_selected()[1]
649
path = self.store_folder_view.get_value( iter, 1 )
650
path = self.snapshots.get_snapshot_path_to( self.snapshot_id, path )
651
path = gnomevfs.escape_path_string( path )
652
selection_data.set_uris( [ 'file://' + path ] )
654
def on_list_folder_view_button_press_event( self, list, event ):
655
if event.button != 3:
658
if len( self.store_folder_view ) <= 0:
661
path = self.list_folder_view.get_path_at_pos( int( event.x ), int( event.y ) )
666
self.list_folder_view.get_selection().select_path( path )
667
self.show_folder_view_menu_popup( self.list_folder_view, event.button, event.time )
669
def on_list_folder_view_popup_menu( self, list ):
670
self.show_folder_view_menu_popup( list, 1, gtk.get_current_event_time() )
672
def show_folder_view_menu_popup( self, list, button, time ):
673
iter = list.get_selection().get_selected()[1]
678
self.popup_menu = gtk.Menu()
680
menu_item = gtk.ImageMenuItem( 'backintime.open' )
681
menu_item.set_image( gtk.image_new_from_icon_name( self.store_folder_view.get_value( iter, 2 ), gtk.ICON_SIZE_MENU ) )
682
menu_item.connect( 'activate', self.on_list_folder_view_open_item )
683
self.popup_menu.append( menu_item )
685
self.popup_menu.append( gtk.SeparatorMenuItem() )
687
menu_item = gtk.ImageMenuItem( 'backintime.copy' )
688
menu_item.set_image( gtk.image_new_from_stock( gtk.STOCK_COPY, gtk.ICON_SIZE_MENU ) )
689
menu_item.connect( 'activate', self.on_list_folder_view_copy_item )
690
self.popup_menu.append( menu_item )
692
menu_item = gtk.ImageMenuItem( 'backintime.snapshots' )
693
menu_item.set_image( gtk.image_new_from_stock( gtk.STOCK_INDEX, gtk.ICON_SIZE_MENU ) )
694
menu_item.connect( 'activate', self.on_list_folder_view_snapshots_item )
695
self.popup_menu.append( menu_item )
697
if len( self.snapshot_id ) > 1:
698
menu_item = gtk.ImageMenuItem( 'backintime.restore' )
699
menu_item.set_image( gtk.image_new_from_stock( gtk.STOCK_UNDELETE, gtk.ICON_SIZE_MENU ) )
700
menu_item.connect( 'activate', self.on_list_folder_view_restore_item )
701
self.popup_menu.append( menu_item )
703
self.popup_menu.show_all()
704
self.popup_menu.popup( None, None, None, button, time )
706
def on_list_folder_view_restore_item( self, widget, data = None ):
707
self.on_btn_restore_clicked( self.glade.get_widget( 'btn_restore' ) )
709
def on_list_folder_view_copy_item( self, widget, data = None ):
710
self.on_btn_copy_clicked( self.glade.get_widget( 'btn_copy' ) )
712
def on_list_folder_view_snapshots_item( self, widget, data = None ):
713
self.on_btn_snapshots_clicked( self.glade.get_widget( 'btn_snapshots' ) )
715
def on_list_folder_view_open_item( self, widget, data = None ):
716
iter = self.list_folder_view.get_selection().get_selected()[1]
720
path = self.store_folder_view.get_value( iter, 1 )
721
path = self.snapshots.get_snapshot_path_to( self.snapshot_id, path )
722
cmd = "gnome-open \"%s\" &" % path
726
def on_list_folder_view_row_activated( self, list, path, column ):
727
iter = list.get_selection().get_selected()[1]
728
path = self.store_folder_view.get_value( iter, 1 )
731
if 0 == self.store_folder_view.get_value( iter, 3 ):
732
self.folder_path = path
733
self.update_folder_view( 1 )
737
path = self.snapshots.get_snapshot_path_to( self.snapshot_id, path )
738
cmd = "gnome-open \"%s\" &" % path
742
def on_btn_fodler_up_clicked( self, button ):
743
if len( self.folder_path ) <= 1:
746
index = self.folder_path.rfind( '/' )
750
parent_path = self.folder_path[ : index ]
752
self.folder_path = parent_path
753
self.update_folder_view( 1 )
755
def on_btn_restore_clicked( self, button ):
756
iter = self.list_folder_view.get_selection().get_selected()[1]
758
button.set_sensitive( False )
759
gnometools.run_gtk_update_loop()
760
self.snapshots.restore( self.snapshot_id, self.store_folder_view.get_value( iter, 1 ) )
761
button.set_sensitive( True )
763
def on_btn_copy_clicked( self, button ):
764
iter = self.list_folder_view.get_selection().get_selected()[1]
768
path = self.store_folder_view.get_value( iter, 1 )
769
path = self.snapshots.get_snapshot_path_to( self.snapshot_id, path )
771
clipboardtools.clipboard_copy_path( path )
773
def on_btn_hidden_files_toggled( self, button ):
774
if self.folder_path is None:
777
self.show_hidden_files = button.get_active()
778
self.update_folder_view( 0 )
780
def on_btn_snapshots_clicked( self, button ):
781
iter = self.list_folder_view.get_selection().get_selected()[1]
785
path = self.store_folder_view.get_value( iter, 1 )
786
icon_name = self.store_folder_view.get_value( iter, 2 )
788
retVal = snapshotsdialog.SnapshotsDialog( self.snapshots, self.window, path, self.snapshots_list, self.snapshot_id, icon_name ).run()
790
#select the specified file
791
if not retVal is None:
792
iter = self.store_time_line.get_iter_first()
793
while not iter is None:
794
snapshot_id = self.store_time_line.get_value( iter, 1 )
795
if snapshot_id == retVal:
797
iter = self.store_time_line.iter_next( iter )
800
self.list_time_line.get_selection().select_iter( iter )
801
self.update_folder_view( 2 )
803
def on_btn_about_clicked( self, button ):
804
AboutDialog( self.config, self.window ).run()
807
gnome.help_display('backintime')
809
def on_btn_help_clicked( self, button ):
812
def on_btn_link_clicked( self, button ):
813
os.system( "gnome-open http://backintime.le-web.org &" )
815
def on_key_release_event( self, widget, event ):
816
if 'F1' == gtk.gdk.keyval_name( event.keyval ) and ( event.state & (gtk.gdk.CONTROL_MASK | gtk.gdk.MOD1_MASK) ) == 0:
819
def on_btn_settings_clicked( self, button ):
820
snapshots_path = self.config.get_snapshots_path()
821
include_folders = self.config.get_include_folders()
823
settingsdialog.SettingsDialog( self.config, self.window ).run()
825
if snapshots_path != self.config.get_snapshots_path() or include_folders != self.config.get_include_folders():
826
self.update_all( False )
828
def on_btn_snapshot_name_clicked( self, button ):
829
iter = self.list_time_line.get_selection().get_selected()[1]
833
snapshot_id = self.store_time_line.get_value( iter, 1 )
834
if len( snapshot_id ) <= 1:
837
old_name = self.snapshots.get_snapshot_name( snapshot_id )
838
new_name = messagebox.text_input_dialog( self.window, self.config, _('Snapshot Name'), old_name )
842
if old_name == new_name:
845
self.snapshots.set_snapshot_name( snapshot_id, new_name )
846
self.store_time_line.set_value( iter, 0, gnometools.get_snapshot_display_markup( self.snapshots, snapshot_id ) )
848
def on_btn_remove_snapshot_clicked( self, button ):
849
iter = self.list_time_line.get_selection().get_selected()[1]
853
snapshot_id = self.store_time_line.get_value( iter, 1 )
854
if len( snapshot_id ) <= 1:
857
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 ) ):
858
print "Remove Snapshot: %s" % snapshot_id
859
self.snapshots.remove_snapshot( snapshot_id )
860
self.fill_time_line()
862
def on_btn_backup_clicked( self, button ):
863
button.set_sensitive( False )
864
self.updatetime_line = True
866
if self.snapshots.is_busy():
867
self.update_backup_info()
870
backintime.take_snapshot_now_async()
871
self.update_backup_info( True )
873
def on_btn_update_snapshots_clicked( self, button ):
874
self.fill_time_line()
876
def update_folder_view( self, changed_from, selected_file = None, show_snapshots = False ): #0 - places, 1 - folder view, 2 - time_line
878
if 2 == changed_from:
879
iter = self.list_time_line.get_selection().get_selected()[1]
880
self.snapshot_id = self.store_time_line.get_value( iter, 1 )
881
#self.lblTime.set_markup( "<b>%s</b>" % backupTime )
885
if len( self.snapshot_id ) > 1:
886
name = self.snapshots.get_snapshot_display_id( self.snapshot_id )
887
text = _('Snapshot: %s') % name
888
tooltip = _('View the snapshot made at %s') % name
890
tooltip = _('View the current disk content')
893
self.lbl_snapshot.set_markup( ' <b>' + text + '</b> ' )
894
self.lbl_snapshot.set_tooltip_text( tooltip )
896
#update selected places item
897
if 1 == changed_from:
898
iter = self.store_places.get_iter_first()
899
while not iter is None:
900
place_path = self.store_places.get_value( iter, 1 )
901
if place_path == self.folder_path:
903
iter = self.store_places.iter_next( iter )
906
self.list_places.get_selection().unselect_all()
908
self.list_places.get_selection().select_iter( iter )
912
full_path = self.snapshots.get_snapshot_path_to( self.snapshot_id, self.folder_path )
915
folder_exists = os.path.isdir( full_path )
919
all_files = os.listdir( full_path )
925
for file in all_files:
929
if not self.show_hidden_files:
932
if file[ -1 ] == '~':
935
path = os.path.join( full_path, file )
941
file_stat = os.stat( path )
942
file_size = file_stat[stat.ST_SIZE]
943
file_date = file_stat[stat.ST_MTIME]
948
file_size_int = file_size
949
if file_size_int < 0:
953
file_size = 'unknown'
954
elif file_size < 1024:
955
file_size = str( file_size ) + ' bytes'
956
elif file_size < 1024 * 1024:
957
file_size = file_size / 1024
958
file_size = str( file_size ) + ' KB'
959
elif file_size < 1024 * 1024 * 1024:
960
file_size = file_size / ( 1024 * 1024 )
961
file_size = str( file_size ) + ' MB'
963
file_size = file_size / ( 1024 * 1024 * 1024 )
964
file_size = str( file_size ) + ' GB'
968
file_date = 'unknown'
970
file_date = datetime.datetime.fromtimestamp(file_date).isoformat(' ')
972
if os.path.isdir( path ):
973
files.append( [ file, file_size, file_date, self.icon_names.get_icon(path), file_size_int, 0 ] )
975
files.append( [ file, file_size, file_date, self.icon_names.get_icon(path), file_size_int, 1 ] )
977
#try to keep old selected file
978
if selected_file is None:
980
iter = self.list_folder_view.get_selection().get_selected()[1]
982
selected_file = self.store_folder_view.get_value( iter, 1 )
984
self.list_folder_view_widget.show()
985
self.list_folder_view_shadow.hide()
987
self.list_folder_view_widget.hide()
988
self.list_folder_view_shadow.show()
991
self.store_folder_view.clear()
995
rel_path = os.path.join( self.folder_path, item[0] )
996
new_iter = self.store_folder_view.append( [ item[0], rel_path, item[3], item[5], item[1], item[2], item[4] ] )
997
if selected_file == rel_path:
998
selected_iter = new_iter
1000
#select old item or the first item
1001
if len( files ) > 0:
1002
if selected_iter is None:
1003
selected_iter = self.store_folder_view.get_iter_first()
1004
self.list_folder_view.get_selection().select_iter( selected_iter )
1005
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 )
1007
self.list_folder_view.drag_source_unset()
1009
#update folderup button state
1010
self.glade.get_widget( 'btn_folder_up' ).set_sensitive( len( self.folder_path ) > 1 )
1012
#update restore button state
1013
self.glade.get_widget( 'btn_restore' ).set_sensitive( len( self.snapshot_id ) > 1 and len( self.store_folder_view ) > 0 )
1015
#update remove/name snapshot buttons
1016
self.glade.get_widget( 'btn_snapshot_name' ).set_sensitive( len( self.snapshot_id ) > 1 )
1017
self.glade.get_widget( 'btn_remove_snapshot' ).set_sensitive( len( self.snapshot_id ) > 1 )
1019
#update copy button state
1020
self.glade.get_widget( 'btn_copy' ).set_sensitive( len( self.store_folder_view ) > 0 )
1022
#update snapshots button state
1023
self.glade.get_widget( 'btn_snapshots' ).set_sensitive( len( self.store_folder_view ) > 0 )
1025
#display current folder
1026
self.glade.get_widget( 'edit_current_path' ).set_text( self.folder_path )
1030
self.on_btn_snapshots_clicked( None )
1033
def open_url( dialog, link, user_data ):
1034
os.system( "gnome-open \"%s\" &" % link )
1037
if __name__ == '__main__':
1038
cfg = backintime.start_app( 'backintime-gnome', ['-s', '--snapshots'] )
1041
if len( sys.argv ) > 1:
1042
raise_cmd = '\n'.join( sys.argv[ 1 : ] )
1044
app_instance = guiapplicationinstance.GUIApplicationInstance( cfg.get_app_instance_file(), raise_cmd )
1046
gnome_props = { gnome.PARAM_APP_DATADIR : '/usr/share' }
1047
gnome.program_init( 'backintime', cfg.VERSION, properties = gnome_props )
1049
gtk.about_dialog_set_url_hook( open_url, None )
1052
main_window = MainWindow( cfg, app_instance )
1053
if cfg.is_configured():
1057
app_instance.exit_application()