Package plugins :: Package vfs :: Package vfsutils :: Module main |
[hide private]
[frames] | no frames]

# Source Code for Module plugins.vfs.vfsutils.main

      1  #-*- coding: utf8 -*
      2  #
      3  # Max E. Kuznecov <syhpoon@syhpoon.name> 2009
      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
     15 -class XYZPlugin(BasePlugin):
     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
     30 -    def __init__(self, xyz):
     31          super(XYZPlugin, self).__init__(xyz)
     32
     33          self.keys = uilib.Keys()
     34          self._panel = None
     35
     36          self.export(self.mkdir)
     37          self.export(self.remove)
     38          self.export(self.copy)
     39          self.export(self.move)
     40
     41      #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     42
     43 -    def mkdir(self):
     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
     72 -    def remove(self):
     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                  # While runner is running, poll for the user input
    288                  # abort if ESCAPE pressed
    289                  while True:
    290                      # Callback handler is active
    291                      if not free.isSet():
    292                          free.wait()
    293
    294                      # Runner thread terminated, continue
    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                      # User abort
    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
    320 -    def move(self):
    321          """
    322          Move objects dialog
    323          """
    324
    325          return self.copy(move=True)
    326
    327      #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    328
    329 -    def _load_panel(self):
    330          """
    331          Load :sys:panel plugin
    332          """
    333
    334          if self._panel is None:
    335              self._panel = self.xyz.pm.load(":sys:panel")
    336