Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/tutorius
diff options
context:
space:
mode:
Diffstat (limited to 'tutorius')
-rw-r--r--tutorius/TProbe.py78
-rw-r--r--tutorius/actions.py6
-rw-r--r--tutorius/engine.py11
-rw-r--r--tutorius/filters.py6
-rw-r--r--tutorius/properties.py18
5 files changed, 88 insertions, 31 deletions
diff --git a/tutorius/TProbe.py b/tutorius/TProbe.py
index 2834f0c..7f4126e 100644
--- a/tutorius/TProbe.py
+++ b/tutorius/TProbe.py
@@ -46,6 +46,10 @@ import copy
-------------------- ----------
"""
+
+#Prefix separator for action/event addresses
+PSEP=":"
+
#TODO Add stub error handling for remote calls in the classes so that it will
# be clearer how errors can be handled in the future.
@@ -94,7 +98,7 @@ class TProbe(dbus.service.Object):
self._installedActions = {}
self._subscribedEvents = {}
- LOGGER.debug("TProbe :: registering '%s' with unique_id '%s'", self._activity_name, activity.get_id())
+ LOGGER.debug("TProbe :: registering '%s' with unique_id '%s'", self._activity_name, self._unique_id)
self._service_proxy.register_probe(self._activity_name, self._unique_id)
def start(self):
@@ -324,6 +328,7 @@ class ProbeProxy:
bus = dbus.SessionBus()
self._object = bus.get_object(activityName, "/tutorius/Probe/"+str(unique_id))
self._probe = dbus.Interface(self._object, "org.tutorius.ProbeInterface")
+ self.prefix = str(unique_id)+PSEP
self._actions = {}
self._edition_callbacks = {}
@@ -375,7 +380,7 @@ class ProbeProxy:
if editing_cb:
self._edition_callbacks[address] = editing_cb
# Propagate the action installed callback upwards in the stack
- callback(address)
+ callback(self.prefix + address)
def __clear_action(self, address):
# Remove the action installed at this address
@@ -458,7 +463,7 @@ class ProbeProxy:
# our dictionary (python pass arguments by reference)
self._subscribedEvents[address] = copy.copy(event)
- event_subscribed_cb(address)
+ event_subscribed_cb(self.prefix + address)
return address
def __clear_event(self, address):
@@ -574,6 +579,12 @@ class ProbeManager(object):
currentActivity = property(fget=getCurrentActivity, fset=setCurrentActivity)
+ def get_source_activity(self, propc):
+ if hasattr(propc, "source"):
+ return propc.source
+ else:
+ return None
+
def install(self, action, action_installed_cb, error_cb, is_editing=False, editing_cb=None):
"""
Install an action on the current activity
@@ -586,8 +597,13 @@ class ProbeManager(object):
this action (only used when is_editing is true)
@return None
"""
- if self.currentActivity:
- return self._first_proxy(self.currentActivity).install(
+ activity = self.get_source_activity(action)
+ #Allow the creator to look for the current activity
+ if activity is None and is_editing:
+ activity = self.currentActivity
+
+ if activity:
+ return self._first_proxy(activity).install(
action=action,
is_editing=is_editing,
action_installed_cb=action_installed_cb,
@@ -605,8 +621,15 @@ class ProbeManager(object):
@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, is_editing)
+ probe_id, sep, address = action_address.rpartition(PSEP)
+ if probe_id:
+ probe = self._get_proxy_by_unique_id(probe_id)
+ if probe is None:
+ #TODO What happens if the Probe is gone??
+ raise RuntimeWarning("ProbeProxy containing action address is gone")
+ else:
+ return probe.update(address, newaction, is_editing)
+
else:
raise RuntimeWarning("No activity attached")
@@ -617,8 +640,16 @@ class ProbeManager(object):
@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, is_editing)
+ probe_id, sep, address = action_address.rpartition(PSEP)
+ if probe_id:
+ probe = self._get_proxy_by_unique_id(probe_id)
+ if probe is None:
+ logging.warning(
+ "ProbeProxy for address %s is gone, assuming uninstall not necessary" % \
+ action_address)
+ else:
+ return probe.uninstall(address, is_editing)
+
else:
raise RuntimeWarning("No activity attached")
@@ -646,8 +677,10 @@ class ProbeManager(object):
installation
@return address identifier used for unsubscribing
"""
- if self.currentActivity:
- return self._first_proxy(self.currentActivity).subscribe(event, notification_cb,\
+ activity = self.get_source_activity(event)
+
+ if activity:
+ return self._first_proxy(activity).subscribe(event, notification_cb,\
event_subscribed_cb, error_cb)
else:
raise RuntimeWarning("No activity attached")
@@ -658,8 +691,15 @@ class ProbeManager(object):
@param address identifier given by subscribe()
@return None
"""
- if self.currentActivity:
- return self._first_proxy(self.currentActivity).unsubscribe(address)
+ probe_id, sep, address = address.rpartition(PSEP)
+ if probe_id:
+ probe = self._get_proxy_by_unique_id(probe_id)
+ if probe is None:
+ logging.warning(
+ "ProbeProxy for address %s is gone, assuming unsubscribe not necessary" % \
+ address)
+ else:
+ return probe.unsubscribe(address)
else:
raise RuntimeWarning("No activity attached")
@@ -720,4 +760,14 @@ class ProbeManager(object):
else:
raise RuntimeWarning("No activity attached under '%s'", process_name)
-
+ def _get_proxy_by_unique_id(self, unique_id):
+ """
+ Get a probe proxy by it's unique id.
+ @param unique_id The unique id of the probe
+ @return the probe proxy or None if not found
+ """
+ for probes in self._probes.values():
+ for id, probe in probes:
+ if id == unique_id:
+ return probe
+ return None
diff --git a/tutorius/actions.py b/tutorius/actions.py
index cf586f2..6d1f58e 100644
--- a/tutorius/actions.py
+++ b/tutorius/actions.py
@@ -165,9 +165,9 @@ class DragWrapper(object):
class Action(TPropContainer):
"""Base class for Actions"""
- def __init__(self):
- TPropContainer.__init__(self)
- self.position = (0,0)
+ source = TStringProperty(None, null=True)
+ def __init__(self, **kwargs):
+ super(Action, self).__init__(**kwargs)
self._drag = None
# The callback that will be triggered when the action is requested
# to notify all its changes
diff --git a/tutorius/engine.py b/tutorius/engine.py
index 198fa11..c0769b5 100644
--- a/tutorius/engine.py
+++ b/tutorius/engine.py
@@ -77,14 +77,9 @@ class TutorialRunner(object):
#Temp FIX until event/actions have an activity id
self._activity_id = None
- #Temp FIX until event, actions have an activity id
- def setCurrentActivity(self):
- self._pM.currentActivity = self._activity_id
-
###########################################################################
# Incoming messages
def start(self):
- self.setCurrentActivity() #Temp Hack until activity in events/actions
self.enterState(self._tutorial.INIT)
def stop(self):
@@ -141,6 +136,8 @@ class TutorialRunner(object):
# Send all the event registration
for (event_name, (event, next_state)) in transitions.items():
+ if hasattr(event, "source") and not event.source:
+ event.source = self._activity_id
self._pM.subscribe(event,
save_args(self._handleEvent, next_state),
save_args(self.event_subscribed, event_name),
@@ -153,7 +150,6 @@ class TutorialRunner(object):
###########################################################################
# Helper functions
def _execute_stop(self):
- self.setCurrentActivity() #Temp Hack until activity in events/actions
self._teardownState()
self._state = None
self._runner_state = RUNNER_STATE_IDLE
@@ -253,6 +249,8 @@ class TutorialRunner(object):
for (action_name, action) in actions.items():
LOGGER.debug("TutorialRunner :: Installed action %s"%(action_name))
+ if hasattr(action, "source") and not action.source:
+ action.source = self._activity_id
self._pM.install(action,
save_args(self.action_installed, action_name),
save_args(self.install_error, action_name))
@@ -269,7 +267,6 @@ class TutorialRunner(object):
@param state_name The name of the state to enter in
"""
- self.setCurrentActivity() #Temp Hack until activity in events/actions
# Set the runner state to actions setup
self._runner_state = RUNNER_STATE_SETUP_ACTIONS
diff --git a/tutorius/filters.py b/tutorius/filters.py
index 38cf86b..6ef8867 100644
--- a/tutorius/filters.py
+++ b/tutorius/filters.py
@@ -25,12 +25,12 @@ class EventFilter(properties.TPropContainer):
"""
Base class for an event filter
"""
-
- def __init__(self):
+ source = properties.TStringProperty(None, null=True)
+ def __init__(self, **kwargs):
"""
Constructor.
"""
- super(EventFilter, self).__init__()
+ super(EventFilter, self).__init__(**kwargs)
self._callback = None
def install_handlers(self, callback, **kwargs):
diff --git a/tutorius/properties.py b/tutorius/properties.py
index bfdb32c..a0d63bb 100644
--- a/tutorius/properties.py
+++ b/tutorius/properties.py
@@ -49,12 +49,14 @@ class TPropContainer(object):
at the cost of needing a mapping between container instances, and
property values. This is what TPropContainer does.
"""
- def __init__(self):
+ def __init__(self, **kwargs):
"""
Prepares the instance for property value storage. This is done at
object initialization, thus allowing initial mapping of properties
declared on the class. Properties won't work correctly without
this call.
+
+ Keyword arguments will be evaluated as properties
"""
# create property value storage
object.__setattr__(self, "_props", {})
@@ -74,6 +76,10 @@ class TPropContainer(object):
# to the creator to update its action edition dialog.
self._diff_dict = {}
+ #Set attribute values that were supplied
+ for key, value in kwargs.items():
+ setattr(self, key, value)
+
def __getattribute__(self, name):
"""
Process the 'fake' read of properties in the appropriate instance
@@ -254,11 +260,15 @@ class TStringProperty(TutoriusProperty):
Represents a string. Can have a maximum size limit.
"""
widget_class = StringPropWidget
- def __init__(self, value, size_limit=None):
+ def __init__(self, value, size_limit=None, null=False):
TutoriusProperty.__init__(self)
self.type = "string"
- self.size_limit = MaxSizeConstraint(size_limit)
- self.string_type = StringTypeConstraint()
+ if size_limit:
+ self.size_limit = MaxSizeConstraint(size_limit)
+ if null:
+ self.string_type = TypeConstraint((str, type(None)))
+ else:
+ self.string_type = StringTypeConstraint()
self.default = self.validate(value)