Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/tutorius/engine.py
blob: b0a49a854ed6b92d6b31456c35a2484ee45f4b21 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
import logging
import dbus.mainloop.glib
from jarabe.model import shell
from sugar.bundle.activitybundle import ActivityBundle

from .vault import Vault
from .TProbe import ProbeManager
from .dbustools import save_args


class TutorialRunner(object):
    """
    Driver for the execution of one tutorial
    """
    def __init__(self, tutorial, probeManager):
        """Constructor
        @param tutorial Tutorial to execute
        @param probeManager probeManager to use
        """
        self._tutorial = tutorial
        self._pM = probeManager

        #State
        self._state = None
        self._sEvents = set() #Subscribed Events

        #Cached objects
        self._actions = {}

        #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

    def start(self):
        self.setCurrentActivity() #Temp Hack until activity in events/actions
        self.setState(self._tutorial.INIT)

    def stop(self):
        self.setCurrentActivity() #Temp Hack until activity in events/actions
        self.setState(self._tutorial.END)
        self._teardownState()
        self._state = None

    def _handleEvent(self, next_state, event):
        #FIXME sanity check
        self.setState(next_state)

    def _teardownState(self):
        if self._state is None:
            #No state, no teardown
            return

        #Clear the current actions
        for action in self._actions.values():
            self._pM.uninstall(action)
        self._actions = {}

        #Clear the EventFilters
        for event in self._sEvents:
            self._pM.unsubscribe(event)
        self._sEvents.clear()

    def _setupState(self):
        if self._state is None:
            raise RuntimeError("Attempting to setupState without a state")

        self._actions = self._tutorial.get_action_dict(self._state)
        transitions = self._tutorial.get_transition_dict(self._state)
        for (event, next_state) in transitions.values():
            self._sEvents.add(self._pM.subscribe(event, save_args(self._handleEvent, next_state)))
        for action in self._actions.values():
            self._pM.install(action)

    def setState(self, state_name):
        self.setCurrentActivity() #Temp Hack until activity in events/actions
        if state_name == self._state:
            #Nothing to do
            return

        self._teardownState()
        self._state = state_name
        self._setupState()


class Engine:
    """
    Driver for the execution of tutorials
    """

    def __init__(self, probeManager=None):
        """Constructor
        @param probeManager (optional) ProbeManager instance to use
        """
        dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
        #FIXME shell.get_model() will only be useful in the shell process
        self._shell = shell.get_model()
        self._probeManager = probeManager or ProbeManager()
        self._tutorial = None

    def launch(self, tutorialID):
	""" Launch a tutorial 
            @param tutorialID unique tutorial identifier used to retrieve it from the disk
        """
        if self._tutorial:
            self.stop()

        self._tutorial = TutorialRunner(Vault.loadTutorial(tutorialID), self._probeManager)

        #Get the active activity from the shell
        activity = self._shell.get_active_activity()
        #TProbes automatically use the bundle id, available from the ActivityBundle
        bundle = ActivityBundle(activity.get_bundle_path())

        self._tutorial._activity_id = bundle.get_bundle_id() #HACK until we have activity id's in action/events

        self._tutorial.start()

    def stop(self, tutorialID=None):
        """ Stop the current tutorial
        """
        if tutorialID is None:
            logging.warning(
                "stop() without a tutorialID will become deprecated")
        self._tutorial.stop()
        self._tutorial = None

    def pause(self, tutorialID=None):
        """ Interrupt the current tutorial and save its state in the journal
        """
        if tutorialID is None:
            logging.warning( \
                "pause() without a tutorialID will become deprecated")
        raise NotImplementedError("Unable to store tutorial state")