From 0c3f127c86af818d260966d2292b199757087157 Mon Sep 17 00:00:00 2001 From: Simon Poirier Date: Sat, 11 Jul 2009 21:39:46 +0000 Subject: repackage --- (limited to 'tutorius/gtkutils.py') diff --git a/tutorius/gtkutils.py b/tutorius/gtkutils.py new file mode 100644 index 0000000..1a9cb0f --- /dev/null +++ b/tutorius/gtkutils.py @@ -0,0 +1,203 @@ +# Copyright (C) 2009, Tutorius.org +# Copyright (C) 2009, Vincent Vinet +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +""" +Utility classes and functions that are gtk related +""" +import gtk + +def raddr_lookup(widget): + name = [] + child = widget + parent = widget.parent + while parent: + name.append(str(parent.get_children().index(child))) + child = parent + parent = child.parent + + name.append("0") # root object itself + name.reverse() + return ".".join(name) + + +def find_widget(base, target_fqdn): + """Find a widget by digging into a parent widget's children tree + @param base the parent widget + @param target_fqdn fqdn-style target object name + + @return widget found + + The object should normally be the activity widget, as it is the root + widget for activities. The target_fqdn is a dot separated list of + indexes used in widget.get_children and should start with a 0 which is + the base widget itself, + + Example Usage: + find_widget(activity,"0.0.0.1.0.0.2") + """ + path = target_fqdn.split(".") + #We select the first object and pop the first zero + obj = base + path.pop(0) + + while len(path) > 0: + try: + obj = get_children(obj)[int(path.pop(0))] + except: + break + + return obj + +EVENTS = ( + "focus", + "button-press-event", + "enter-notify-event", + "leave-notify-event", + "key-press-event", + "text-selected", + "clicked", +) + +IGNORED_WIDGETS = ( + "GtkVBox", + "GtkHBox", + "GtkAlignment", + "GtkNotebook", + "GtkButton", + "GtkToolItem", + "GtkToolbar", +) + +def register_signals_numbered(target, handler, prefix="0", max_depth=None, events=None): + """ + Recursive function to register event handlers on an target + and it's children. The event handler is called with an extra + argument which is a two-tuple containing the signal name and + the FQDN-style name of the target that triggered the event. + + This function registers all of the events listed in + EVENTS + + Example arg tuple added: + ("focus", "1.1.2") + Side effects: + -Handlers connected on the various targets + + @param target the target to recurse on + @param handler the handler function to connect + @param prefix name prepended to the target name to form a chain + @param max_depth maximum recursion depth, None for infinity + + @returns list of (object, handler_id) + """ + ret = [] + evts = events or EVENTS + #Gtk Containers have a get_children() function + children = get_children(target) + for i in range(len(children)): + child = children[i] + if max_depth is None or max_depth > 0: + #Recurse with a prefix on all children + pre = ".".join( \ + [p for p in (prefix, str(i)) if not p is None] + ) + if max_depth is None: + dep = None + else: + dep = max_depth - 1 + ret+=register_signals_numbered(child, handler, pre, dep, evts) + #register events on the target if a widget XXX necessary to check this? + if isinstance(target, gtk.Widget): + for sig in evts: + try: + ret.append( \ + (target, target.connect(sig, handler, (sig, prefix) ))\ + ) + except TypeError: + pass + + return ret + +def register_signals(target, handler, prefix=None, max_depth=None, events=None): + """ + Recursive function to register event handlers on an target + and it's children. The event handler is called with an extra + argument which is a two-tuple containing the signal name and + the FQDN-style name of the target that triggered the event. + + This function registers all of the events listed in + EVENTS and omits widgets with a name matching + IGNORED_WIDGETS from the name hierarchy. + + Example arg tuple added: + ("focus", "Activity.Toolbox.Bold") + Side effects: + -Handlers connected on the various targets + + @param target the target to recurse on + @param handler the handler function to connect + @param prefix name prepended to the target name to form a chain + @param max_depth maximum recursion depth, None for infinity + + @returns list of (object, handler_id) + """ + ret = [] + evts = events or EVENTS + #Gtk Containers have a get_children() function + for child in get_children(target): + if max_depth is None or max_depth > 0: + #Recurse with a prefix on all children + pre = ".".join( \ + [p for p in (prefix, target.get_name()) \ + if not (p is None or p in IGNORED_WIDGETS)] \ + ) + if max_depth is None: + dep = None + else: + dep = max_depth - 1 + ret += register_signals(child, handler, pre, dep, evts) + name = ".".join( \ + [p for p in (prefix, target.get_name()) \ + if not (p is None or p in IGNORED_WIDGETS)] \ + ) + #register events on the target if a widget XXX necessary to check this? + if isinstance(target, gtk.Widget): + for sig in evts: + try: + ret.append( \ + (target, target.connect(sig, handler, (sig, name) )) \ + ) + except TypeError: + pass + + return ret + +def get_children(widget): + """Lists widget's children""" + #widgets with multiple children + try: + return widget.get_children() + except (AttributeError,TypeError): + pass + + #widgets with a single child + try: + return [widget.get_child(),] + except (AttributeError,TypeError): + pass + + #otherwise return empty list + return [] -- cgit v0.9.1