~ubuntu-branches/ubuntu/precise/pybackpack/precise

« back to all changes in this revision

Viewing changes to src/pybackpack/seteditor.py

  • Committer: Bazaar Package Importer
  • Author(s): Andy Price, Andy Price, Piotr Ożarowski, Marco Rodrigues
  • Date: 2007-12-23 15:07:21 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20071223150721-16ur0rbpnlppmbz3
Tags: 0.5.4-1
[ Andy Price ]
* New upstream release
* Update debian/docs - TODO file has been removed
* Depend on genisoimage which upstream now uses
* Remove debian/dirs - distutils creates usr/bin
* Fix section in debian/menu to follow menu guidelines

[ Piotr Ożarowski ]
* Homepage field added
* Rename XS-Vcs-* fields to Vcs-* (dpkg supports them now)

[ Marco Rodrigues ]
* Update Standards-Version to 3.7.3.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
import os
2
 
import re
3
 
import sys
4
 
import gtk
5
 
import gtk.glade
6
 
import gobject
7
 
try:
8
 
        import nautilusburn
9
 
except ImportError:
10
 
        pass
11
 
else:
12
 
        pass
13
 
 
14
 
import version
15
 
import rdiff_interface
16
 
from Dialogs import ErrorDialog
17
 
from filechooser import FileChooser
18
 
 
19
 
class SetEditor:
20
 
    def __init__(self, bsetid=None):
21
 
        self.exitnotify = None
22
 
        try:
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())
29
 
 
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)
33
 
 
34
 
        self.widgets.get_widget('treeview_druidfilelist').set_model(self.filelist)
35
 
        self.widgets.get_widget('druid_summary_filelist').set_model(self.filelist)
36
 
 
37
 
        # List layout: Include/Exclude icon, 
38
 
        #              file/folder icon,
39
 
        #              path,
40
 
        #              include(True)/exclude(False)
41
 
 
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())
45
 
 
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)
49
 
 
50
 
        self.find_cd_burners()
51
 
 
52
 
    def _new_column(self):
53
 
        column = gtk.TreeViewColumn()
54
 
        column.set_title(_("Path"))
55
 
        column.set_spacing(3)
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)
65
 
        return column
66
 
 
67
 
    def setexitnotify(self, func=None):
68
 
 
69
 
        """Set the callback that will be called when the set editor finishes"""
70
 
 
71
 
        self.exitnotify = func
72
 
 
73
 
    def show(self):
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()
77
 
 
78
 
 
79
 
    def druid_cleanup(self, widget=None, event=None):
80
 
 
81
 
        """Resets the 'new backup set' druid to a 'clean' state"""
82
 
 
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'))
86
 
 
87
 
        for widget in [ 'entry_new_set_name', \
88
 
                        'entry_new_set_desc', \
89
 
                        'entry_new_set_def_dest', \
90
 
                        'entry_ssh_user', \
91
 
                        'entry_ssh_host', \
92
 
                        'entry_ssh_path']:
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)
101
 
        
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()
105
 
 
106
 
        return True
107
 
 
108
 
    def set_backupset_to_edit(self, bsetid):
109
 
 
110
 
        """
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.
114
 
 
115
 
        Arguments:
116
 
                bsetid - The numerical index of the backup set.
117
 
 
118
 
        Returns:
119
 
                True if successful (bsetid is not 'home' or invalid)
120
 
                False otherwise
121
 
        """
122
 
 
123
 
        if bsetid is not None:
124
 
            bset = rdiff_interface.backupsets[bsetid]
125
 
            if bset['name'] == "home":
126
 
                return False
127
 
 
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'])
131
 
 
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:
138
 
                        user = ""
139
 
                        host = ""
140
 
                        path = ""
141
 
                    else:
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)
152
 
                    found = False
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)
156
 
                            found = True
157
 
                    if found == False:
158
 
                        self.widgets.get_widget('cmb_dst_burner').set_active(0)
159
 
                else:
160
 
                    self.widgets.get_widget('cmb_dst_type').set_active(0)
161
 
                    self.widgets.get_widget('entry_new_set_def_dest').set_text(dest)
162
 
            else:
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']:
168
 
                if f == "**":
169
 
                    continue
170
 
                if os.path.isdir(f):
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])
174
 
                else:
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']:
179
 
                if os.path.isdir(f):
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])
183
 
                else:
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")
189
 
        else:
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'])
195
 
        return True
196
 
 
197
 
    # Event handlers start here
198
 
 
199
 
    def on_entry_new_set_name_changed(self, widget):
200
 
        widget.set_text(widget.get_text().replace("/", ""))
201
 
 
202
 
    def on_cmb_dst_type_changed(self, widget):
203
 
        try:
204
 
            self.widgets.get_widget('notebook').set_current_page(widget.get_active())
205
 
        except:
206
 
            pass
207
 
 
208
 
    def on_druid_page_2_next(self, widget, event):
209
 
 
210
 
        """Check user input"""
211
 
 
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()
214
 
            return True
215
 
        else:
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()
220
 
            return True
221
 
        else:
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()
232
 
                return True
233
 
            else:
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:
238
 
                return True
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())
245
 
    
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'))
249
 
            return True
250
 
 
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:
255
 
            return True
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."))
260
 
        filechooser.show()
261
 
        filechooser.set_current_folder_uri("sftp://%s@%s/" %(user, host))
262
 
 
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))
270
 
 
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"))
276
 
        filechooser.show()
277
 
    
278
 
    def filechosen_new_set_default_dest(self, filename):
279
 
        self.widgets.get_widget('entry_new_set_def_dest').set_text(filename)
280
 
 
281
 
    def on_button_refresh_cd_burners_clicked(self, widget):
282
 
        self.find_cd_burners()
283
 
 
284
 
    def on_druid_page_finish_prepare(self, widget, event):
285
 
        event.set_buttons_sensitive(False, False, False, False)
286
 
                
287
 
    def on_druid_page_finish_finish(self, event, something):
288
 
        filelist = []
289
 
        for f in self.filelist:
290
 
            filelist.append((f[2], f[3]))
291
 
        try:
292
 
            rdiff_interface.WriteSet(
293
 
                self.widgets.get_widget('druid_summary_name').get_text(),
294
 
                self.widgets.get_widget('druid_summary_desc').get_text(),
295
 
                filelist,
296
 
                self.widgets.get_widget('new_set_overwrite').get_active(),
297
 
                {'default_dest':
298
 
                    self.widgets.get_widget('druid_summary_dest').get_text(),
299
 
                 'removable':
300
 
                    self.widgets.get_widget('chk_removable_device').get_active()
301
 
                })
302
 
            if callable(self.exitnotify):
303
 
                self.exitnotify(self.widgets.get_widget('druid_summary_name').get_text())
304
 
            self.druid_cleanup()
305
 
        except OSError, e:
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})
309
 
 
310
 
    def on_button_add_to_set_clicked(self, widget):
311
 
        for f in self.widgets.get_widget('filechooserwidget1').get_filenames():
312
 
            if os.path.isdir(f):
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"), 
315
 
                                      f, True])
316
 
            else:
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"),
319
 
                                      f, True])
320
 
        if len(self.filelist) == 1:
321
 
            self.widgets.get_widget('druidfilelist_label').set_text(_("1 item"))
322
 
        else:
323
 
            self.widgets.get_widget('druidfilelist_label').set_text(_("%d items")%len(self.filelist))
324
 
        self.widgets.get_widget('filechooserwidget1').unselect_all()
325
 
    
326
 
    def on_button_exc_from_set_clicked(self, widget):
327
 
        for f in self.widgets.get_widget('filechooserwidget1').get_filenames():
328
 
            if os.path.isdir(f):
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"),
331
 
                                      f, False])
332
 
            else:
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"), 
335
 
                                      f, False])
336
 
        if len(self.filelist) == 1:
337
 
            self.widgets.get_widget('druidfilelist_label').set_text(_("1 item"))
338
 
        else:
339
 
            self.widgets.get_widget('druidfilelist_label').set_text(_("%d items")%len(self.filelist))
340
 
        self.widgets.get_widget('filechooserwidget1').unselect_all()
341
 
    
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()
345
 
        if row is not None:
346
 
            store.remove(row)
347
 
            if len(self.filelist)==1:
348
 
                self.widgets.get_widget('druidfilelist_label').set_text(_("1 item"))
349
 
            else:
350
 
                self.widgets.get_widget('druidfilelist_label').set_text(_("%d items")%len(self.filelist))
351
 
 
352
 
    def find_cd_burners(self):
353
 
 
354
 
        """ Populate a combo box with the names of available CD/DVD drives """
355
 
        try:
356
 
            nautilusburn
357
 
        except NameError:
358
 
            error_string = _("No CD burners available, because you do not have the python module \
359
 
nautilusburn.")
360
 
            self.widgets.get_widget('lbl_cd_burner').set_text(error_string)
361
 
            self.widgets.get_widget('cmb_dst_burner').set_sensitive(False)
362
 
        else:
363
 
            sel = nautilusburn.DriveSelection()
364
 
            self.widgets.get_widget('cmb_dst_burner').set_model(sel.get_model())
365
 
 
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)
370
 
            else:
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)
375