From 2c8fe66c0f7490c8aaaae27b4977b987001c6b71 Mon Sep 17 00:00:00 2001 From: mike Date: Tue, 01 Dec 2009 20:11:43 +0000 Subject: Merge branch 'master' of git://git.sugarlabs.org/tutorius/simpoirs-clone Conflicts: src/extensions/tutoriusremote.py tutorius/TProbe.py tutorius/creator.py --- (limited to 'tutorius/TProbe.py') diff --git a/tutorius/TProbe.py b/tutorius/TProbe.py index 1521eab..7021f80 100644 --- a/tutorius/TProbe.py +++ b/tutorius/TProbe.py @@ -1,10 +1,25 @@ +# Copyright (C) 2009, Tutorius.org +# +# 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 1 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 + import logging LOGGER = logging.getLogger("sugar.tutorius.TProbe") import os import gobject -import dbus import dbus.service import cPickle as pickle @@ -12,7 +27,6 @@ import cPickle as pickle from . import addon from . import properties from .services import ObjectStore -from .properties import TPropContainer from .dbustools import remote_call, save_args import copy @@ -78,8 +92,6 @@ class TProbe(dbus.service.Object): LOGGER.debug("TProbe :: registering '%s' with unique_id '%s'", self._activity_name, activity.get_id()) self._service_proxy.register_probe(self._activity_name, self._unique_id) - - def start(self): """ @@ -184,32 +196,12 @@ class TProbe(dbus.service.Object): in_signature='s', out_signature='s') def create_event(self, addon_name): # avoid recursive imports - from .creator import WidgetSelector, SignalInputDialog, TextInputDialog - event = addon.create(addon_name) addonname = type(event).__name__ meta = addon.get_addon_meta(addonname) for propname in meta['mandatory_props']: prop = getattr(type(event), propname) - if isinstance(prop, properties.TUAMProperty): - selector = WidgetSelector(self._activity) - setattr(event, propname, selector.select()) - elif isinstance(prop, properties.TEventType): - try: - dlg = SignalInputDialog(self._activity, - text="Mandatory property", - field=propname, - addr=event.object_id) - setattr(event, propname, dlg.pop()) - except AttributeError: - pass - elif isinstance(prop, properties.TStringProperty): - dlg = TextInputDialog(self._activity, - text="Mandatory property", - field=propname) - setattr(event, propname, dlg.pop()) - else: - raise NotImplementedError() + prop.widget_class.run_dialog(self._activity, event, propname) return pickle.dumps(event) @@ -322,7 +314,6 @@ class ProbeProxy: self._subscribedEvents = {} self._registeredCallbacks = {} - self._object.connect_to_signal("eventOccured", self._handle_signal, dbus_interface="org.tutorius.ProbeInterface") def _handle_signal(self, pickled_event): @@ -344,58 +335,57 @@ class ProbeProxy: except: return False - def __update_action(self, action, address): + def __update_action(self, action, callback, address): LOGGER.debug("ProbeProxy :: Updating action %s with address %s", str(action), str(address)) - self._actions[action] = str(address) + self._actions[address] = action + callback(address) - def __clear_action(self, action): - self._actions.pop(action, None) + def __clear_action(self, address): + self._actions.pop(address, None) - def install(self, action, block=False, is_editing=False): + def install(self, action, action_installed_cb, error_cb, is_editing=False): """ Install an action on the TProbe's activity @param action Action to install - @param block Force a synchroneous dbus call if True + @param action_installed_cb The callback function to call once the action is installed + @param error_cb The callback function to call when an error happens @param is_editing whether this action comes from the editor @return None """ - return remote_call(self._probe.install, - (pickle.dumps(action), is_editing), - save_args(self.__update_action, action), - block=block) + self._probe.install(pickle.dumps(action), is_editing, + reply_handler=save_args(self.__update_action, action, action_installed_cb), + error_handler=save_args(error_cb, action)) - def update(self, action, newaction, block=False, is_editing=False): + def update(self, action_address, newaction, is_editing=False): """ Update an already installed action's properties and run it again - @param action Action to update + @param action_address The address of the action to update. This is + provided by the install callback method. @param newaction Action to update it with @param block Force a synchroneous dbus call if True @param is_editing whether this action comes from the editor @return None """ #TODO review how to make this work well - if not action in self._actions.keys(): + if not action_address in self._actions.keys(): raise RuntimeWarning("Action not installed") #TODO Check error handling - return remote_call(self._probe.update, - (self._actions[action], - pickle.dumps(newaction._props), - is_editing), - block=block) + return self._probe.update(action_address, pickle.dumps(newaction._props), is_editing, + reply_handler=ignore, + error_handler=logError) - def uninstall(self, action, block=False, is_editing=False): + def uninstall(self, action_address, is_editing): """ Uninstall an installed action - @param action Action to uninstall - @param block Force a synchroneous dbus call if True + @param action_address The address of the action to uninstall. This address was given + on action installation @param is_editing whether this action comes from the editor """ - if action in self._actions.keys(): - remote_call(self._probe.uninstall, - (self._actions.pop(action), is_editing), - block=block) + if action_address in self._actions: + self._actions.pop(action_address, None) + self._probe.uninstall(action_address, is_editing, reply_handler=ignore, error_handler=logError) - def __update_event(self, event, callback, address): + def __update_event(self, event, callback, event_subscribed_cb, address): LOGGER.debug("ProbeProxy :: Registered event %s with address %s", str(hash(event)), str(address)) # Since multiple callbacks could be associated to the same # event signature, we will store multiple callbacks @@ -411,7 +401,7 @@ class ProbeProxy: # TODO elavoie 2009-07-25 decide on a proper exception # taxonomy if self._registeredCallbacks[event].has_key(address): - # Oups, how come we have two similar addresses? + # Oops, how come we have two similar addresses? # send the bad news! raise Exception("Probe subscribe exception, the following address already exists: " + str(address)) @@ -424,6 +414,7 @@ class ProbeProxy: # our dictionary (python pass arguments by reference) self._subscribedEvents[address] = copy.copy(event) + event_subscribed_cb(address) return address def __clear_event(self, address): @@ -453,24 +444,26 @@ class ProbeProxy: """ return pickle.loads(str(self._probe.create_event(addon_name))) - def subscribe(self, event, callback, block=True): + def subscribe(self, event, notification_cb, event_subscribed_cb, error_cb): + """ Register an event listener @param event Event to listen for - @param callback callable that will be called when the event occurs - @param block Force a synchroneous dbus call if True (Not allowed yet) + @param notification_cb callable that will be called when the event occurs + @param event_installed_cb callable that will be called once the event is subscribed to + @param error_cb callable that will be called if the subscription fails @return address identifier used for unsubscribing """ LOGGER.debug("ProbeProxy :: Registering event %s", str(hash(event))) - if not block: - raise RuntimeError("This function does not allow non-blocking mode yet") + #if not block: + # raise RuntimeError("This function does not allow non-blocking mode yet") # TODO elavoie 2009-07-25 When we will allow for patterns both # for event types and sources, we will need to revise the lookup # mecanism for which callback function to call - return remote_call(self._probe.subscribe, (pickle.dumps(event),), - save_args(self.__update_event, event, callback), - block=block) + self._probe.subscribe(pickle.dumps(event), + reply_handler=save_args(self.__update_event, event, notification_cb, event_subscribed_cb), + error_handler=save_args(error_cb, event)) def unsubscribe(self, address, block=True): """ @@ -481,9 +474,10 @@ class ProbeProxy: """ LOGGER.debug("ProbeProxy :: Unregister adress %s issued", str(address)) if address in self._subscribedEvents.keys(): - remote_call(self._probe.unsubscribe, (address,), - return_cb=save_args(self.__clear_event, address), - block=block) + self.__clear_event(address) + self._probe.unsubscribe(address, + reply_handler=save_args(self.__clear_event, address), + error_handler=logError) else: LOGGER.debug("ProbeProxy :: unsubscribe address %s failed : not registered", address) @@ -493,10 +487,10 @@ class ProbeProxy: subscribed events should be removed. """ for action_addr in self._actions.keys(): - self.uninstall(action_addr, block) + self.uninstall(action_addr) for address in self._subscribedEvents.keys(): - self.unsubscribe(address, block) + self.unsubscribe(address) class ProbeManager(object): @@ -536,43 +530,48 @@ class ProbeManager(object): currentActivity = property(fget=getCurrentActivity, fset=setCurrentActivity) - def install(self, action, block=False, is_editing=False): + def install(self, action, action_installed_cb, error_cb, is_editing=False): """ Install an action on the current activity @param action Action to install + @param action_installed_cb The callback to call once the action is installed + @param error_cb The callback that will be called if there is an error during installation @param block Force a synchroneous dbus call if True @param is_editing whether this action comes from the editor @return None """ if self.currentActivity: - return self._first_proxy(self.currentActivity).install(action, block, is_editing) + return self._first_proxy(self.currentActivity).install( + action=action, + is_editing=is_editing, + action_installed_cb=action_installed_cb, + error_cb=error_cb) else: raise RuntimeWarning("No activity attached") - def update(self, action, newaction, block=False, is_editing=False): + def update(self, action_address, newaction, is_editing=False): """ Update an already installed action's properties and run it again - @param action Action to update + @param action_address Action to update @param newaction Action to update it with @param block Force a synchroneous dbus call if True @param is_editing whether this action comes from the editor @return None """ if self.currentActivity: - return self._first_proxy(self.currentActivity).update(action, newaction, block, is_editing) + return self._first_proxy(self.currentActivity).update(action_address, newaction, is_editing) else: raise RuntimeWarning("No activity attached") - def uninstall(self, action, block=False, is_editing=False): + def uninstall(self, action_address, is_editing=False): """ Uninstall an installed action - @param action Action to uninstall + @param action_address Action to uninstall @param block Force a synchroneous dbus call if True @param is_editing whether this action comes from the editor """ if self.currentActivity: - # return self._probes[self.currentActivity].uninstall(action, block, is_editing) - return self._first_proxy(self.currentActivity).uninstall(action, block, is_editing) + return self._first_proxy(self.currentActivity).uninstall(action_address, is_editing) else: raise RuntimeWarning("No activity attached") @@ -585,19 +584,24 @@ class ProbeManager(object): @returns: an eventfilter instance """ if self.currentActivity: - return self._first_proxy(self.currentActivity).uninstall(action, block) + return self._first_proxy(self.currentActivity).create_event(addon_name) else: raise RuntimeWarning("No activity attached") - def subscribe(self, event, callback): + def subscribe(self, event, notification_cb, event_subscribed_cb, error_cb): """ Register an event listener @param event Event to listen for - @param callback callable that will be called when the event occurs + @param notification_cb callable that will be called when the event occurs + @param subscribe_cb callable that will be called once the action has been + installed + @param error_cb callable that will be called if an error happens during + installation @return address identifier used for unsubscribing """ if self.currentActivity: - return self._first_proxy(self.currentActivity).subscribe(event, callback) + return self._first_proxy(self.currentActivity).subscribe(event, notification_cb,\ + event_subscribed_cb, error_cb) else: raise RuntimeWarning("No activity attached") -- cgit v0.9.1