Package libxyz :: Package core :: Module keymanager
[hide private]
[frames] | no frames]

Source Code for Module libxyz.core.keymanager

  1  #-*- coding: utf8 -* 
  2  # 
  3  # Max E. Kuznecov ~syhpoon <syhpoon@syhpoon.name> 2008 
  4  # 
  5  # This file is part of XYZCommander. 
  6  # XYZCommander is free software: you can redistribute it and/or modify 
  7  # it under the terms of the GNU Lesser Public License as published by 
  8  # the Free Software Foundation, either version 3 of the License, or 
  9  # (at your option) any later version. 
 10  # XYZCommander 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 
 13  # GNU Lesser Public License for more details. 
 14  # You should have received a copy of the GNU Lesser Public License 
 15  # along with XYZCommander. If not, see <http://www.gnu.org/licenses/>. 
 16   
 17  import libxyz 
 18   
 19  from libxyz.core.plugins import Namespace 
 20  from libxyz.core.utils import ustring 
 21  from libxyz.core.utils import is_func 
 22   
 23  from libxyz.ui import Shortcut 
 24   
 25  from libxyz.exceptions import PluginError 
 26  from libxyz.exceptions import KeyManagerError 
 27   
28 -class KeyManager(object):
29 """ 30 Key bindings management class 31 """ 32 33 CONTEXT_DEFAULT = u"DEFAULT" 34 CONTEXT_SELF = u"@" 35
36 - def __init__(self, xyz):
37 self.xyz = xyz 38 self.keys = libxyz.ui.Keys() 39 40 self._loaded_methods = {} 41 self._bind_data = {} 42 self._prefixes = []
43 44 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 45
46 - def process(self, pressed, context=None):
47 """ 48 Process pressed keys 49 50 @return: Tuple (method, arguments) 51 """ 52 53 context = context or self.CONTEXT_DEFAULT 54 _p = Shortcut(raw=pressed) 55 56 # Got prefix key. Now wait for another keystroke and proceed 57 if _p in self._prefixes: 58 _aux = self.xyz.input.get() 59 _p = Shortcut(raw=pressed + _aux) 60 61 _method = None 62 63 # Look for binded shortcut 64 try: 65 _method = self._bind_data[context][_p] 66 except KeyError: 67 # No bind 68 pass 69 70 return _method
71 72 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 73
74 - def set_prefix(self, shortcut):
75 """ 76 Set prefix key 77 """ 78 79 if not isinstance(shortcut, Shortcut): 80 raise KeyManagerError(_(u"Invalid shortcut type: %s.") % 81 ustring(type(shortcut))) 82 83 if shortcut not in self._prefixes: 84 self._prefixes.append(shortcut)
85 86 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 87 88
89 - def load(self, method):
90 """ 91 Load method 92 """ 93 94 _p = Namespace(method) 95 96 # Already loaded 97 if _p.full in self._loaded_methods: 98 return 99 100 # Wildcard 101 if _p.method == _p.ALL: 102 self._loaded_methods[_p.full] = _p.ALL 103 # Just load and instantiate plugin 104 elif _p.method is None: 105 self.xyz.pm.load(_p) 106 else: 107 self._loaded_methods[_p.full] = self.xyz.pm.from_load(_p.pfull, 108 _p.method)
109 110 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 111
112 - def bind(self, method, shortcut, context=None):
113 """ 114 Bind a shortcut to a method. 115 A method can be either a string, in that case it should denote the 116 plugin method or it can be a function. 117 118 @return: True on success, False otherwise, also raises exception 119 if method was not loaded 120 """ 121 122 if isinstance(method, basestring): 123 _p = Namespace(method) 124 _mobj = None 125 126 if context == self.CONTEXT_SELF: 127 context = _p.pfull 128 129 # First check if methods were loaded by wildcard ALL 130 if _p.full not in self._loaded_methods: 131 if "%s:%s" % (_p.pfull, _p.ALL) not in self._loaded_methods: 132 raise KeyManagerError(_(u"Method %s not loaded" % _p)) 133 134 # Else try to load specified method 135 try: 136 _mobj = self.xyz.pm.from_load(_p.pfull, _p.method) 137 except PluginError, e: 138 raise KeyManagerError(_(u"Load error: %s" % e)) 139 else: 140 _mobj = self._loaded_methods[_p.full] 141 142 if _mobj is None: 143 # Wait until plugin method is available and then run callback 144 self.xyz.pm.wait_for(_p, self._bind_wait_cb, _p.method, 145 shortcut, context) 146 147 elif is_func(method): 148 _mobj = method 149 _mobj.ns = _(u"<Internal function object>") 150 else: 151 raise KeyManagerError(_(u"Invalid method type: %s. "\ 152 u"Must be string or function") % 153 type(method)) 154 155 self._bind(_mobj, shortcut, context)
156 157 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 158
159 - def _bind_wait_cb(self, plugin_obj, method, shortcut, context):
160 if method not in plugin_obj.public: 161 xyzlog.error(_(u"Unable to bind method %s. "\ 162 u"Plugin %s doesn't export it." % 163 (method, plugin_obj.ns.pfull))) 164 return 165 166 self._bind(plugin_obj.public[method], shortcut, context, force=False)
167 168 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 169
170 - def _bind(self, mobj, shortcut, context=None, force=True):
171 if context is None: 172 context = self.CONTEXT_DEFAULT 173 174 if context not in self._bind_data: 175 self._bind_data[context] = {} 176 177 if shortcut in self._bind_data[context] and \ 178 self._bind_data[context][shortcut] is not None and not force: 179 return 180 181 self._bind_data[context][shortcut] = mobj
182 183 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 184
185 - def get_binds(self):
186 """ 187 Return keybindings data 188 """ 189 190 return self._bind_data
191