1
2
3
4
5
6 import threading
7
8 import libxyz.ui as uilib
9
10 from libxyz.core.utils import ustring, bstring
11 from libxyz.core.plugins import BasePlugin
12
13 from box_copy import CopyBox
14
16 """
17 Plugin vfsutils
18 """
19
20 NAME = u"vfsutils"
21 AUTHOR = u"Max E. Kuznecov <syhpoon@syhpoon.name>"
22 VERSION = u"0.1"
23 BRIEF_DESCRIPTION = _(u"Useful VFS routines")
24 FULL_DESCRIPTION = _(u"Dialogs for common VFS operations")
25 NAMESPACE = u"vfs"
26 MIN_XYZ_VERSION = None
27 DOC = None
28 HOMEPAGE = "http://xyzcmd.syhpoon.name"
29
40
41
42
44 """
45 Create new directory dialog
46 """
47
48 self._load_panel()
49
50 _box = uilib.InputBox(self.xyz, self.xyz.top,
51 _(u"New directory name"),
52 title=_(u"Create directory"))
53
54 _dir = _box.show()
55
56 if not _dir:
57 return
58 else:
59 _dir = bstring(_dir)
60
61 try:
62 self._panel.get_current().mkdir(_dir)
63 except Exception, e:
64 xyzlog.error(_(u"Unable to create directory: %s") %
65 ustring(str(e)))
66 else:
67 self._panel.reload()
68 self._panel.select(_dir)
69
70
71
73 """
74 Remove VFS object dialog
75 """
76
77 self._load_panel()
78 objs = self._panel.get_active()
79
80 if not objs:
81 return
82
83 _len = len(objs)
84
85 if _len > 1:
86 msg = _(u"Really remove %d objects?") % _len
87 else:
88 selected = objs[0]
89 msg = _(u"Really remove %s (%s)?") % \
90 (ustring(selected.name), ustring(selected.ftype))
91
92 _deletep = uilib.YesNoBox(self.xyz, self.xyz.top, msg,
93 title=_(u"Remove object"))
94
95 if not _deletep.show():
96 return
97
98 force = False
99
100 CODE_ALL = 10
101 CODE_YES = 20
102 CODE_NO = 30
103 CODE_ABORT = 40
104
105 buttons = [
106 (_(u"All"), CODE_ALL),
107 (_(u"Yes"), CODE_YES),
108 (_(u"No"), CODE_NO),
109 (_(u"Abort"), CODE_ABORT),
110 ]
111
112 for obj in objs:
113 if not force and obj.is_dir() and not obj.is_dir_empty():
114 _rec = uilib.ButtonBox(
115 self.xyz, self.xyz.top,
116 _(u"Directory is not empty\nRemove it recursively?"),
117 buttons,
118 title=_(u"Remove %s") % ustring(obj.full_path)).show()
119
120 if _rec == CODE_ABORT:
121 break
122 elif _rec == CODE_ALL:
123 force = True
124 elif _rec == CODE_NO:
125 continue
126
127 uilib.MessageBox(self.xyz, self.xyz.top,
128 _(u"Removing object: %s") %
129 ustring(obj.full_path),
130 _(u"Removing")).show(wait=False)
131
132 try:
133 obj.remove()
134 except Exception, e:
135 uilib.ErrorBox(self.xyz, self.xyz.top,
136 _(u"Unable to remove object: %s") %
137 (ustring(str(e))),
138 _(u"Error")).show()
139 xyzlog.error(_(u"Error removing object: %s") %
140 ustring(str(e)))
141 break
142
143 self._panel.reload()
144
145
146
147 - def copy(self, move=False):
148 """
149 Copy objects dialog
150 """
151
152 self._load_panel()
153 objs = self._panel.get_active()
154
155 if not objs:
156 return
157
158 if len(objs) == 1:
159 srctxt = ustring(objs[0].full_path)
160 else:
161 srctxt = _(u"%d objects") % len(objs)
162
163 srctxt = bstring(srctxt)
164
165 if move:
166 _m = _(u"Move")
167 msg = _(u"Moving object: %s")
168 caption = _(u"Moving")
169 unable_msg = _(u"Unable to move object: %s")
170 unable_caption = _(u"Move error")
171 else:
172 _m = _(u"Copy")
173 msg = _(u"Copying object: %s")
174 caption = _(u"Copying")
175 unable_msg = _(u"Unable to copy object: %s")
176 unable_caption = _(u"Copy error")
177
178 msg += _(u"\nESCAPE to abort")
179 data = CopyBox(self.xyz, srctxt, self._panel.cwd(active=False),
180 bstring(_m)).show()
181
182 if data is None:
183 return
184
185 stopped = threading.Event()
186 cancel = threading.Event()
187 free = threading.Event()
188 free.set()
189
190 def existcb(vfsobj):
191 free.clear()
192
193 buttons = [
194 (_(u"Yes"), "override"),
195 (_(u"All"), "override all"),
196 (_(u"Skip"), "skip"),
197 (_(u"Skip all"), "skip all"),
198 (_(u"Abort"), "abort"),
199 ]
200
201 try:
202 name = ustring(vfsobj.name)
203
204 _rec = uilib.ButtonBox(
205 self.xyz, self.xyz.top,
206 _(u"Object %s already exists. Really override?") % name,
207 buttons, title=_(u"Override %s") % name).show()
208
209 uilib.MessageBox(self.xyz, self.xyz.top,
210 caption, caption).show(wait=False)
211
212 free.set()
213 return _rec or 'abort'
214 except Exception:
215 free.set()
216
217
218
219 def errorcb(vfsobj, errstr):
220 free.clear()
221
222 buttons = [
223 (_(u"Skip"), "skip"),
224 (_(u"Skip all"), "skip all"),
225 (_(u"Abort"), "abort"),
226 ]
227
228 try:
229 _rec = uilib.ButtonBox(
230 self.xyz, self.xyz.top,
231 _(u"An error occured %s: %s") % (
232 ustring(vfsobj.full_path), ustring(errstr)),
233 buttons, title=_(u"Copy error")).show()
234
235 uilib.MessageBox(self.xyz, self.xyz.top,
236 caption, caption).show(wait=False)
237
238 free.set()
239 return _rec or 'abort'
240 except Exception:
241 free.set()
242
243
244
245 args = {
246 "existcb": existcb,
247 "errorcb": errorcb,
248 "save_attrs": data["save_attributes"],
249 "follow_links": data["follow_links"],
250 "cancel": cancel
251 }
252
253 runner_error = []
254
255 def frun(o, err):
256 stopped.clear()
257
258 try:
259 if move:
260 attr = "move"
261 else:
262 attr = "copy"
263
264 getattr(o, attr)(data["dst"], **args)
265 except StopIteration, e:
266 pass
267 except Exception, e:
268 err.append(ustring(str(e)))
269
270 stopped.set()
271
272
273
274 for obj in objs:
275 if cancel.isSet():
276 break
277
278 uilib.MessageBox(self.xyz, self.xyz.top,
279 msg % ustring(obj.full_path),
280 caption).show(wait=False)
281
282 try:
283 runner = threading.Thread(target=lambda:
284 frun(obj, runner_error))
285 runner.start()
286
287
288
289 while True:
290
291 if not free.isSet():
292 free.wait()
293
294
295 if stopped.isSet():
296 runner.join()
297 if runner_error:
298 uilib.ErrorBox(self.xyz, self.xyz.top,
299 unable_msg % runner_error[0],
300 unable_caption).show()
301 xyzlog.error(unable_msg % runner_error[0])
302
303 break
304
305 _in = self.xyz.input.get(True)
306
307
308 if self.keys.ESCAPE in _in:
309 cancel.set()
310 runner.join()
311 break
312 except Exception:
313 break
314
315 self._panel.reload()
316 self._panel.reload(active=False)
317
318
319
321 """
322 Move objects dialog
323 """
324
325 return self.copy(move=True)
326
327
328
330 """
331 Load :sys:panel plugin
332 """
333
334 if self._panel is None:
335 self._panel = self.xyz.pm.load(":sys:panel")
336