Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/tutorius/editor.py
diff options
context:
space:
mode:
Diffstat (limited to 'tutorius/editor.py')
-rw-r--r--tutorius/editor.py318
1 files changed, 318 insertions, 0 deletions
diff --git a/tutorius/editor.py b/tutorius/editor.py
new file mode 100644
index 0000000..42cc718
--- /dev/null
+++ b/tutorius/editor.py
@@ -0,0 +1,318 @@
+# Copyright (C) 2009, Tutorius.org
+# Greatly influenced by sugar/activity/namingalert.py
+#
+# 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
+""" Tutorial Editor Module
+"""
+
+import gtk
+import gobject
+#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.
+
+ """
+ __gtype_name__ = 'TutoriusWidgetIdentifier'
+
+ def __init__(self, activity):
+ gtk.Window.__init__(self)
+
+ self._activity = activity
+ 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)
+ self.set_modal(False)
+
+ self.connect('realize', self.__realize_cb)
+
+ self._expander = gtk.Expander(_("Widget Identifier"))
+ self._expander.set_expanded(True)
+ self.add(self._expander)
+ self._expander.connect("notify::expanded", self.__expander_cb)
+
+ self._expander.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()
+
+ swd = gtk.ScrolledWindow()
+ swd.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
+ swd.add(self.logview)
+ self.logview.show()
+
+ 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
+ )
+
+ 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()
+
+ ###############################
+ # GObject Explorer Page
+ ###############################
+ tree2 = gtk.TreeStore(gobject.TYPE_STRING, gobject.TYPE_STRING)
+ explorer2 = gtk.TreeView(tree2)
+
+ pathrendr2 = gtk.CellRendererText()
+ pathrendr2.set_properties(background="#ffffff", foreground="#000000")
+ pathcol2 = gtk.TreeViewColumn(_("Path"), pathrendr2, text=0, background=0, foreground=0)
+ explorer2.append_column(pathcol2)
+
+ typerendr2 = gtk.CellRendererText()
+ typerendr2.set_properties(background="#ffffff", foreground="#000000")
+ typecol2 = gtk.TreeViewColumn(_("Widget"), typerendr2, text=1, background=1, foreground=1)
+ explorer2.append_column(typecol2)
+
+ self.__populate_gobject_treestore(
+ tree2, #tree
+ tree2.append(None, ["activity",self._activity.get_name()]), #parent
+ self._activity, #widget
+ "activity" #path
+ )
+
+ explorer2.set_expander_column(typecol2)
+
+ swd3 = gtk.ScrolledWindow()
+ swd3.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
+ swd3.add(explorer2)
+ explorer2.show()
+ nbk.append_page(swd3, gtk.Label(_("GObject Explorer")))
+ swd3.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 __populate_gobject_treestore(self, tree, parent, widget, path, listed=None):
+ """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
+ """
+ listed = listed or []
+ if widget in listed:
+ return
+ listed.append(widget)
+ #DEBUG: show parameters in log window gehehe
+ #self._handle_events((path,str(type(widget))))
+ #Add a child node
+ children = tree.append(parent, ["","children"])
+ for i in dir(widget):
+ #Add if a gobject
+ try:
+ child = getattr(widget, i)
+ except:
+ continue
+ if isinstance(child,gobject.GObject):
+ childpath = ".".join([path, i])
+ child = getattr(widget, i)
+ self.__populate_gobject_treestore(
+ tree, #tree
+ tree.append(children, [childpath, i]), #parent
+ child, #widget
+ path + "." + i, #path,
+ listed
+ )
+ widgets = tree.append(parent, ["","widgets"])
+ wchildren = get_children(widget)
+ for i in xrange(len(wchildren)):
+ childpath = ".".join([path, str(i)])
+ child = wchildren[i]
+ self.__populate_gobject_treestore(
+ tree, #tree
+ tree.append(widgets, [childpath, (hasattr(child,"get_name") and child.get_name()) or i]), #parent
+ child, #widget
+ childpath, #path,
+ listed
+ )
+
+ #Add signals and attributes nodes
+ signals = tree.append(parent, ["","signals"])
+ for signame in gobject.signal_list_names(widget):
+ tree.append(signals, ["",signame])
+
+ attributes = tree.append(parent, ["","properties"])
+ for prop in gobject.list_properties(widget):
+ tree.append(attributes, ["",prop])
+
+ 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):
+ """Move the window to it's expanded position"""
+ width = 500
+ height = 300
+ swidth = gtk.gdk.screen_width()
+ sheight = gtk.gdk.screen_height()
+
+ self.set_size_request(width, height)
+ self.move((swidth-width)/2, sheight-height)
+
+ def __move_collapsed(self):
+ """Move the window to it's collapsed position"""
+ width = 150
+ height = 40
+ swidth = gtk.gdk.screen_width()
+ sheight = gtk.gdk.screen_height()
+
+ self.set_size_request(width, 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):
+ """ 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)] +
+ self._textbuffer.get_text(*(self._textbuffer.get_bounds())
+ ).split("\r\n"))[:80]
+ )
+ self._textbuffer.set_text(text)
+
+