Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVincent Vinet <vince.vinet@gmail.com>2009-03-25 18:26:30 (GMT)
committer Vincent Vinet <vince.vinet@gmail.com>2009-03-30 18:04:51 (GMT)
commitf14b5e3e41af68866edd706c9d48db61f3e0da4f (patch)
treeadbdb6d81d487650c823de86bb9231fe367f5d00
parent0b7e950b799b6904e4656fe756776ace36a2cf1a (diff)
Add the filters and treeview in the editor, and get_children in gtkutils
-rw-r--r--src/sugar/tutorius/editor.py176
-rw-r--r--src/sugar/tutorius/gtkutils.py90
2 files changed, 199 insertions, 67 deletions
diff --git a/src/sugar/tutorius/editor.py b/src/sugar/tutorius/editor.py
index 1a1eb61..bf70216 100644
--- a/src/sugar/tutorius/editor.py
+++ b/src/sugar/tutorius/editor.py
@@ -14,17 +14,22 @@
# 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
+""" Tutorial Editor Module
+"""
import gtk
import gobject
-import hippo
-import gconf
+#import hippo
+#import gconf
from gettext import gettext as _
+from sugar.tutorius.gtkutils import register_signals_numbered, get_children
+
class WidgetIdentifier(gtk.Window):
"""
- Tool that allows identifying widgets
+ Tool that allows identifying widgets.
+
"""
__gtype_name__ = 'TutoriusWidgetIdentifier'
@@ -32,7 +37,19 @@ class WidgetIdentifier(gtk.Window):
gtk.Window.__init__(self)
self._activity = activity
- self._handlers = []
+ self._handlers = {}
+ # dict of signals to register on the widgets.
+ # key : signal name
+ # value : initial checkbox status
+ signals = {
+ "focus":True,
+ "button-press-event":True,
+ "enter-notify-event":False,
+ "leave-notify-event":False,
+ "key-press-event":True,
+ "text-selected":True,
+ "clicked":True,
+ }
self.set_decorated(False)
self.set_resizable(False)
@@ -47,63 +64,164 @@ class WidgetIdentifier(gtk.Window):
self._expander.show()
- vbox = gtk.VBox()
- self._expander.add(vbox)
- vbox.show()
-
+ nbk = gtk.Notebook()
+ self._expander.add(nbk)
+ nbk.show()
+ ###############################
+ # Event log viewer page
+ ###############################
self.logview = gtk.TextView()
self.logview.set_editable(False)
self.logview.set_cursor_visible(False)
self.logview.set_wrap_mode(gtk.WRAP_NONE)
self._textbuffer = self.logview.get_buffer()
- sw = gtk.ScrolledWindow()
- sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
- sw.add(self.logview)
+ swd = gtk.ScrolledWindow()
+ swd.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
+ swd.add(self.logview)
self.logview.show()
- vbox.pack_start(sw)
- sw.show()
-
- from sugar.tutorius.gtkutils import register_signals_numbered
- self._handlers = register_signals_numbered(self._activity, self._handle_events)
+ nbk.append_page(swd, gtk.Label(_("Log")))
+ swd.show()
+
+ ###############################
+ # Filters page
+ ###############################
+ filters = gtk.Table( (len(signals)+1)/2, 2)
+
+ xpos, ypos = 0, 0
+ for key, active in signals.items():
+ cbtn = gtk.CheckButton(label=key)
+ filters.attach(cbtn, xpos, xpos+1, ypos, ypos+1)
+ cbtn.show()
+ cbtn.set_active(active)
+ if active:
+ self._handlers[key] = register_signals_numbered( \
+ self._activity, self._handle_events, events=(key,))
+ else:
+ self._handlers[key] = []
+
+ cbtn.connect("toggled", self.__filter_toggle_cb, key)
+
+ #Follow lines then columns
+ xpos, ypos = (xpos+1)%2, ypos+(xpos%2)
+
+ nbk.append_page(filters, gtk.Label(_("Events")))
+ filters.show()
+
+ ###############################
+ # Explorer Page
+ ###############################
+ tree = gtk.TreeStore(gobject.TYPE_STRING, gobject.TYPE_STRING)
+ explorer = gtk.TreeView(tree)
+
+ pathrendr = gtk.CellRendererText()
+ pathrendr.set_properties(background="#ffffff", foreground="#000000")
+ pathcol = gtk.TreeViewColumn(_("Path"), pathrendr, text=0, background=0, foreground=0)
+ explorer.append_column(pathcol)
+
+ typerendr = gtk.CellRendererText()
+ typerendr.set_properties(background="#ffffff", foreground="#000000")
+ typecol = gtk.TreeViewColumn(_("Widget"), typerendr, text=1, background=1, foreground=1)
+ explorer.append_column(typecol)
+
+ self.__populate_treestore(
+ tree, #tree
+ tree.append(None, ["0",self._activity.get_name()]), #parent
+ self._activity, #widget
+ "0" #path
+ )
- def __expander_cb(self, *args):
+ explorer.set_expander_column(typecol)
+
+ swd2 = gtk.ScrolledWindow()
+ swd2.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
+ swd2.add(explorer)
+ explorer.show()
+ nbk.append_page(swd2, gtk.Label(_("Explorer")))
+ swd2.show()
+
+ def __populate_treestore(self, tree, parent, widget, path):
+ """Populates the treestore with the widget's children recursively
+ @param tree gtk.TreeStore to populate
+ @param parent gtk.TreeIter to append to
+ @param widget gtk.Widget to check for children
+ @param path treeish of the widget
+ """
+ #DEBUG: show parameters in log window gehehe
+ #self._handle_events((path,str(type(widget))))
+ children = get_children(widget)
+ for i in xrange(len(children)):
+ childpath = ".".join([path, str(i)])
+ child = children[i]
+ self.__populate_treestore(
+ tree, #tree
+ tree.append(parent, [childpath, child.get_name()]), #parent
+ child, #widget
+ childpath #path
+ )
+
+
+ def __filter_toggle_cb(self, btn, eventname):
+ """Callback for signal name checkbuttons' toggling"""
+ #Disconnect existing handlers on key
+ self.__disconnect_handlers(eventname)
+ if btn.get_active():
+ #if checked, reconnect
+ self._handlers[eventname] = register_signals_numbered( \
+ self._activity, self._handle_events, events=(eventname,))
+
+
+ def __expander_cb(self, *args):
+ """Callback for the window expander toggling"""
if self._expander.get_expanded():
self.__move_expanded()
else:
self.__move_collapsed()
def __move_expanded(self):
- width = 400
+ """Move the window to it's expanded position"""
+ width = 500
height = 300
- ww = gtk.gdk.screen_width()
- wh = gtk.gdk.screen_height()
+ swidth = gtk.gdk.screen_width()
+ sheight = gtk.gdk.screen_height()
self.set_size_request(width, height)
- self.move((ww-width)/2, wh-height)
+ self.move((swidth-width)/2, sheight-height)
def __move_collapsed(self):
+ """Move the window to it's collapsed position"""
width = 150
height = 40
- ww = gtk.gdk.screen_width()
- wh = gtk.gdk.screen_height()
+ swidth = gtk.gdk.screen_width()
+ sheight = gtk.gdk.screen_height()
self.set_size_request(width, height)
- self.move((ww-width)/2, wh-height)
+ self.move((swidth-width)/2, sheight-height)
def __realize_cb(self, widget):
+ """Callback for realize"""
self.window.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DIALOG)
self.window.set_accept_focus(True)
self.__move_expanded()
def _disconnect_handlers(self):
- for widget, handlerid in self._handlers:
- widget.handler_disconnect(handlerid)
- self._handlers = []
-
- def _handle_events(self,*args):
+ """ Disconnect all event handlers """
+ for key in self._handlers:
+ self.__disconnect_handlers(key)
+
+ def __disconnect_handlers(self, key):
+ """ Disconnect event handlers associated to signal name "key" """
+ if self._handlers.has_key(key):
+ for widget, handlerid in self._handlers[key]:
+ widget.handler_disconnect(handlerid)
+ del self._handlers[key]
+
+ def _handle_events(self, *args):
+ """ Event handler for subscribed widget events.
+ Accepts variable length argument list. Last must be
+ a two-tuple containing (event name, widget name) """
sig, name = args[-1]
text = "\r\n".join(
(["%s event received from %s" % (sig, name)] +
diff --git a/src/sugar/tutorius/gtkutils.py b/src/sugar/tutorius/gtkutils.py
index 1870dc4..bbd8863 100644
--- a/src/sugar/tutorius/gtkutils.py
+++ b/src/sugar/tutorius/gtkutils.py
@@ -47,13 +47,13 @@ def find_widget(base, target_fqdn):
while len(path) > 0:
try:
- obj = obj.get_children()[int(path.pop(0))]
+ obj = get_children(obj)[int(path.pop(0))]
except:
break
return obj
-EVENTS = [
+EVENTS = (
"focus",
"button-press-event",
"enter-notify-event",
@@ -61,9 +61,9 @@ EVENTS = [
"key-press-event",
"text-selected",
"clicked",
-]
+)
-IGNORED_WIDGETS = [
+IGNORED_WIDGETS = (
"GtkVBox",
"GtkHBox",
"GtkAlignment",
@@ -71,9 +71,9 @@ IGNORED_WIDGETS = [
"GtkButton",
"GtkToolItem",
"GtkToolbar",
-]
+)
-def register_signals_numbered(target, handler, prefix="0", max_depth=None):
+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
@@ -96,25 +96,24 @@ def register_signals_numbered(target, handler, prefix="0", max_depth=None):
@returns list of (object, handler_id)
"""
ret = []
+ evts = events or EVENTS
#Gtk Containers have a get_children() function
- if hasattr(target, "get_children") and \
- hasattr(target.get_children, "__call__"):
- children = target.get_children()
- 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)
+ 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 EVENTS:
+ for sig in evts:
try:
ret.append( \
(target, target.connect(sig, handler, (sig, prefix) ))\
@@ -124,7 +123,7 @@ def register_signals_numbered(target, handler, prefix="0", max_depth=None):
return ret
-def register_signals(target, handler, prefix=None, max_depth=None):
+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
@@ -148,28 +147,27 @@ def register_signals(target, handler, prefix=None, max_depth=None):
@returns list of (object, handler_id)
"""
ret = []
+ evts = events or EVENTS
#Gtk Containers have a get_children() function
- if hasattr(target, "get_children") and \
- hasattr(target.get_children, "__call__"):
- for child in target.get_children():
- 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)
+ 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 EVENTS:
+ for sig in evts:
try:
ret.append( \
(target, target.connect(sig, handler, (sig, name) )) \
@@ -179,3 +177,19 @@ def register_signals(target, handler, prefix=None, max_depth=None):
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 []