diff options
-rwxr-xr-x | src/extensions/tutoriusremote.py | 80 | ||||
-rw-r--r-- | tutorius/TProbe.py | 3 | ||||
-rw-r--r-- | tutorius/properties.py | 19 |
3 files changed, 92 insertions, 10 deletions
diff --git a/src/extensions/tutoriusremote.py b/src/extensions/tutoriusremote.py index 9bb4bfb..dfe6f37 100755 --- a/src/extensions/tutoriusremote.py +++ b/src/extensions/tutoriusremote.py @@ -21,20 +21,29 @@ creator from the Sugar frame. """ import gtk + from gettext import gettext as _ import gconf import dbus +import logging + from sugar.graphics.tray import TrayIcon from sugar.graphics.palette import Palette from sugar.graphics.xocolor import XoColor +from sugar.graphics.combobox import ComboBox from jarabe.frame.frameinvoker import FrameWidgetInvoker +from jarabe.model.shell import get_model from sugar.tutorius.creator import default_creator +from sugar.tutorius.vault import Vault + _ICON_NAME = 'tutortool' +LOGGER = logging.getLogger('remote') + class TutoriusRemote(TrayIcon): FRAME_POSITION_RELATIVE = 102 @@ -61,14 +70,81 @@ class TPalette(Palette): self._creator_item = gtk.MenuItem(_('Create a tutorial')) self._creator_item.connect('activate', self._start_creator) self._creator_item.show() + + self._stop_creator_item = gtk.MenuItem(_('Stop creating tutorial')) + self._stop_creator_item.connect('activate', self._stop_creator) + + self._tut_list_item = gtk.MenuItem(_('Show tutorials')) + self._tut_list_item.connect('activate', self._list_tutorials) + self._tut_list_item.show() + self.menu.append(self._creator_item) + self.menu.append(self._stop_creator_item) + self.menu.append(self._tut_list_item) self.set_content(None) def _start_creator(self, widget): - default_creator().start_authoring(tutorial=None) - + creator = default_creator() + + if creator.is_authoring == False: + # Replace the start creator button by the stop creator + # Allocate a white color for the text + self._creator_item.hide() + self._stop_creator_item.show() + creator.start_authoring(tutorial=None) + + def _stop_creator(self, widget): + # Close the creator but let the confirmation dialog appear + # if the user hasn't saved his tutorial + creator = default_creator() + + if creator.is_authoring == False: + return + + creator._cleanup_cb() + + # If the creator was not actually closed + if creator.is_authoring == True: + return + # Switch back to start creator entry + self._stop_creator_item.hide() + self._creator_item.show() + def _list_tutorials(self, widget): + dlg = gtk.Dialog('Run a tutorial', + None, + gtk.DIALOG_MODAL, + (gtk.STOCK_OK, gtk.RESPONSE_ACCEPT, + gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT)) + dlg.vbox.pack_start(gtk.Label(_('Which tutorial do you want to run?\n'))) + + activity = get_model().get_active_activity() + + act_name = activity.get_activity_name() + tutorial_dict = Vault.list_available_tutorials(act_name) + + # Build the combo box + combo = ComboBox() + for (tuto_name, tuto_guid) in tutorial_dict.items(): + combo.append_item(tuto_name, tuto_guid) + dlg.vbox.pack_end(combo) + dlg.show_all() + + result = dlg.run() + dlg.destroy() + + if result == gtk.RESPONSE_ACCEPT: + row = combo.get_active_item() + if row: + guid = row[0] + name = row[1] + LOGGER.debug("TPalette :: Got message to launch tutorial %s with guid %s"%(str(name), str(guid))) + + from sugar.tutorius.service import ServiceProxy + service = ServiceProxy() + + service.launch(guid) def setup(tray): tray.add_device(TutoriusRemote(default_creator())) diff --git a/tutorius/TProbe.py b/tutorius/TProbe.py index 5b5cf8d..7021f80 100644 --- a/tutorius/TProbe.py +++ b/tutorius/TProbe.py @@ -25,9 +25,10 @@ import cPickle as pickle from . import addon +from . import properties from .services import ObjectStore -from .dbustools import save_args, ignore, logError +from .dbustools import remote_call, save_args import copy """ diff --git a/tutorius/properties.py b/tutorius/properties.py index a462782..cc76748 100644 --- a/tutorius/properties.py +++ b/tutorius/properties.py @@ -19,6 +19,7 @@ TutoriusProperties have the same behaviour as python properties (assuming you also use the TPropContainer), with the added benefit of having builtin dialog prompts and constraint validation. """ +import uuid from copy import copy, deepcopy from .constraints import Constraint, \ @@ -60,6 +61,8 @@ class TPropContainer(object): self._props[attr_name] = propinstance.validate( copy(propinstance.default)) + self.__id = hash(uuid.uuid4()) + def __getattribute__(self, name): """ Process the 'fake' read of properties in the appropriate instance @@ -128,21 +131,23 @@ class TPropContainer(object): # Providing the hash methods necessary to use TPropContainers # in a dictionary, according to their properties def __hash__(self): - #Return a hash of properties (key, value) sorted by key - #We need to transform the list of property key, value lists into - # a tuple of key, value tuples - return hash(tuple(map(tuple,sorted(self._props.items(), cmp=lambda x, y: cmp(x[0], y[0]))))) + # many places we use containers as keys to store additional data. + # Since containers are mutable, there is a need for a hash function + # where the result is constant, so we can still lookup old instances. + return self.__id def __eq__(self, e2): - return isinstance(e2, type(self)) and self._props == e2._props + return self.__id == e2.__id or \ + (isinstance(e2, type(self)) and self._props == e2._props) # Adding methods for pickling and unpickling an object with # properties def __getstate__(self): - return self._props.copy() + return dict(id=self.__id, props=self._props.copy()) def __setstate__(self, dict): - self._props.update(dict) + self.__id = dict['id'] + self._props.update(dict['props']) class TutoriusProperty(object): """ |