Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/tutorius/TProbe.py
diff options
context:
space:
mode:
authormike <michael.jmontcalm@gmail.com>2009-12-04 02:21:14 (GMT)
committer mike <michael.jmontcalm@gmail.com>2009-12-04 02:21:14 (GMT)
commit49ab39870266196f6267f83dd6951f839ebde773 (patch)
tree116fb1552882edf5b4e42bbcc293c5ec918abca4 /tutorius/TProbe.py
parentb8c9419f0381c1864035af76853ed1c02ad434cc (diff)
parent243d29608df4816f791c98407c10fa8a702574e1 (diff)
Merge ../../simpoirs-clone into remote_integration
Conflicts: src/extensions/tutoriusremote.py
Diffstat (limited to 'tutorius/TProbe.py')
-rw-r--r--tutorius/TProbe.py177
1 files changed, 141 insertions, 36 deletions
diff --git a/tutorius/TProbe.py b/tutorius/TProbe.py
index d0cc6e1..c0eedee 100644
--- a/tutorius/TProbe.py
+++ b/tutorius/TProbe.py
@@ -20,16 +20,16 @@ import os
import gobject
-import dbus
import dbus.service
import cPickle as pickle
+from functools import partial
from . import addon
+from . import properties
from .services import ObjectStore
-from .properties import TPropContainer
-from .dbustools import save_args, ignore, logError
+from .dbustools import remote_call, save_args, ignore, logError
import copy
"""
@@ -127,11 +127,12 @@ class TProbe(dbus.service.Object):
# ------------------ Action handling --------------------------------------
@dbus.service.method("org.tutorius.ProbeInterface",
- in_signature='s', out_signature='s')
- def install(self, pickled_action):
+ in_signature='sb', out_signature='s')
+ def install(self, pickled_action, is_editing):
"""
Install an action on the Activity
@param pickled_action string pickled action
+ @param is_editing whether this action comes from the editor
@return string address of installed action
"""
loaded_action = pickle.loads(str(pickled_action))
@@ -144,17 +145,22 @@ class TProbe(dbus.service.Object):
if action._props:
action._props.update(loaded_action._props)
- action.do(activity=self._activity)
-
+ if not is_editing:
+ action.do(activity=self._activity)
+ else:
+ action.enter_editmode()
+ action.set_notification_cb(partial(self.update_action, address))
+
return address
@dbus.service.method("org.tutorius.ProbeInterface",
- in_signature='ss', out_signature='')
- def update(self, address, action_props):
+ in_signature='ssb', out_signature='')
+ def update(self, address, action_props, is_editing):
"""
Update an already registered action
@param address string address returned by install()
@param action_props pickled action properties
+ @param is_editing whether this action comes from the editor
@return None
"""
action = self._installedActions[address]
@@ -162,26 +168,47 @@ class TProbe(dbus.service.Object):
if action._props:
props = pickle.loads(str(action_props))
action._props.update(props)
- action.undo()
- action.do()
+ if not is_editing:
+ action.undo()
+ action.do()
+ else:
+ action.exit_editmode()
+ action.enter_editmode()
@dbus.service.method("org.tutorius.ProbeInterface",
- in_signature='s', out_signature='')
- def uninstall(self, address):
+ in_signature='sb', out_signature='')
+ def uninstall(self, address, is_editing):
"""
Uninstall an action
@param address string address returned by install()
+ @param is_editing whether this action comes from the editor
@return None
"""
if self._installedActions.has_key(address):
action = self._installedActions[address]
- action.undo()
+ if not is_editing:
+ action.undo()
+ else:
+ action.exit_editmode()
self._installedActions.pop(address)
# ------------------ Event handling ---------------------------------------
@dbus.service.method("org.tutorius.ProbeInterface",
in_signature='s', out_signature='s')
+ def create_event(self, addon_name):
+ # avoid recursive imports
+ 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)
+ prop.widget_class.run_dialog(self._activity, event, propname)
+
+ return pickle.dumps(event)
+
+ @dbus.service.method("org.tutorius.ProbeInterface",
+ in_signature='s', out_signature='s')
def subscribe(self, pickled_event):
"""
Subscribe to an Event
@@ -214,7 +241,6 @@ class TProbe(dbus.service.Object):
@param address string adress returned by subscribe()
@return None
"""
-
if self._subscribedEvents.has_key(address):
eventfilter = self._subscribedEvents[address]
eventfilter.remove_handlers()
@@ -235,6 +261,21 @@ class TProbe(dbus.service.Object):
else:
raise RuntimeWarning("Attempted to raise an unregistered event")
+ @dbus.service.signal("org.tutorius.ProbeInterface")
+ def addonUpdated(self, addon_address, pickled_diff_dict):
+ # Don't do any added processing, the signal will be sent
+ # when the method exits
+ pass
+
+ def update_action(self, addon_address, diff_dict):
+ LOGGER.debug("TProbe :: Trying to update action %s with new property dict %s"%(addon_address, str(diff_dict)))
+ # Check that this action is installed
+ if addon_address in self._installedActions.keys():
+ LOGGER.debug("TProbe :: Updating action %s"%(addon_address))
+ self.addonUpdated(addon_address, pickle.dumps(diff_dict))
+ else:
+ raise RuntimeWarning("Attempted to updated an action that wasn't installed")
+
# Return a unique name for this action
def _generate_action_reference(self, action):
# TODO elavoie 2009-07-25 Should return a universal address
@@ -282,6 +323,7 @@ class ProbeProxy:
self._probe = dbus.Interface(self._object, "org.tutorius.ProbeInterface")
self._actions = {}
+ self._edition_callbacks = {}
# We keep those two data structures to be able to have multiple callbacks
# for the same event and be able to remove them independently
# _subscribedEvents holds a list of callback addresses's for each event
@@ -290,6 +332,17 @@ class ProbeProxy:
self._registeredCallbacks = {}
self._object.connect_to_signal("eventOccured", self._handle_signal, dbus_interface="org.tutorius.ProbeInterface")
+ self._object.connect_to_signal("addonUpdated", self._handle_update_signal, dbus_interface="org.tutorius.ProbeInterface")
+
+ def _handle_update_signal(self, addon_address, pickled_diff_dict):
+ address = str(addon_address)
+ diff_dict = pickle.loads(str(pickled_diff_dict))
+ LOGGER.debug("ProbeProxy :: Received update property for action %s"%(address))
+ # Launch the callback to warn the upper layers of a modification of the addon
+ # from a widget inside the activity
+ if self._edition_callbacks.has_key(address):
+ LOGGER.debug("ProbeProxy :: Executing update callback...")
+ self._edition_callbacks[address](address, diff_dict)
def _handle_signal(self, pickled_event):
event = pickle.loads(str(pickled_event))
@@ -310,33 +363,47 @@ class ProbeProxy:
except:
return False
- def __update_action(self, action, callback, address):
+ def __update_action(self, action, callback, editing_cb, address):
LOGGER.debug("ProbeProxy :: Updating action %s with address %s", str(action), str(address))
+ address = str(address)
+ # Store the action
self._actions[address] = action
+ # Store the edition callback
+ if editing_cb:
+ self._edition_callbacks[address] = editing_cb
+ # Propagate the action installed callback upwards in the stack
callback(address)
def __clear_action(self, address):
+ # Remove the action installed at this address
self._actions.pop(address, None)
+ # Remove the edition callback
+ self._edition_callbacks.pop(address, None)
- def install(self, action, action_installed_cb, error_cb):
+ def install(self, action, action_installed_cb, error_cb, is_editing=False, editing_cb=None):
"""
Install an action on the TProbe's activity
@param action Action to install
@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
+ @param editing_cb The function to execute when the action is updated
+ (this is only done in edition mode)
@return None
"""
- self._probe.install(pickle.dumps(action),
- reply_handler=save_args(self.__update_action, action, action_installed_cb),
- error_handler=save_args(error_cb, action))
+ self._probe.install(pickle.dumps(action),
+ is_editing,
+ reply_handler=save_args(self.__update_action, action, action_installed_cb, editing_cb),
+ error_handler=save_args(error_cb, action))
- def update(self, action_address, newaction):
+ def update(self, action_address, newaction, is_editing=False):
"""
Update an already installed action's properties and run it again
@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
@@ -344,19 +411,20 @@ class ProbeProxy:
raise RuntimeWarning("Action not installed")
#TODO Check error handling
return self._probe.update(action_address, pickle.dumps(newaction._props),
+ is_editing,
reply_handler=ignore,
error_handler=logError)
- def uninstall(self, action_address):
+ def uninstall(self, action_address, is_editing):
"""
Uninstall an installed action
@param action_address The address of the action to uninstall. This address was given
on action installation
- @param block Force a synchroneous dbus call if True
+ @param is_editing whether this action comes from the editor
"""
if action_address in self._actions:
self._actions.pop(action_address, None)
- self._probe.uninstall(action_address, reply_handler=ignore, error_handler=logError)
+ self._probe.uninstall(action_address, is_editing, reply_handler=ignore, error_handler=logError)
def __update_event(self, event, callback, event_subscribed_cb, address):
LOGGER.debug("ProbeProxy :: Registered event %s with address %s", str(hash(event)), str(address))
@@ -407,7 +475,18 @@ class ProbeProxy:
else:
LOGGER.debug("ProbeProxy :: unsubsribe address %s inconsistency : not registered", address)
+ def create_event(self, addon_name):
+ """
+ Create an event on the app side and request the user to fill the
+ properties before returning it.
+
+ @param addon_name: the add-on name of the event
+ @returns: an eventfilter instance
+ """
+ return pickle.loads(str(self._probe.create_event(addon_name)))
+
def subscribe(self, event, notification_cb, event_subscribed_cb, error_cb):
+
"""
Register an event listener
@param event Event to listen for
@@ -427,7 +506,7 @@ class ProbeProxy:
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):
+ def unsubscribe(self, address):
"""
Unregister an event listener
@param address identifier given by subscribe()
@@ -449,12 +528,13 @@ class ProbeProxy:
subscribed events should be removed.
"""
for action_addr in self._actions.keys():
- self.uninstall(action_addr)
+ # TODO : Make sure there is a way for each action to be properly
+ # uninstalled according to its right edition mode
+ self.uninstall(action_addr, True)
for address in self._subscribedEvents.keys():
self.unsubscribe(address)
-
class ProbeManager(object):
"""
The ProbeManager provides multiplexing across multiple activity ProbeProxies
@@ -464,6 +544,8 @@ class ProbeManager(object):
"""
_LOGGER = logging.getLogger("sugar.tutorius.ProbeManager")
+ default_instance = None
+
def __init__(self, proxy_class=ProbeProxy):
"""Constructor
@param proxy_class Class to use for creating Proxies to activities.
@@ -478,6 +560,8 @@ class ProbeManager(object):
ProbeManager._LOGGER.debug("__init__()")
+ ProbeManager.default_instance = self
+
def setCurrentActivity(self, activity_id):
if not activity_id in self._probes:
raise RuntimeError("Activity not attached, id : %s"%activity_id)
@@ -488,41 +572,64 @@ class ProbeManager(object):
currentActivity = property(fget=getCurrentActivity, fset=setCurrentActivity)
- def install(self, action, action_installed_cb, error_cb):
+ def install(self, action, action_installed_cb, error_cb, is_editing=False, editing_cb=None):
"""
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
+ @param editing_cb The function to execute when propagating changes on
+ this action (only used when is_editing is true)
@return None
"""
if self.currentActivity:
- return self._first_proxy(self.currentActivity).install(action, action_installed_cb, error_cb)
+ return self._first_proxy(self.currentActivity).install(
+ action=action,
+ is_editing=is_editing,
+ action_installed_cb=action_installed_cb,
+ error_cb=error_cb,
+ editing_cb=editing_cb)
else:
raise RuntimeWarning("No activity attached")
- def update(self, action_address, newaction):
+ def update(self, action_address, newaction, is_editing=False):
"""
Update an already installed action's properties and run it again
@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_address, newaction)
+ return self._first_proxy(self.currentActivity).update(action_address, newaction, is_editing)
else:
raise RuntimeWarning("No activity attached")
- def uninstall(self, action_address):
+ 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._first_proxy(self.currentActivity).uninstall(action_address)
+ return self._first_proxy(self.currentActivity).uninstall(action_address, is_editing)
+ else:
+ raise RuntimeWarning("No activity attached")
+
+ def create_event(self, addon_name):
+ """
+ Create an event on the app side and request the user to fill the
+ properties before returning it.
+
+ @param addon_name: the add-on name of the event
+ @returns: an eventfilter instance
+ """
+ if self.currentActivity:
+ return self._first_proxy(self.currentActivity).create_event(addon_name)
else:
raise RuntimeWarning("No activity attached")
@@ -599,8 +706,6 @@ class ProbeManager(object):
return self._probes[process_name]
else:
return []
-
-
def _first_proxy(self, process_name):
"""