15
import rdiff_interface
16
from Dialogs import ErrorDialog
17
from filechooser import FileChooser
20
def __init__(self, bsetid=None):
21
self.exitnotify = None
23
self.widgets = gtk.glade.XML("%s/seteditor.glade"
24
% os.path.dirname(__file__))
25
except RuntimeError, e:
26
dlg = gtk.MessageDialog(None, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR,
27
gtk.BUTTONS_CLOSE,_("Unable to start the backup set editor"))
28
dlg.connect("response", lambda w: gtk.main_quit())
30
# Connect signals to handler functions
31
self.widgets.signal_autoconnect(self)
32
self.filelist = gtk.ListStore(gtk.gdk.Pixbuf, gtk.gdk.Pixbuf, gobject.TYPE_STRING, bool)
34
self.widgets.get_widget('treeview_druidfilelist').set_model(self.filelist)
35
self.widgets.get_widget('druid_summary_filelist').set_model(self.filelist)
37
# List layout: Include/Exclude icon,
40
# include(True)/exclude(False)
42
# Add the Path column to the treeview
43
self.widgets.get_widget('treeview_druidfilelist').append_column(self._new_column())
44
self.widgets.get_widget('druid_summary_filelist').append_column(self._new_column())
46
self.widgets.get_widget('filechooserwidget1').set_current_folder(os.environ['HOME'])
47
self.widgets.get_widget('cmb_dst_type').set_active(0)
48
self.widgets.get_widget('notebook').set_current_page(0)
50
self.find_cd_burners()
52
def _new_column(self):
53
column = gtk.TreeViewColumn()
54
column.set_title(_("Path"))
56
renderer = gtk.CellRendererPixbuf()
57
column.pack_start(renderer, expand=False)
58
column.add_attribute(renderer, 'pixbuf', 0)
59
renderer = gtk.CellRendererPixbuf()
60
column.pack_start(renderer, expand=False)
61
column.add_attribute(renderer, 'pixbuf', 1)
62
renderer = gtk.CellRendererText()
63
column.pack_start(renderer, expand=True)
64
column.add_attribute(renderer, 'text', 2)
67
def setexitnotify(self, func=None):
69
"""Set the callback that will be called when the set editor finishes"""
71
self.exitnotify = func
74
self.widgets.get_widget('druid_page_start').show()
75
self.widgets.get_widget('druid_page_finish').show()
76
self.widgets.get_widget('window_new_set').show()
79
def druid_cleanup(self, widget=None, event=None):
81
"""Resets the 'new backup set' druid to a 'clean' state"""
83
self.widgets.get_widget('window_new_set').hide()
84
self.widgets.get_widget('window_new_set').set_title(_("Create New Backup Set"))
85
self.widgets.get_widget('druid1').set_page(self.widgets.get_widget('druid_page_start'))
87
for widget in [ 'entry_new_set_name', \
88
'entry_new_set_desc', \
89
'entry_new_set_def_dest', \
93
self.widgets.get_widget(widget).set_text('')
94
self.widgets.get_widget('cmb_dst_type').set_active(0)
95
self.widgets.get_widget('new_set_overwrite').set_active(False)
96
self.widgets.get_widget('frame_set_exists_warning').hide()
97
self.widgets.get_widget('frame_ssh_error').hide()
98
self.widgets.get_widget('frame_empty_set_name_error').hide()
99
self.widgets.get_widget('frame_cd_burner_error').hide()
100
self.widgets.get_widget('entry_new_set_name').set_sensitive(True)
102
self.widgets.get_widget('filechooserwidget1').set_current_folder(os.environ['HOME'])
103
self.widgets.get_widget('druidfilelist_label').set_text(_("0 items"))
104
self.filelist.clear()
108
def set_backupset_to_edit(self, bsetid):
111
Initialises the input widgets in the backup set editor to the
112
settings defined in an existing set. Special case is the 'home'
113
set which cannot be edited by the user.
116
bsetid - The numerical index of the backup set.
119
True if successful (bsetid is not 'home' or invalid)
123
if bsetid is not None:
124
bset = rdiff_interface.backupsets[bsetid]
125
if bset['name'] == "home":
128
self.widgets.get_widget('entry_new_set_name').set_text(bset['name'])
129
self.widgets.get_widget('entry_new_set_name').set_sensitive(False)
130
self.widgets.get_widget('entry_new_set_desc').set_text(bset['desc'])
132
if bset.has_key('default_dest'):
133
dest = bset['default_dest']
134
if dest[:7] == "sftp://":
135
p = re.compile("sftp://([^@]+)@([^/]+)(.*)")
136
matches = p.match(dest)
137
if len(matches.groups()) < 3:
142
user = matches.group(1)
143
host = matches.group(2)
144
path = matches.group(3)
145
self.widgets.get_widget('cmb_dst_type').set_active(2)
146
self.widgets.get_widget('entry_ssh_user').set_text(user)
147
self.widgets.get_widget('entry_ssh_host').set_text(host)
148
self.widgets.get_widget('entry_ssh_path').set_text(path)
149
elif dest[:7] == "cdrw://":
150
device = dest.replace("cdrw://", "")
151
self.widgets.get_widget('cmb_dst_type').set_active(1)
153
for row in self.widgets.get_widget('cmb_dst_burner').get_model():
154
if row[1].get_device() == device:
155
self.widgets.get_widget('cmb_dst_burner').set_active_iter(row.iter)
158
self.widgets.get_widget('cmb_dst_burner').set_active(0)
160
self.widgets.get_widget('cmb_dst_type').set_active(0)
161
self.widgets.get_widget('entry_new_set_def_dest').set_text(dest)
163
self.widgets.get_widget('cmb_dst_type').set_active(0)
164
self.widgets.get_widget('new_set_overwrite').set_active(True)
165
druidfilelist = self.widgets.get_widget('treeview_druidfilelist')
166
druidfilelistmodel = druidfilelist.get_model()
167
for f in bset['filelist_exc']:
171
druidfilelistmodel.append([druidfilelist.render_icon(gtk.STOCK_REMOVE,\
172
gtk.ICON_SIZE_MENU, "TreeView"), druidfilelist.render_icon(\
173
gtk.STOCK_DIRECTORY, gtk.ICON_SIZE_MENU, "TreeView"), f, False])
175
druidfilelistmodel.append([druidfilelist.render_icon(gtk.STOCK_REMOVE,\
176
gtk.ICON_SIZE_MENU, "TreeView"), druidfilelist.render_icon(\
177
gtk.STOCK_FILE, gtk.ICON_SIZE_MENU, "TreeView"), f, False])
178
for f in bset['filelist_inc']:
180
druidfilelistmodel.append([druidfilelist.render_icon(gtk.STOCK_ADD,\
181
gtk.ICON_SIZE_MENU, "TreeView"), druidfilelist.render_icon(\
182
gtk.STOCK_DIRECTORY, gtk.ICON_SIZE_MENU, "TreeView"), f, True])
184
druidfilelistmodel.append([druidfilelist.render_icon(gtk.STOCK_ADD,\
185
gtk.ICON_SIZE_MENU, "TreeView"), druidfilelist.render_icon(\
186
gtk.STOCK_FILE, gtk.ICON_SIZE_MENU, "TreeView"), f, True])
187
if len(druidfilelist)==1:
188
self.widgets.get_widget('druidfilelist_label').set_text("1 item")
190
self.widgets.get_widget('druidfilelist_label').set_text("%d items"%len(druidfilelist))
191
self.widgets.get_widget('druid_page_start').show()
192
self.widgets.get_widget('druid_page_finish').show()
193
self.widgets.get_widget('druid1').set_page(self.widgets.get_widget('druid_page_2'))
194
self.widgets.get_widget('window_new_set').set_title(_("Editing backup set '%s'") % bset['name'])
197
# Event handlers start here
199
def on_entry_new_set_name_changed(self, widget):
200
widget.set_text(widget.get_text().replace("/", ""))
202
def on_cmb_dst_type_changed(self, widget):
204
self.widgets.get_widget('notebook').set_current_page(widget.get_active())
208
def on_druid_page_2_next(self, widget, event):
210
"""Check user input"""
212
if len(self.widgets.get_widget('entry_new_set_name').get_text()) == 0:
213
self.widgets.get_widget('frame_empty_set_name_error').show()
216
self.widgets.get_widget('frame_empty_set_name_error').hide()
217
if rdiff_interface.SetExists(self.widgets.get_widget('entry_new_set_name').get_text()) and not self.widgets.get_widget('new_set_overwrite').get_active():
218
self.widgets.get_widget('label_set_exists_warning').set_text(_("A set with the name '%s' already exists.\nYou can either enter a new name in the text box above, or overwrite the existing set.") % self.widgets.get_widget('entry_new_set_name').get_text())
219
self.widgets.get_widget('frame_set_exists_warning').show()
222
self.widgets.get_widget('frame_set_exists_warning').hide()
223
# ok, the set doesn't already exist - have a crack at compiling the default destination string
224
if self.widgets.get_widget('cmb_dst_type').get_active() == 0: # local
225
self.widgets.get_widget('druid_summary_dest').set_text(self.widgets.get_widget('entry_new_set_def_dest').get_text())
226
elif self.widgets.get_widget('cmb_dst_type').get_active() == 2: # SSH
227
host = self.widgets.get_widget('entry_ssh_host').get_text()
228
user = self.widgets.get_widget('entry_ssh_user').get_text()
229
path = self.widgets.get_widget('entry_ssh_path').get_text()
230
if len(host) == 0 or len(user) == 0 or len(path) == 0 or path[0] != "/":
231
self.widgets.get_widget('frame_ssh_error').show()
234
self.widgets.get_widget('frame_ssh_error').hide()
235
self.widgets.get_widget('druid_summary_dest').set_text("sftp://%s@%s%s" % (user, host, path))
236
elif self.widgets.get_widget('cmb_dst_type').get_active() == 1: # CD burner
237
if self.widgets.get_widget('cmb_dst_burner').get_active() == -1:
239
dest = self.widgets.get_widget('cmb_dst_burner').get_model()[self.widgets.get_widget('cmb_dst_burner').get_active()][1].get_device()
240
self.widgets.get_widget('druid_summary_dest').set_text("cdrw://%s" % dest)
241
self.widgets.get_widget('chk_removable_device').set_active(True)
242
self.widgets.get_widget('druid_page_3').set_title("Add Files/Folders to '%s'" % self.widgets.get_widget('entry_new_set_name').get_text())
243
self.widgets.get_widget('druid_summary_name').set_text(self.widgets.get_widget('entry_new_set_name').get_text())
244
self.widgets.get_widget('druid_summary_desc').set_text(self.widgets.get_widget('entry_new_set_desc').get_text())
246
def on_druid_page_3_next(self, widget, event):
247
if len(self.filelist) == 0:
248
ErrorDialog(_("You cannot create an empty backup set."), self.widgets.get_widget('window_new_set'))
251
def on_button_ssh_path_clicked(self, widget):
252
host = self.widgets.get_widget('entry_ssh_host').get_text()
253
user = self.widgets.get_widget('entry_ssh_user').get_text()
254
if len(host) == 0 or len(user) == 0:
256
filechooser = FileChooser()
257
filechooser.set_return_type(filechooser.RETURN_URI)
258
filechooser.set_exitnotify(self.filechosen_new_set_ssh_path)
259
filechooser.set_title(_("Select a default remote location to backup to."))
261
filechooser.set_current_folder_uri("sftp://%s@%s/" %(user, host))
263
def filechosen_new_set_ssh_path(self, uri):
264
host = self.widgets.get_widget('entry_ssh_host').get_text().replace(".", "\.")
265
user = self.widgets.get_widget('entry_ssh_user').get_text()
266
patt = re.compile("sftp:/[/]+%s@%s(.*)" % (user, host))
267
match = patt.match(uri)
268
if len(match.groups()) > 0:
269
self.widgets.get_widget('entry_ssh_path').set_text(match.group(1))
271
def on_button_default_dest_clicked(self, widget):
272
filechooser = FileChooser()
273
filechooser.set_return_type(filechooser.RETURN_FILENAME)
274
filechooser.set_exitnotify(self.filechosen_new_set_default_dest)
275
filechooser.set_title(_("Select a default location to backup to"))
278
def filechosen_new_set_default_dest(self, filename):
279
self.widgets.get_widget('entry_new_set_def_dest').set_text(filename)
281
def on_button_refresh_cd_burners_clicked(self, widget):
282
self.find_cd_burners()
284
def on_druid_page_finish_prepare(self, widget, event):
285
event.set_buttons_sensitive(False, False, False, False)
287
def on_druid_page_finish_finish(self, event, something):
289
for f in self.filelist:
290
filelist.append((f[2], f[3]))
292
rdiff_interface.WriteSet(
293
self.widgets.get_widget('druid_summary_name').get_text(),
294
self.widgets.get_widget('druid_summary_desc').get_text(),
296
self.widgets.get_widget('new_set_overwrite').get_active(),
298
self.widgets.get_widget('druid_summary_dest').get_text(),
300
self.widgets.get_widget('chk_removable_device').get_active()
302
if callable(self.exitnotify):
303
self.exitnotify(self.widgets.get_widget('druid_summary_name').get_text())
306
self.widgets.get_widget('druid_page_finish').set_text(
307
_("ERROR: Couldn't write new set %(name)s: %(error)s") %
308
{'name':self.widgets.get_widget('entry_new_set_name').get_text(), 'error':e})
310
def on_button_add_to_set_clicked(self, widget):
311
for f in self.widgets.get_widget('filechooserwidget1').get_filenames():
313
self.filelist.append([widget.render_icon(gtk.STOCK_ADD, gtk.ICON_SIZE_MENU, "TreeView"),
314
widget.render_icon(gtk.STOCK_DIRECTORY, gtk.ICON_SIZE_MENU, "TreeView"),
317
self.filelist.append([widget.render_icon(gtk.STOCK_ADD, gtk.ICON_SIZE_MENU, "TreeView"),
318
widget.render_icon(gtk.STOCK_FILE, gtk.ICON_SIZE_MENU, "TreeView"),
320
if len(self.filelist) == 1:
321
self.widgets.get_widget('druidfilelist_label').set_text(_("1 item"))
323
self.widgets.get_widget('druidfilelist_label').set_text(_("%d items")%len(self.filelist))
324
self.widgets.get_widget('filechooserwidget1').unselect_all()
326
def on_button_exc_from_set_clicked(self, widget):
327
for f in self.widgets.get_widget('filechooserwidget1').get_filenames():
329
self.filelist.append([widget.render_icon(gtk.STOCK_REMOVE, gtk.ICON_SIZE_MENU, "TreeView"),
330
widget.render_icon(gtk.STOCK_DIRECTORY, gtk.ICON_SIZE_MENU, "TreeView"),
333
self.filelist.append([widget.render_icon(gtk.STOCK_REMOVE, gtk.ICON_SIZE_MENU, "TreeView"),
334
widget.render_icon(gtk.STOCK_FILE, gtk.ICON_SIZE_MENU, "TreeView"),
336
if len(self.filelist) == 1:
337
self.widgets.get_widget('druidfilelist_label').set_text(_("1 item"))
339
self.widgets.get_widget('druidfilelist_label').set_text(_("%d items")%len(self.filelist))
340
self.widgets.get_widget('filechooserwidget1').unselect_all()
342
def on_button_remove_from_set_clicked(self, widget):
343
selection = self.widgets.get_widget('treeview_druidfilelist').get_selection()
344
store, row = selection.get_selected()
347
if len(self.filelist)==1:
348
self.widgets.get_widget('druidfilelist_label').set_text(_("1 item"))
350
self.widgets.get_widget('druidfilelist_label').set_text(_("%d items")%len(self.filelist))
352
def find_cd_burners(self):
354
""" Populate a combo box with the names of available CD/DVD drives """
358
error_string = _("No CD burners available, because you do not have the python module \
360
self.widgets.get_widget('lbl_cd_burner').set_text(error_string)
361
self.widgets.get_widget('cmb_dst_burner').set_sensitive(False)
363
sel = nautilusburn.DriveSelection()
364
self.widgets.get_widget('cmb_dst_burner').set_model(sel.get_model())
366
if len(sel.get_model()) == 0:
367
error_string = _("No CD burners were detected on your system.")
368
self.widgets.get_widget('lbl_cd_burner').set_text(error_string)
369
self.widgets.get_widget('cmb_dst_burner').set_sensitive(False)
371
msg_string = _("Select which CD burner to use:")
372
self.widgets.get_widget('lbl_cd_burner').set_text(msg_string)
373
self.widgets.get_widget('cmb_dst_burner').set_active(0)
374
self.widgets.get_widget('cmb_dst_burner').set_sensitive(True)