diff options
Diffstat (limited to 'gi/_gtktemplate.py')
-rw-r--r-- | gi/_gtktemplate.py | 49 |
1 files changed, 40 insertions, 9 deletions
diff --git a/gi/_gtktemplate.py b/gi/_gtktemplate.py index 15f6b2c5..a631a6eb 100644 --- a/gi/_gtktemplate.py +++ b/gi/_gtktemplate.py @@ -17,26 +17,57 @@ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 # USA +from collections import abc from functools import partial from gi.repository import GLib, GObject, Gio +def _extract_handler_and_args(obj_or_map, handler_name): + handler = None + if isinstance(obj_or_map, abc.Mapping): + handler = obj_or_map.get(handler_name, None) + else: + handler = getattr(obj_or_map, handler_name, None) + + if handler is None: + raise AttributeError('Handler %s not found' % handler_name) + + args = () + if isinstance(handler, abc.Sequence): + if len(handler) == 0: + raise TypeError("Handler %s tuple can not be empty" % handler) + args = handler[1:] + handler = handler[0] + + elif not callable(handler): + raise TypeError('Handler %s is not a method, function or tuple' % handler) + + return handler, args + + def define_builder_scope(): from gi.repository import Gtk class BuilderScope(GObject.GObject, Gtk.BuilderScope): - def __init__(self): + def __init__(self, scope_object=None): super().__init__() + self._scope_object = scope_object def do_create_closure(self, builder, func_name, flags, obj): - current_object = builder.get_current_object() + current_object = builder.get_current_object() or self._scope_object - if func_name not in current_object.__gtktemplate_methods__: - return None + if not self._scope_object: + current_object = builder.get_current_object() + if func_name not in current_object.__gtktemplate_methods__: + return None - current_object.__gtktemplate_handlers__.add(func_name) + current_object.__gtktemplate_handlers__.add(func_name) + handler_name = current_object.__gtktemplate_methods__[func_name] + else: + current_object = self._scope_object + handler_name = func_name swapped = int(flags & Gtk.BuilderClosureFlags.SWAPPED) if swapped: @@ -44,12 +75,12 @@ def define_builder_scope(): "%r not supported" % GObject.ConnectFlags.SWAPPED) return None - handler_name = current_object.__gtktemplate_methods__[func_name] - handler = getattr(current_object, handler_name) + handler, args = _extract_handler_and_args(current_object, handler_name) + if obj: - return partial(handler, swap_data=obj) + return partial(handler, *args, swap_data=obj) - return handler + return partial(handler, *args) return BuilderScope |