3
# Copyright (c) 2007 Timon ter Braak
5
# This library is free software; you can redistribute it and/or
6
# modify it under the terms of the GNU Lesser General Public
7
# License as published by the Free Software Foundation; either
8
# version 2 of the License, or (at your option) any later version.
10
# This library is distributed in the hope that it will be useful,
11
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
# Lesser General Public License for more details.
15
# You should have received a copy of the GNU Lesser General Public
16
# License along with this library; if not, write to the
17
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18
# Boston, MA 02111-1307, USA.
26
class GUITransfer(object):
28
def __init__(self, src, dst, options):
29
self.__progress = None
30
self.dialog_visible = False
32
self.txt_operation = ""
33
self.label_under = None
34
if not (options & gnomevfs.XFER_LINK_ITEMS):
35
if (options & gnomevfs.XFER_REMOVESOURCE):
36
self.txt_operation = "Moving"
37
elif (options & gnomevfs.XFER_EMPTY_DIRECTORIES):
38
self.txt_operation = "Deleting"
40
self.txt_operation = "Copying"
41
self.dialog = gtk.Dialog(title=self.txt_operation + " files",
42
buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT))
43
self.dialog.set_border_width(12)
44
self.dialog.set_has_separator(False)
45
self.dialog.vbox.set_spacing(2)
46
hbox_copy = gtk.HBox(False, 0)
47
label_copy = gtk.Label("")
48
label_copy.set_markup("<big><b>" + self.txt_operation + " files</b></big>\n")
49
hbox_copy.pack_start(label_copy, False, False, 0)
50
self.dialog.vbox.add(hbox_copy)
51
hbox_info = gtk.HBox(False, 0)
52
label_fromto = gtk.Label("")
53
label_fromto.set_markup("<b>From:</b>\n<b>To:</b>")
54
label_fromto.set_justify(gtk.JUSTIFY_RIGHT)
55
hbox_info.pack_start(label_fromto, False, False, 0)
57
srcdir = src[0].parent.path
58
dstdir = dst[0].parent.path
59
label_srcdst = gtk.Label("")
60
label_srcdst.set_alignment(0.0, 0.5)
61
label_srcdst.set_ellipsize(pango.ELLIPSIZE_START)
62
label_srcdst.set_markup("%s\n%s" % (srcdir, dstdir))
63
hbox_info.pack_start(label_srcdst, True, True, 4)
66
self.dialog.vbox.add(hbox_info)
67
self.progress_bar = gtk.ProgressBar()
68
self.dialog.vbox.add(self.progress_bar)
69
hbox_under = gtk.HBox(False, 0)
70
self.label_under = gtk.Label("")
71
self.label_under.set_justify(gtk.JUSTIFY_LEFT)
72
self.label_under.set_ellipsize(pango.ELLIPSIZE_MIDDLE)
73
self.label_under.xalign = 0.0
74
hbox_under.pack_start(self.label_under, True, True, 0)
75
self.dialog.vbox.add(hbox_under)
77
self.status_label = gtk.Label()
78
self.dialog.vbox.add(self.status_label)
79
self.dialog.set_size_request(400,180)
80
self.dialog.connect("response", self.__dialog_response)
81
self.dialog.show_all()
83
self.handle = gnomevfs.async.xfer(
84
source_uri_list=src, target_uri_list=dst,
86
error_mode=gnomevfs.XFER_ERROR_MODE_ABORT,
87
overwrite_mode=gnomevfs.XFER_OVERWRITE_MODE_ABORT,
88
progress_update_callback=self.update_info_cb,
89
update_callback_data=options,
90
progress_sync_callback=None,
91
sync_callback_data=None
95
def __dialog_response(self, dialog, response):
96
if response == gtk.RESPONSE_REJECT or \
97
response == gtk.RESPONSE_DELETE_EVENT:
101
def update_info_cb(self, _reserved, info, data):
102
if info.status == gnomevfs.XFER_PROGRESS_STATUS_VFSERROR:
103
uri = gnomevfs.URI(info.source_name)
105
if xfer_opts & gnomevfs.XFER_REMOVESOURCE:
106
msg = _("Error while moving.")
107
msg2 = _('Cannot move "%s" to the trash because you do not have permissions to change it or its parent folder.' % uri.short_name)
108
elif xfer_opts & gnomevfs.XFER_DELETE_ITEMS:
109
msg = _("Error while deleting.")
110
msg2 = _('"%s" cannot be deleted because you do not have permissions to modify its parent folder.') % uri.short_name
112
msg = _("Error while performing file operation.")
113
msg2 = _('Cannot perform file operation %d on "%s".') % (xfer_opts, uri.short_name)
114
dialog = gtk.MessageDialog(type = gtk.MESSAGE_ERROR,
115
message_format = msg)
116
dialog.format_secondary_text(msg2)
117
if info.files_total > 1:
118
button = gtk.Button(label=_("_Skip"))
120
dialog.add_action_widget(button, gtk.RESPONSE_REJECT)
122
dialog.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
123
button = gtk.Button(label=_("_Retry"))
124
button.set_property("can-default", True)
126
dialog.add_action_widget(button, gtk.RESPONSE_ACCEPT)
127
dialog.set_default_response(gtk.RESPONSE_ACCEPT)
129
response = dialog.run()
132
if response == gtk.RESPONSE_ACCEPT:
133
return gnomevfs.XFER_ERROR_ACTION_RETRY
134
elif response == gtk.RESPONSE_REJECT:
135
return gnomevfs.XFER_ERROR_ACTION_SKIP
137
return gnomevfs.XFER_ERROR_ACTION_ABORT
139
if (data & gnomevfs.XFER_LINK_ITEMS):
141
if info.phase == gnomevfs.XFER_PHASE_COMPLETED:
142
self.dialog.destroy()
143
if info.status == gnomevfs.XFER_PROGRESS_STATUS_OK:
144
self.label_under.set_markup(
145
"<i>%s %s</i>" % (self.txt_operation, str(info.source_name)))
146
self.progress_bar.set_text(self.txt_operation + " " +
147
str(info.file_index) + " of " + str(info.files_total))
148
if info.bytes_copied > 0 and info.bytes_total > 0:
149
fraction = float(info.bytes_copied)/float(info.bytes_total)
150
if not self.dialog_visible: # TODO: and enough time..
151
self.dialog_visible = True
152
self.dialog.show_all()
153
self.progress_bar.set_fraction(fraction)
155
# TODO: remove partial target?
160
class VfsUri(gobject.GObject):
164
def __init__(self, uri):
165
gobject.GObject.__init__(self)
166
if isinstance(uri, gnomevfs.URI):
169
self.uri = gnomevfs.URI(uri.strip())
172
def equals(self, uri2):
173
return gnomevfs.uris_match(self.as_string(), uri2.as_string())
181
ustr = self.uri.scheme + "://"
182
if self.uri.user_name is not None:
183
ustr += self.uri.user_name
184
if self.uri.password is not None:
185
ustr += ":" + self.uri.password
187
if self.uri.host_name is not None:
188
ustr += self.uri.host_name
189
if self.uri.host_port > 0:
190
ustr += ":" + str(self.uri.host_port)
191
if self.uri.path is not None:
192
ustr += self.uri.path
196
class Monitor(gobject.GObject):
199
"event" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE,
200
(gobject.TYPE_STRING, gobject.TYPE_INT)),
201
"created" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_OBJECT,)),
202
"deleted" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_OBJECT,)),
203
"changed" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_OBJECT,))
207
gnomevfs.MONITOR_EVENT_CREATED : "created",
208
gnomevfs.MONITOR_EVENT_DELETED : "deleted",
209
gnomevfs.MONITOR_EVENT_CHANGED : "changed",
210
gnomevfs.MONITOR_EVENT_METADATA_CHANGED : "changed"
217
def __init__(self, vfs_uri):
218
assert isinstance(vfs_uri, VfsUri)
219
gobject.GObject.__init__(self)
220
self.vfs_uri = vfs_uri
221
type = gnomevfs.get_file_info(vfs_uri.as_uri(),
222
gnomevfs.FILE_INFO_DEFAULT |
223
gnomevfs.FILE_INFO_FOLLOW_LINKS).type
224
if type == gnomevfs.FILE_TYPE_DIRECTORY:
225
self.monitor_type = gnomevfs.MONITOR_DIRECTORY
226
elif type == gnomevfs.FILE_TYPE_REGULAR:
227
self.monitor_type = gnomevfs.MONITOR_FILE
229
raise gnomevfs.NotSupportedError
231
self.monitor = gnomevfs.monitor_add(
235
except gnomevfs.NotSupportedError:
239
def _monitor_cb(self, monitor_uri, info_uri, event):
240
signal = self.event_mapping[event]
242
if self.monitor_type == gnomevfs.MONITOR_FILE:
243
self.emit(signal, self.vfs_uri)
245
self.emit(signal, VfsUri(info_uri))
250
gnomevfs.monitor_cancel(self.monitor)