def show_box(self, use_wrap=True): """ Show test_box dialog @param use_wrap: Whether to use input wrapper which honours learned keys """ _msg = _(u"Press any key. Escape twice to quit.") _escape = 0 _escape_key = uilib.Shortcut(sc=[self._keys.ESCAPE]) while True: shortcut = InputBox(self.xyz, self.xyz.top, bstring(_msg), _(u"Input test")).show(use_wrap=use_wrap) if shortcut == _escape_key: _escape += 1 if _escape == 2: return else: _escape = 0 method = self.xyz.km.get_method_by_key(shortcut) _msg = u"Shortcut: '%s'. Raw: '%s'" % ( (u" ".join([ustring(x) for x in shortcut.sc]), u" ".join([ustring(x) for x in shortcut.raw]))) if method is not None: _msg = u"%s\n[%s]" % (_msg, method.ns)
def existcb(vfsobj): free.clear() buttons = [ (_(u"Yes"), "override"), (_(u"All"), "override all"), (_(u"Skip"), "skip"), (_(u"Skip all"), "skip all"), (_(u"Abort"), "abort"), ] try: name = ustring(vfsobj.name) _rec = uilib.ButtonBox( self.xyz, self.xyz.top, _(u"Object %s already exists. Really override?") % name, buttons, title=_(u"Override %s") % name).show() uilib.MessageBox(self.xyz, self.xyz.top, caption, caption).show(wait=False) free.set() return _rec or 'abort' except Exception: free.set()
def fileinfo(self): """ Show VFS object info """ _selected = self.xyz.pm.from_load(":sys:panel", "get_selected")() self.fire_event("fileinfo", _selected) _data = [] _na = lambda x: lowui.Text(u"%-30s: N/A" % x) for _name, _value in _selected.attributes: if _value in (None, ""): _data.append(_na(_name)) else: if not isinstance(_value, basestring): _value = ustring(str(_value)) _data.append(lowui.Text(u"%-30s: %s" % (_name, _value))) _walker = lowui.SimpleListWalker(_data) _dim = tuple([x - 2 for x in self.xyz.screen.get_cols_rows()]) XYZListBox(self.xyz, self.xyz.top, _walker, _(u"VFS Object Info"), _dim).show()
def _prepare(self): if self.path == os.sep: self.root = True else: self.root = False (self.tarobj, self.members) = self._find_cached() if self.root: self.obj = None else: self.obj = self._init_obj() self.ftype = self._find_type() self.vtype = self.ftype.vtype self._set_attributes() self.attributes = ( (_(u"Name"), ustring(self.name)), (_(u"Type"), ustring(self.ftype)), (_(u"Modification time"), ustring(time.ctime(self.mtime))), (_(u"Size in bytes"), ustring(self.size)), (_(u"Owner"), ustring(self.uid)), (_(u"Group"), ustring(self.gid)), (_(u"Access mode"), ustring(self.mode)), (_(u"Type-specific data"), self.data), )
def add_bookmark(self, path, name=None): """ Add new bookmark entry If name is not specified, path is used instead """ if name is None: name = path path = ustring(path) name = ustring(name) _data = self._load_data() if _data is not None: _data[name] = path return self._save_data(_data)
def _find_type(self, path): """ Find out file type """ try: self._stat = os.lstat(path) except OSError, e: raise VFSError(_(u"Unable to stat file %s: %s") % (ustring(path), unicode(e.strerror, xyzenc)))
def set_prefix(self, shortcut): """ Set prefix key """ if not isinstance(shortcut, Shortcut): raise KeyManagerError(_(u"Invalid shortcut type: %s.") % ustring(type(shortcut))) if shortcut not in self._prefixes: self._prefixes.append(shortcut)
def del_bookmark(self, name): """ Delete saved bookmark entry by name """ name = ustring(name) _data = self._load_data() if _data is not None and name in _data: del(_data[name]) return self._save_data(_data)
def init_logger(self): """ Initiate Logger object and put it into builtin namespace """ _log = logger.LogLevel() try: _levels = self.xyz.conf[u"plugins"][u":sys:logger"][u"levels"] except KeyError: _levels = (logger.LogLevel().ALL,) else: if not isinstance(_levels, tuple) and not \ isinstance(_levels, list): _levels = (_levels,) try: _levels = [getattr(_log, x) for x in _levels] except Exception: raise XYZValueError(_(u"Invalid value %s.\n"\ u"A list of valid log levels expected") % ustring(_levels)) try: _lines = self.xyz.conf[u"plugins"][u":sys:logger"][u"lines"] # Value not defined in conf except KeyError: _lines = 100 try: _lines = abs(int(_lines)) except ValueError: raise XYZValueError(_(u"Invalid value %s. "\ u"A positive integer expected") % ustring(_lines)) _logger = core.logger.Logger(self.xyz, _levels, _lines) __builtin__.__dict__["xyzlog"] = _logger
def get_path(self, name): """ Get bookmark path by name """ name = ustring(name) _data = self._load_data() if _data is not None and name in _data: return _data[name] return None
def errorcb(vfsobj, errstr): free.clear() buttons = [ (_(u"Skip"), "skip"), (_(u"Skip all"), "skip all"), (_(u"Abort"), "abort"), ] try: _rec = uilib.ButtonBox( self.xyz, self.xyz.top, _(u"An error occured %s: %s") % ( ustring(vfsobj.full_path), ustring(errstr)), buttons, title=_(u"Copy error")).show() uilib.MessageBox(self.xyz, self.xyz.top, caption, caption).show(wait=False) free.set() return _rec or 'abort' except Exception: free.set()
def make_args(func): _args, _varargs, _varkw, _def = inspect.getargspec(func) # We will be inspecting only methods, so always skip self if len(_args) == 1: return u"" _args = _args[1:] _tmp = [] # No defaults if _def is None: _tmp = _args else: _delta = len(_args) - len(_def) if _delta > 0: _tmp.extend(_args[:_delta]) _args = _args[_delta:] for _a, _d in zip(_args, _def): _tmp.append(u"=".join((ustring(_a), ustring(_d)))) return u",".join(_tmp)
def show(self, dim=None, exit_keys=None): """ Show window. Update contents as user types """ exit_keys = exit_keys or [] if dim is None: dim = self.xyz.screen.get_cols_rows() _buf = u"" _title = self.title while True: self.xyz.screen.draw_screen(dim, self.render(dim, True)) _i = self.xyz.input.get() if self.xyz.input.WIN_RESIZE in _i: dim = self.xyz.screen.get_cols_rows() continue update = False if _i: for _k in _i: if _k == self._keys.ESC: return elif _k == self._keys.BACKSPACE: _buf = _buf[:-1] update = True elif _k == self._keys.ENTER: entry, _ = self.listbox.get_focus() return entry.text elif len(ustring(_k)) == 1: _buf += _k update = True else: self._listbox.keypress(dim, _k) if update: _b = bstring(_buf) self.set_title(u"%s: %s" % (_title, _buf)) self.listbox.body.contents = [x for x in self._extra if _b in x._text]
def __init__(self, *args, **kwargs): super(ExternalVFSObject, self).__init__(*args, **kwargs) self.members = [] self.obj = None self.path_sel = libxyz.PathSelector() self.driver_cmd = self._init_driver_cmd(self.driver) # Check if we've already visited this particular VFS object _cache = self.xyz.vfs.get_cache(self.parent.full_path) # First time visit, we should run driver and build members list then if _cache is None: self.members = dict([self._parse_obj(x) for x in self._run_driver("list", self.parent.full_path) if x]) # Now cache the data for further use self.xyz.vfs.set_cache(self.parent.full_path, self.members) else: self.members = _cache # We're at the root of VFS if self.path == os.sep: self.root = True self.ftype = self.parent.ftype # Otherwise we're somewhere inside, strip the leading slash from path else: self.root = False self.path = self.path.lstrip(os.sep) self.obj = self._init_obj(self.path) self.ftype = self.obj["type"] self.vtype = self.ftype.vtype self._set_attributes() self.attributes = ( (_(u"Name"), ustring(self.name)), (_(u"Type"), ustring(self.ftype)), (_(u"Modification time"), ustring(self.mtime)), (_(u"Size in bytes"), ustring(self.size)), (_(u"Owner"), ustring(self.uid)), (_(u"Group"), ustring(self.gid)), (_(u"Access mode"), ustring(self.mode)), (_(u"Type-specific data"), self.data), )
def _prepare(self): self.ftype = self._find_type(self.path) self.vtype = self.ftype.vtype self._set_attributes() _time = lambda x: ustring(time.ctime(x)) self.attributes = ( (_(u"Name"), ustring(self.name)), (_(u"Type"), ustring(self.ftype)), (_(u"Access time"), _time(self.atime)), (_(u"Modification time"), _time(self.mtime)), (_(u"Change time"), _time(self.ctime)), (_(u"Size in bytes"), ustring(self.size)), (_(u"Owner"), ustring(self._uid(self.uid))), (_(u"Group"), ustring(self._gid(self.gid))), (_(u"Access mode"), ustring(self.mode)), (_(u"Inode"), ustring(self.inode)), (_(u"Type-specific data"), self.data), )
def __init__(self, xyz, srctxt, dst, caption): self.xyz = xyz self._attr = lambda name: self.xyz.skin.attr(self.resolution, name) self._keys = uilib.Keys() srclabel = lowui.Text(bstring(_(u"Source:"))) srctxt = lowui.Text(bstring(srctxt)) dstlabel = lowui.Text(bstring(_(u"Destination:"))) self.dstw = lowui.AttrWrap(lowui.Edit(edit_text=ustring(dst), wrap='clip'), self._attr("input")) self.save_attrw = lowui.CheckBox(bstring(_(u"Save attributes")), state=True) self.follow_linksw = lowui.CheckBox(bstring(_(u"Follow links"))) self.buttonsw = lowui.Columns([self.save_attrw, self.follow_linksw]) spacer = lowui.Text(" ") msg = lowui.Text( bstring(_(u"TAB to cycle. ENTER to submit. ESCAPE to cancel")), align=uilib.align.CENTER) w = [ srclabel, srctxt, spacer, dstlabel, self.dstw, spacer, self.buttonsw, uilib.Separator(), msg ] self.widgets = lowui.Pile(w) box = lowui.AttrWrap(lowui.Filler(self.widgets), self._attr("box")) self.widget = uilib.Border(box, caption, self._attr("title"), self._attr("border")) super(CopyBox, self).__init__(self.widget)
def dispatch(self, event, *args): """ Sequentially run procedures registered with provided event """ # No callbacks registered if event not in self._data or not self._data[event]: return False for proc in self._data[event]: try: proc(*args) except Exception, e: xyzlog.error( _(u"Error running callback procedure for event %s") % unicode(e)) xyzlog.debug(ustring(traceback.format_exc())) return False
def _parse_raw(self, raw): """ Make shortcut from raw keys received """ _raw = [] for el in raw: el = ustring(el) _data = el if el in (u"page up", u"page down"): _data = self._keys.get_key(el) elif len(el) > 1: # Shortcut _data = u"-".join([self._keys.get_key(x) or x for x in el.split(u" ")]) _raw.append(_data) return _raw
def truncate(text, cols, enc=None, backward=False): """ Truncate text if its length exceeds cols If backward is True, text will be truncated from the beginning """ if enc is None: enc = xyzenc text = ustring(text, enc) _len = lowui.util.calc_width(text, 0, len(text)) if _len < cols: return text else: if backward: return u"~%s" % text[-(cols - 1):] else: return u"%s~" % text[:cols - 1]
def _parse_sc(self, sc): """ Parse shortcut into raw form @param sc: List of shortcuts as read from config file """ _shortcut = [] for s in sc: _tmp = [] for _key in s.split("-"): try: _tmp.append(getattr(self._keys, _key)) except AttributeError: _tmp.append(_key) _shortcut.append(u" ".join([ustring(x) for x in _tmp])) return _shortcut
def __init__(self, *args, **kwargs): super(LocalVFSObject, self).__init__(*args, **kwargs) self.ftype = self._find_type(self.path) self.vtype = self.ftype.vtype self._set_attributes() _time = lambda x: ustring(time.ctime(x)) self.attributes = ( (_(u"Name"), ustring(self.name)), (_(u"Type"), ustring(self.ftype)), (_(u"Access time"), _time(self.atime)), (_(u"Modification time"), _time(self.mtime)), (_(u"Change time"), _time(self.ctime)), (_(u"Size in bytes"), ustring(self.size)), (_(u"Owner"), ustring(self._uid(self.uid))), (_(u"Group"), ustring(self._gid(self.gid))), (_(u"Access mode"), ustring(self.mode)), (_(u"Inode"), ustring(self.inode)), (_(u"Type-specific data"), self.data), )
def macro(cls, macroname): """ Expand macro name. Available macros: * ACT_CWD -- Working directory in active panel * INACT_CWD -- Working directory in inactive panel * ACT_PATH -- Full selected object path in active panel * INACT_PATH -- Full selected object path in inactive panel * ACT_BASE -- Parent directory in active panel * INACT_BASE -- Parent directory in inactive panel * ACT_TAGGED -- List of tagged files in active panel * INACT_TAGGED -- List of tagged files in inactive panel * ACT_UNTAGGED -- List of not tagged files in active panel * INACT_UNTAGGED -- List of not tagged files in inactive panel """ if macroname in cls.macros: try: return cls.macros[macroname]() except Exception, e: xyzlog.warning(_(u"Unable to expand macro %s: %s") % (ustring(macroname), unicode(e)))
def walk(self): """ Directory tree walker @return: tuple (parent, dir, objects) where: parent - parent dir LocalVFSObject instance dir - current LocalVFSObject instance objects - BlockEntries of LocalVFSObject objects """ try: _dir, _dirs, _files = os.walk(self.path).next() except StopIteration: raise XYZRuntimeError(_(u"Unable to walk on %s") % ustring(self.path)) _dirs.sort() _files.sort() _parent = self.xyz.vfs.get_parent(_dir, self.enc) get_path = lambda x: os.path.abspath(os.path.join(self.path, x)) return [_parent, self, BlockEntries(self.xyz, _dirs + _files, get_path)]
def remove(self): """ Remove VFS object dialog """ self._load_panel() objs = [x for x in self._panel.get_active() if not x.name == ".."] if not objs: return _len = len(objs) if _len > 1: msg = _(u"Really remove %d objects?") % _len else: selected = objs[0] msg = _(u"Really remove %s (%s)?") % \ (ustring(selected.name), ustring(selected.ftype)) _deletep = uilib.YesNoBox(self.xyz, self.xyz.top, msg, title=_(u"Remove object")) if not _deletep.show(): return force = False CODE_ALL = 10 CODE_YES = 20 CODE_NO = 30 CODE_ABORT = 40 buttons = [ (_(u"All"), CODE_ALL), (_(u"Yes"), CODE_YES), (_(u"No"), CODE_NO), (_(u"Abort"), CODE_ABORT), ] for obj in objs: if not force and obj.is_dir() and not obj.is_dir_empty(): _rec = uilib.ButtonBox( self.xyz, self.xyz.top, _(u"Directory is not empty\nRemove it recursively?"), buttons, title=_(u"Remove %s") % ustring(obj.full_path)).show() if _rec == CODE_ABORT: break elif _rec == CODE_ALL: force = True elif _rec in (CODE_NO, None): continue uilib.MessageBox(self.xyz, self.xyz.top, _(u"Removing object: %s") % ustring(obj.full_path), _(u"Removing")).show(wait=False) try: obj.remove() except Exception, e: uilib.ErrorBox(self.xyz, self.xyz.top, _(u"Unable to remove object: %s") % (unicode(e)), _(u"Error")).show() xyzlog.error(_(u"Error removing object: %s") % unicode(e)) break
def copy(self, move=False): """ Copy objects dialog """ self._load_panel() objs = self._panel.get_active() if not objs: return if len(objs) == 1: srctxt = ustring(objs[0].full_path) else: srctxt = _(u"%d objects") % len(objs) srctxt = bstring(srctxt) if move: _m = _(u"Move") msg = _(u"Moving object: %s") caption = _(u"Moving") unable_msg = _(u"Unable to move object: %s") unable_caption = _(u"Move error") else: _m = _(u"Copy") msg = _(u"Copying object: %s") caption = _(u"Copying") unable_msg = _(u"Unable to copy object: %s") unable_caption = _(u"Copy error") msg += _(u"\nESCAPE to abort") data = CopyBox(self.xyz, srctxt, self._panel.cwd(active=False), bstring(_m)).show() if data is None: return stopped = threading.Event() cancel = threading.Event() free = threading.Event() free.set() def existcb(vfsobj): free.clear() buttons = [ (_(u"Yes"), "override"), (_(u"All"), "override all"), (_(u"Skip"), "skip"), (_(u"Skip all"), "skip all"), (_(u"Abort"), "abort"), ] try: name = ustring(vfsobj.name) _rec = uilib.ButtonBox( self.xyz, self.xyz.top, _(u"Object %s already exists. Really override?") % name, buttons, title=_(u"Override %s") % name).show() uilib.MessageBox(self.xyz, self.xyz.top, caption, caption).show(wait=False) free.set() return _rec or 'abort' except Exception: free.set() #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ def errorcb(vfsobj, errstr): free.clear() buttons = [ (_(u"Skip"), "skip"), (_(u"Skip all"), "skip all"), (_(u"Abort"), "abort"), ] try: _rec = uilib.ButtonBox( self.xyz, self.xyz.top, _(u"An error occured %s: %s") % ( ustring(vfsobj.full_path), ustring(errstr)), buttons, title=_(u"Copy error")).show() uilib.MessageBox(self.xyz, self.xyz.top, caption, caption).show(wait=False) free.set() return _rec or 'abort' except Exception: free.set() #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ args = { "existcb": existcb, "errorcb": errorcb, "save_attrs": data["save_attributes"], "follow_links": data["follow_links"], "cancel": cancel } runner_error = [] def frun(o, err): stopped.clear() try: if move: attr = "move" else: attr = "copy" getattr(o, attr)(data["dst"], **args) except StopIteration, e: pass except Exception, e: err.append(unicode(e))
getattr(o, attr)(data["dst"], **args) except StopIteration, e: pass except Exception, e: err.append(unicode(e)) stopped.set() #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for obj in objs: if cancel.isSet(): break uilib.MessageBox(self.xyz, self.xyz.top, msg % ustring(obj.full_path), caption).show(wait=False) try: runner = threading.Thread(target=lambda: frun(obj, runner_error)) runner.start() # While runner is running, poll for the user input # abort if ESCAPE pressed while True: # Callback handler is active if not free.isSet(): free.wait() # Runner thread terminated, continue
def _copystat(self, obj, dst): try: os.chown(dst, obj.uid, obj.gid) except Exception, e: xyzlog.warning(_(u"Unable to chown %s: %s") % (ustring(dst), unicode(e)))
self._copystat(obj, dst) #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ def _copystat(self, obj, dst): try: os.chown(dst, obj.uid, obj.gid) except Exception, e: xyzlog.warning(_(u"Unable to chown %s: %s") % (ustring(dst), unicode(e))) try: os.chmod(dst, obj.mode) except Exception, e: xyzlog.warning(_(u"Unable to chmod %s: %s") % (ustring(dst), unicode(e))) #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ def _find_cached(self): """ Find cached data """ return self.xyz.vfs.get_cache(self.parent.full_path) or (None, None) #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ def _init_members(self, tarobj): """ Init members from archive contents
def __unicode__(self): return ustring(str(self))
def __len__(self): """ Return prompt text length """ return len(ustring(self.get_text()[0]))