~ubuntu-branches/ubuntu/maverick/backintime/maverick

« back to all changes in this revision

Viewing changes to kde4/settingsdialog.py

  • Committer: Bazaar Package Importer
  • Author(s): Jonathan Wiltshire
  • Date: 2009-05-16 23:04:32 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20090516230432-orrutvtufbtuxsc6
Tags: 0.9.24-1
* New upstream version (closes: #527447):
  - backintime is no longer aware of 'backintime-gnome' and 'backintime-kde4'
    (you need run 'backintime-gnome' for GNOME version and 'backintime-kde4'
    for KDE4 version)
  - fix a bug that crashes the program after taking a snapshot
* Update homepage field in debian/control (closes: #527595)
* Refactor packaging to fit new upstream build system (an almost entire 
  re-write of debian/rules)
* Make configure scripts use /bin/sh instead of /bin/bash (they don't use
  bash features)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#    Back In Time
 
2
#    Copyright (C) 2008-2009 Oprea Dan
 
3
#
 
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.
 
8
#
 
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.
 
13
#
 
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.
 
17
 
 
18
 
 
19
import os
 
20
import os.path
 
21
import sys
 
22
import datetime
 
23
import gettext
 
24
 
 
25
from PyQt4.QtGui import *
 
26
from PyQt4.QtCore import *
 
27
from PyKDE4.kdecore import *
 
28
from PyKDE4.kdeui import *
 
29
from PyKDE4.kio import *
 
30
 
 
31
import config
 
32
import kde4tools
 
33
 
 
34
 
 
35
_=gettext.gettext
 
36
 
 
37
 
 
38
class PopupAutomaticBackupAction( KAction ):
 
39
        def __init__( self, list, id, label ):
 
40
                KAction.__init__( self, label, list )
 
41
                self.list = list
 
42
                self.id = id
 
43
                self.label = label
 
44
        
 
45
                QObject.connect( self, SIGNAL('triggered()'), self.on_selected )
 
46
 
 
47
        def on_selected( self ):
 
48
                item = self.list.currentItem()
 
49
                if not item is None:
 
50
                        item.setText( 1, QString.fromUtf8( self.label ) )
 
51
                        item.setData( 0, Qt.UserRole, QVariant( self.id ) )
 
52
 
 
53
 
 
54
class SettingsDialog( KDialog ):
 
55
        def __init__( self, parent ):
 
56
                KDialog.__init__( self, parent )
 
57
                self.config = parent.config
 
58
 
 
59
                self.setWindowIcon( KIcon( 'configure' ) )
 
60
                self.setCaption( QString.fromUtf8( _( 'Settings' ) ) )
 
61
 
 
62
                self.main_widget = KTabWidget( self )
 
63
                self.setMainWidget( self.main_widget )
 
64
 
 
65
                #TAB: General
 
66
                tab_widget = QWidget( self )
 
67
                self.main_widget.addTab( tab_widget, QString.fromUtf8( _( 'General' ) ) )
 
68
                layout = QVBoxLayout( tab_widget )
 
69
 
 
70
                #Where to save snapshots
 
71
                group_box = QGroupBox( self )
 
72
                group_box.setTitle( QString.fromUtf8( _( 'Where to save snapshots' ) ) )
 
73
                layout.addWidget( group_box )
 
74
 
 
75
                hlayout = QHBoxLayout( group_box )
 
76
 
 
77
                self.edit_snapshots_path = KLineEdit( QString.fromUtf8( self.config.get_snapshots_path() ), self )
 
78
                self.edit_snapshots_path.setReadOnly( True )
 
79
                hlayout.addWidget( self.edit_snapshots_path )
 
80
 
 
81
                self.btn_snapshots_path = KPushButton( KIcon( 'folder' ), '', self )
 
82
                hlayout.addWidget( self.btn_snapshots_path )
 
83
                QObject.connect( self.btn_snapshots_path, SIGNAL('clicked()'), self.on_btn_snapshots_path_clicked )
 
84
 
 
85
                #Schedule
 
86
                group_box = QGroupBox( self )
 
87
                self.global_schedule_group_box = group_box
 
88
                group_box.setTitle( QString.fromUtf8( _( 'Schedule' ) ) )
 
89
                layout.addWidget( group_box )
 
90
 
 
91
                hlayout = QHBoxLayout( group_box )
 
92
 
 
93
                self.combo_automatic_snapshots = KComboBox( self )
 
94
                hlayout.addWidget( self.combo_automatic_snapshots )
 
95
                self.fill_combo( self.combo_automatic_snapshots, self.config.AUTOMATIC_BACKUP_MODES, self.config.get_automatic_backup_mode() )
 
96
 
 
97
                #
 
98
                layout.addStretch()
 
99
                
 
100
                #TAB: Include
 
101
                tab_widget = QWidget( self )
 
102
                self.main_widget.addTab( tab_widget, QString.fromUtf8( _( 'Include' ) ) )
 
103
                layout = QVBoxLayout( tab_widget )
 
104
 
 
105
                self.list_include = QTreeWidget( self )
 
106
                self.list_include.setRootIsDecorated( False )
 
107
                #self.list_include.setEditTriggers( QAbstractItemView.NoEditTriggers )
 
108
                self.list_include.setHeaderLabels( [ QString.fromUtf8( _('Include folders') ), QString.fromUtf8( _('Automatic backup') ) ] )
 
109
                self.list_include.header().setResizeMode( 0, QHeaderView.Stretch )
 
110
 
 
111
                self.popup_automatic_backup = KMenu( self )
 
112
                keys = self.config.AUTOMATIC_BACKUP_MODES.keys()
 
113
                keys.sort()
 
114
                for key in keys:
 
115
                        self.popup_automatic_backup.addAction( PopupAutomaticBackupAction( self.list_include, key, QString.fromUtf8( self.config.AUTOMATIC_BACKUP_MODES[ key ] ) ) )
 
116
 
 
117
                QObject.connect( self.list_include, SIGNAL('itemActivated(QTreeWidgetItem*,int)'), self.on_list_include_item_activated )
 
118
                layout.addWidget( self.list_include )
 
119
 
 
120
                for include in self.config.get_include_folders():
 
121
                        self.add_include( include )
 
122
                
 
123
                buttons_layout = QHBoxLayout()
 
124
                layout.addLayout( buttons_layout )
 
125
 
 
126
                self.btn_include_add = KPushButton( KStandardGuiItem.add(), self )
 
127
                buttons_layout.addWidget( self.btn_include_add )
 
128
                QObject.connect( self.btn_include_add, SIGNAL('clicked()'), self.on_btn_include_add_clicked )
 
129
                
 
130
                self.btn_include_remove = KPushButton( KStandardGuiItem.remove(), self )
 
131
                buttons_layout.addWidget( self.btn_include_remove )
 
132
                QObject.connect( self.btn_include_remove, SIGNAL('clicked()'), self.on_btn_include_remove_clicked )
 
133
 
 
134
                #TAB: exclude
 
135
                tab_widget = QWidget( self )
 
136
                self.main_widget.addTab( tab_widget, QString.fromUtf8( _( 'Exclude' ) ) )
 
137
                layout = QVBoxLayout( tab_widget )
 
138
 
 
139
                self.list_exclude = KListWidget( self )
 
140
                layout.addWidget( self.list_exclude )
 
141
                
 
142
                for exclude in self.config.get_exclude_patterns():
 
143
                        self.add_exclude( exclude )
 
144
 
 
145
                buttons_layout = QHBoxLayout()
 
146
                layout.addLayout( buttons_layout )
 
147
 
 
148
                self.btn_exclude_add = KPushButton( KStandardGuiItem.add(), self )
 
149
                buttons_layout.addWidget( self.btn_exclude_add )
 
150
                QObject.connect( self.btn_exclude_add, SIGNAL('clicked()'), self.on_btn_exclude_add_clicked )
 
151
                
 
152
                self.btn_exclude_file = KPushButton( KStandardGuiItem.add(), self )
 
153
                self.btn_exclude_file.setText( QString.fromUtf8( _( 'Add file' ) ) )
 
154
                buttons_layout.addWidget( self.btn_exclude_file )
 
155
                QObject.connect( self.btn_exclude_file, SIGNAL('clicked()'), self.on_btn_exclude_file_clicked )
 
156
                
 
157
                self.btn_exclude_folder = KPushButton( KStandardGuiItem.add(), self )
 
158
                self.btn_exclude_folder.setText( QString.fromUtf8( _( 'Add folder' ) ) )
 
159
                buttons_layout.addWidget( self.btn_exclude_folder )
 
160
                QObject.connect( self.btn_exclude_folder, SIGNAL('clicked()'), self.on_btn_exclude_folder_clicked )
 
161
                
 
162
                self.btn_exclude_remove = KPushButton( KStandardGuiItem.remove(), self )
 
163
                buttons_layout.addWidget( self.btn_exclude_remove )
 
164
                QObject.connect( self.btn_exclude_remove, SIGNAL('clicked()'), self.on_btn_exclude_remove_clicked )
 
165
 
 
166
                #TAB: Auto-remove
 
167
                tab_widget = QWidget( self )
 
168
                self.main_widget.addTab( tab_widget, QString.fromUtf8( _( 'Auto-remove' ) ) )
 
169
                layout = QGridLayout( tab_widget )
 
170
 
 
171
                #remove old snapshots
 
172
                enabled, value, unit = self.config.get_remove_old_snapshots()
 
173
 
 
174
                self.cb_remove_older_then = QCheckBox( QString.fromUtf8( _( 'Older than:' ) ), self )
 
175
                layout.addWidget( self.cb_remove_older_then, 0, 0 )
 
176
                self.cb_remove_older_then.setChecked( enabled )
 
177
                QObject.connect( self.cb_remove_older_then, SIGNAL('stateChanged(int)'), self.update_remove_older_than )
 
178
 
 
179
                self.edit_remove_older_then = KIntSpinBox( 1, 1000, 1, value, self )
 
180
                layout.addWidget( self.edit_remove_older_then, 0, 1 )
 
181
 
 
182
                self.combo_remove_older_then = KComboBox( self )
 
183
                layout.addWidget( self.combo_remove_older_then, 0, 2 )
 
184
                self.fill_combo( self.combo_remove_older_then, self.config.REMOVE_OLD_BACKUP_UNITS, unit )
 
185
 
 
186
                #min free space
 
187
                enabled, value, unit = self.config.get_min_free_space()
 
188
 
 
189
                self.cb_min_free_space = QCheckBox( QString.fromUtf8( _( 'If free space is less than:' ) ), self )
 
190
                layout.addWidget( self.cb_min_free_space, 1, 0 )
 
191
                self.cb_min_free_space.setChecked( enabled )
 
192
                QObject.connect( self.cb_min_free_space, SIGNAL('stateChanged(int)'), self.update_min_free_space )
 
193
 
 
194
                self.edit_min_free_space = KIntSpinBox( 1, 1000, 1, value, self )
 
195
                layout.addWidget( self.edit_min_free_space, 1, 1 )
 
196
 
 
197
                self.combo_min_free_space = KComboBox( self )
 
198
                layout.addWidget( self.combo_min_free_space, 1, 2 )
 
199
                self.fill_combo( self.combo_min_free_space, self.config.MIN_FREE_SPACE_UNITS, unit )
 
200
 
 
201
                #smart remove
 
202
                self.cb_smart_remove = QCheckBox( QString.fromUtf8( _( 'Smart remove' ) ), self )
 
203
                layout.addWidget( self.cb_smart_remove, 2, 0 )
 
204
                self.cb_smart_remove.setChecked( self.config.get_smart_remove() )
 
205
 
 
206
                label = QLabel( QString.fromUtf8( _( '- keep all snapshots from today and yesterday\n- keep one snapshot for the last week and one for two weeks ago\n- keep one snapshot per month for all previous months of this year\n- keep one snapshot per year for all previous years' ) ),self )
 
207
                label.setContentsMargins( 25, 0, 0, 0 )
 
208
                layout.addWidget( label, 3, 0 )
 
209
 
 
210
                #don't remove named snapshots
 
211
                self.cb_dont_remove_named_snapshots = QCheckBox( QString.fromUtf8( _( 'Don\'t remove named snapshots' ) ), self )
 
212
                layout.addWidget( self.cb_dont_remove_named_snapshots, 4, 0 )
 
213
                self.cb_dont_remove_named_snapshots.setChecked( self.config.get_dont_remove_named_snapshots() )
 
214
 
 
215
                #
 
216
                layout.addWidget( QWidget(), 5, 0 )
 
217
                layout.setRowStretch( 5, 2 )
 
218
                
 
219
                #TAB: Options
 
220
                tab_widget = QWidget( self )
 
221
                self.main_widget.addTab( tab_widget, QString.fromUtf8( _( 'Options' ) ) )
 
222
                layout = QVBoxLayout( tab_widget )
 
223
 
 
224
                self.cb_notify_enabled = QCheckBox( QString.fromUtf8( _( 'Enable notifications' ) ), self )
 
225
                layout.addWidget( self.cb_notify_enabled )
 
226
                self.cb_notify_enabled.setChecked( self.config.is_notify_enabled() )
 
227
 
 
228
                #
 
229
                layout.addStretch()
 
230
 
 
231
                #TAB: Expert Options
 
232
                tab_widget = QWidget( self )
 
233
                self.main_widget.addTab( tab_widget, QString.fromUtf8( _( 'Expert Options' ) ) )
 
234
                layout = QVBoxLayout( tab_widget )
 
235
 
 
236
                label = QLabel( QString.fromUtf8( _('Change this options only if you really know what you are doing !') ), self )
 
237
                kde4tools.set_font_bold( label )
 
238
                layout.addWidget( label )
 
239
 
 
240
                self.cb_per_diretory_schedule = QCheckBox( QString.fromUtf8( _( 'Enable schedule per included directory (see Include tab; default: disabled)' ) ), self )
 
241
                layout.addWidget( self.cb_per_diretory_schedule )
 
242
                self.cb_per_diretory_schedule.setChecked( self.config.get_per_directory_schedule() )
 
243
                QObject.connect( self.cb_per_diretory_schedule, SIGNAL('clicked()'), self.update_include_columns )
 
244
 
 
245
                #
 
246
                layout.addStretch()
 
247
 
 
248
                self.update_include_columns()
 
249
 
 
250
                self.update_remove_older_than()
 
251
                self.update_min_free_space()
 
252
 
 
253
        def update_include_columns( self ):
 
254
                if self.cb_per_diretory_schedule.isChecked():
 
255
                        self.list_include.showColumn( 1 )
 
256
                        self.global_schedule_group_box.hide()
 
257
                else:
 
258
                        self.list_include.hideColumn( 1 )
 
259
                        self.global_schedule_group_box.show()
 
260
 
 
261
        def on_list_include_item_activated( self, item, column ):
 
262
                if not self.cb_per_diretory_schedule.isChecked():
 
263
                        return
 
264
                
 
265
                if item is None:
 
266
                        return
 
267
 
 
268
                #if column != 1:
 
269
                #       return
 
270
 
 
271
                self.popup_automatic_backup.popup( QCursor.pos() )
 
272
 
 
273
        def on_popup_automatic_backup( self ):
 
274
                print "ABC"
 
275
 
 
276
        def update_remove_older_than( self ):
 
277
                enabled = self.cb_remove_older_then.isChecked()
 
278
                self.edit_remove_older_then.setEnabled( enabled )
 
279
                self.combo_remove_older_then.setEnabled( enabled )
 
280
 
 
281
        def update_min_free_space( self ):
 
282
                enabled = self.cb_min_free_space.isChecked()
 
283
                self.edit_min_free_space.setEnabled( enabled )
 
284
                self.combo_min_free_space.setEnabled( enabled )
 
285
 
 
286
        def add_include( self, data ):
 
287
                item = QTreeWidgetItem()
 
288
                item.setText( 0, QString.fromUtf8( data[0] ) )
 
289
                item.setText( 1, QString.fromUtf8( self.config.AUTOMATIC_BACKUP_MODES[ data[1] ] ) )
 
290
                item.setData( 0, Qt.UserRole, QVariant( data[1]) )
 
291
                self.list_include.addTopLevelItem( item )
 
292
 
 
293
                if self.list_include.currentItem() is None:
 
294
                        self.list_include.setCurrentItem( item )
 
295
 
 
296
                return item
 
297
 
 
298
        def add_exclude( self, pattern ):
 
299
                item = QListWidgetItem( KIcon('edit-delete'), pattern, self.list_exclude )
 
300
 
 
301
                if self.list_exclude.currentItem() is None:
 
302
                        self.list_exclude.setCurrentItem( item )
 
303
 
 
304
                return item
 
305
 
 
306
        def fill_combo( self, combo, dict, default_value ):
 
307
                keys = dict.keys()
 
308
                keys.sort()
 
309
                index = 0
 
310
 
 
311
                for key in keys:
 
312
                        combo.addItem( QIcon(), QString.fromUtf8( dict[ key ] ), QVariant( key ) )
 
313
                        if key == default_value:
 
314
                                combo.setCurrentIndex( index )
 
315
                        index = index + 1
 
316
 
 
317
        def validate( self ):
 
318
                #snapshots path
 
319
                snapshots_path = str( self.edit_snapshots_path.text().toUtf8() )
 
320
 
 
321
                #include list 
 
322
                include_list = []
 
323
                for index in xrange( self.list_include.topLevelItemCount() ):
 
324
                        item = self.list_include.topLevelItem( index )
 
325
                        include_list.append( [ str( item.text(0).toUtf8() ), item.data( 0, Qt.UserRole ).toInt()[0] ] )
 
326
 
 
327
                #exclude patterns
 
328
                exclude_list = []
 
329
                for index in xrange( self.list_exclude.count() ):
 
330
                        exclude_list.append( str( self.list_exclude.item( index ).text().toUtf8() ) )
 
331
 
 
332
                #check params
 
333
                check_ret_val = self.config.check_take_snapshot_params( snapshots_path, include_list, exclude_list )
 
334
                if not check_ret_val is None:
 
335
                        err_id, err_msg = check_ret_val
 
336
                        KMessageBox.error( self, QString.fromUtf8( err_msg ) )
 
337
                        return False
 
338
 
 
339
                #check if back folder changed
 
340
                if len( self.config.get_snapshots_path() ) > 0 and self.config.get_snapshots_path() != snapshots_path:
 
341
                        if KMessageBox.Yes != KMessageBox.warningYesNo( self, QString.fromUtf8( _('Are you sure you want to change snapshots directory ?') ) ):
 
342
                                return False 
 
343
 
 
344
                #ok let's save to config
 
345
                msg = self.config.set_snapshots_path( snapshots_path )
 
346
                if not msg is None:
 
347
                        KMessageBox.error( self, QString.fromUtf8( msg ) )
 
348
                        return False
 
349
 
 
350
                self.config.set_include_folders( include_list )
 
351
                self.config.set_exclude_patterns( exclude_list )
 
352
 
 
353
                #schedule
 
354
                self.config.set_automatic_backup_mode( self.combo_automatic_snapshots.itemData( self.combo_automatic_snapshots.currentIndex() ).toInt()[0] )
 
355
 
 
356
                #auto-remove
 
357
                self.config.set_remove_old_snapshots( 
 
358
                                                self.cb_remove_older_then.isChecked(), 
 
359
                                                self.edit_remove_older_then.value(),
 
360
                                                self.combo_remove_older_then.itemData( self.combo_remove_older_then.currentIndex() ).toInt()[0] )
 
361
                self.config.set_min_free_space( 
 
362
                                                self.cb_min_free_space.isChecked(), 
 
363
                                                self.edit_min_free_space.value(),
 
364
                                                self.combo_min_free_space.itemData( self.combo_min_free_space.currentIndex() ).toInt()[0] )
 
365
                self.config.set_dont_remove_named_snapshots( self.cb_dont_remove_named_snapshots.isChecked() )
 
366
                self.config.set_smart_remove( self.cb_smart_remove.isChecked() )
 
367
 
 
368
                #options
 
369
                self.config.set_notify_enabled( self.cb_notify_enabled.isChecked() )
 
370
 
 
371
                #expert options
 
372
                self.config.set_per_directory_schedule( self.cb_per_diretory_schedule.isChecked() )
 
373
 
 
374
                self.config.save()
 
375
                
 
376
                msg = self.config.setup_cron()
 
377
                if not msg is None:
 
378
                        KMessageBox.error( self, QString.fromUtf8( msg ) )
 
379
                        return False
 
380
 
 
381
                return True
 
382
 
 
383
        def on_btn_exclude_remove_clicked ( self ):
 
384
                self.list_exclude.takeItem( self.list_exclude.currentRow() )
 
385
 
 
386
                if self.list_exclude.count() > 0:
 
387
                        self.list_exclude.setCurrentItem( self.list_exclude.item(0) )
 
388
 
 
389
        def add_exclude_( self, pattern ):
 
390
                if len( pattern ) == 0:
 
391
                        return
 
392
 
 
393
                for index in xrange( self.list_exclude.count() ):
 
394
                        if pattern == self.list_exclude.item( index ).text():
 
395
                                return
 
396
 
 
397
                self.add_exclude( pattern )
 
398
        
 
399
        def on_btn_exclude_add_clicked( self ):
 
400
                ret_val = KInputDialog.getText( QString.fromUtf8( _( 'Exclude pattern' ) ), '', '', self )
 
401
                if not ret_val[1]:
 
402
                        return
 
403
                
 
404
                self.add_exclude_( str( ret_val[0].toUtf8() ).strip() )
 
405
 
 
406
        def on_btn_exclude_file_clicked( self ):
 
407
                path = str( KFileDialog.getOpenFileName( KUrl(), '', self, QString.fromUtf8( _( 'Exclude file' ) ) ).toUtf8() )
 
408
                self.add_exclude_( path )
 
409
 
 
410
        def on_btn_exclude_folder_clicked( self ):
 
411
                path = str( KFileDialog.getExistingDirectory( KUrl(), self, QString.fromUtf8( _( 'Exclude folder' ) ) ).toUtf8() )
 
412
                self.add_exclude_( path )
 
413
 
 
414
        def on_btn_include_remove_clicked ( self ):
 
415
                item = self.list_include.currentItem()
 
416
                if item is None:
 
417
                        return
 
418
 
 
419
                index = self.list_include.indexOfTopLevelItem( item )
 
420
                if index < 0:
 
421
                        return
 
422
 
 
423
                self.list_include.takeTopLevelItem( index )
 
424
 
 
425
                if self.list_include.topLevelItemCount() > 0:
 
426
                        self.list_include.setCurrentItem( self.list_include.topLevelItem(0) )
 
427
 
 
428
        def on_btn_include_add_clicked( self ):
 
429
                path = ( KFileDialog.getExistingDirectory( KUrl(), self, QString.fromUtf8( _( 'Include folder' ) ) ).toUtf8() )
 
430
                if len( path ) == 0 :
 
431
                        return
 
432
 
 
433
                path = self.config.prepare_path( path )
 
434
 
 
435
                for index in xrange( self.list_include.topLevelItemCount() ):
 
436
                        if path == str( self.list_include.topLevelItem( index ).text( 0 ).toUtf8() ):
 
437
                                return
 
438
 
 
439
                self.add_include( [ path, self.config.NONE ] )
 
440
 
 
441
        def on_btn_snapshots_path_clicked( self ):
 
442
                path = str( KFileDialog.getExistingDirectory( KUrl( self.edit_snapshots_path.text() ), self, QString.fromUtf8( _( 'Where to save snapshots' ) ) ).toUtf8() )
 
443
                if len( path ) > 0 :
 
444
                        self.edit_snapshots_path.setText( QString.fromUtf8( self.config.prepare_path( path ) ) )
 
445
 
 
446
        def accept( self ):
 
447
                if self.validate():
 
448
                        KDialog.accept( self )
 
449