# 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() 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): """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)