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