# python import import json, logging, os, threading, time # ... from functools import partial # .. from gettext import gettext as _ # gtk import import gtk, glib # ... gtk.gdk.threads_init() # sugar import from sugar.activity import activity # atoidejouer import from atoidejouer.ui import screens, toolbar # .. from atoidejouer.tools import config, storage # .. from atoidejouer.story.keys import StoryKeys # get application logger logger = logging.getLogger('atoidejouer') logger.setLevel(logging.DEBUG) class ThreadAnim(threading.Thread): def __init__(self, activity_): # init parent threading.Thread.__init__(self) # main flag self._die = False self._pause = True # main vars self._activity = activity_ self._time = 0 # start right now self.start() def pause(self, stop=False): self._pause = True # reset time on stop if stop is True: self._time = 0 else: self.set_time() def play(self): self._pause = False def kill(self): self._die = True def set_time(self, time_=None, rate=0, pause=None): # ensure time time_ = self._time if time_ is None else time_ # update time self._time = time_ + rate # set pause self._pause = self._pause if pause is None else pause # ... _current_screen = self._activity.get_current_screen() # ??? if _current_screen is None: # ERROR logger.error('[activity] set_time - scene not found!') # do pause on toolbar elif pause is True: if hasattr(_current_screen, 'toolbar'): _current_screen.toolbar.pause() else: pass else: # update scene if hasattr(_current_screen, 'scene'): _current_screen.scene.refresh() elif hasattr(_current_screen, 'refresh'): _current_screen.refresh() else: pass # update timeline if hasattr(_current_screen, 'timeline'): _current_screen.timeline.refresh() else: pass # update panel if hasattr(_current_screen, 'panel'): _current_screen.panel.refresh() else: pass # update slider if hasattr(_current_screen, 'toolbar'): _current_screen.toolbar.refresh(self._time) else: pass def run(self): # ... while self._die is False: # get current rate _rate = config.Config().get_rate_value() # ... time.sleep(_rate) # do pause if (self._time + 1) >= self._activity._number_of_keys\ and self._pause is False: # just in case self._time = self._activity._number_of_keys - 1 # ... self.set_time(pause=True) # .. continue # .. do nothing elif self._pause is True: continue # .. do something else: # ... self.set_time(rate=_rate) def _toolbar_changed(toolbox, page, activity_): """Catch toolbox activity tab focus to display settings screen. """ # is the activity tab? if page == 0: # remove first if exist activity_.remove_screen('activity') # show the activity screen activity_._change_screen(toolbar=None, name='activity') else: pass # propagate it return True class AToiDeJouerActivity(activity.Activity): def __init__(self, handle): # init parent activity.Activity.__init__(self, handle) # init activity working folder storage.init_activity_folder() # .. self.max_participants = 1 # get toolbox self._toolbox = activity.ActivityToolbox(self) # add tool bars self.set_toolbox(self._toolbox) # keep thread & screen self._thread = None self._screens = dict() self._current = None self._previous = None self._handler_id = None self._number_of_keys = 1 # .. self.__splash = None # sequence dict and list self.graphic_keys = StoryKeys('graphics', self) self.sound_keys = StoryKeys('sounds', self) # show self._toolbox.show() # tmp var _toolbar = None self.__story_toolbar = None # init toolbars for _n in ['story', 'graphics', 'graphics_add', 'sounds', 'sounds_add', 'help']: # init toolbar _t = toolbar.Toolbar(self, name=_n) # if default toolbar .. set default screen if _n == 'story': self.__story_toolbar = _t elif _n == 'graphics': self._change_screen(_t) _toolbar = _t # set default tab self._toolbox.set_current_toolbar(2) # .. self._toolbox.connect('current-toolbar-changed', _toolbar_changed, self) # do anim self._thread = ThreadAnim(self) def get_toolbox(self): return self._toolbox def update_number_of_keys(self): # set max _graphic_max = self.graphic_keys.get_max_frame() _sound_max = self.sound_keys.get_max_frame() _max = _graphic_max if _graphic_max > _sound_max else _sound_max # update value self._number_of_keys = _max + 1 def get_current_screen(self): # little check if self._current in self._screens: return self._screens[self._current] else: return None def set_current_screen(self, name, screen): # udpate current name self._previous = self._current self._current = name # little check self.add_screen(name, screen) def _update_slider(self, toolbar): # sync time if self._thread is None: pass else: toolbar.update_slider(self._thread._time, self._thread._pause) def add_screen(self, name, screen): if name in self._screens: pass else: self._screens[name] = screen def remove_screen(self, name): if name in self._screens: self._screens[name].destroy() del self._screens[name] else: pass def has_screen(self, name): return name in self._screens def get_screen(self, name): if name in self._screens: return self._screens[name] else: return None def _change_screen(self, toolbar=None, name=None): # little check if toolbar is None and name is None: return else: # update current screen name self._previous = self._current self._current = toolbar.name if name is None else name # already exist if self._current in ['graphics', 'sounds']: if self.__splash is None: self.__splash = screens.Splash(toolbar) else: self.__splash._show() # ... glib.idle_add(partial(self.__idle_change, toolbar)) # .. default else: self.__idle_change(toolbar) def __idle_change(self, toolbar): # already exist if self._current in self._screens: # show self._screens[self._current]._show() if toolbar is None: pass else: # do pause toolbar.pause() # update all self._thread.set_time() if self._current == 'graphics'\ or self._current == 'sounds': # .. refresh self._screens[self._current].timeline.refresh_sequence() self._screens[self._current].timeline.refresh_adjustment() elif self._current == 'help': del self._screens[self._current] self._screens[self._current] = screens.ScreenHelp(self) else: pass # exit return # .. elif self._current == 'activity': _scr = screens.ScreenActivity(self) # update screens dict self._screens[self._current] = _scr # .. return # screen factory elif self._current == 'graphics': _scr = screens.ScreenEditGraphics(toolbar) # .. init sequences for _n in self.graphic_keys._names: _scr.timeline.add_sequence(_n) # .. refresh _scr.timeline.refresh_sequence() _scr.timeline.refresh_adjustment() elif self._current == 'sounds': _scr = screens.ScreenEditSounds(toolbar) # .. init sequences for _n in self.sound_keys._names: _scr.timeline.add_sequence(_n) # .. refresh _scr.timeline.refresh_sequence() _scr.timeline.refresh_adjustment() elif self._current == 'story': _scr = screens.ScreenStory(toolbar, set_canvas=True) elif self._current == 'help': _scr = screens.ScreenHelp(self) else: # ?? return # update screens dict self._screens[self._current] = _scr # update slider self._update_slider(toolbar) def read_file(self, file_path): """Read saved data from datastore and resume activity based on a previous state. """ # init content _data = None # read file _file = open(file_path, 'r') try: _data = _file.read() finally: _file.close() # parse json data self.graphic_keys.loads(_data) self.sound_keys.loads(_data) # set activity new number of keys self.update_number_of_keys() # clear self.graphic_keys.ask_clear() # switch to edit mode if no key self._toolbox.set_current_toolbar(1) self._change_screen(toolbar=self.__story_toolbar) def write_file(self, file_path): """Dummy overiding ... """ # content dict _data_dict = { 'graphic_names': self.graphic_keys._names, 'graphic_keys': self.graphic_keys._keys, 'sound_names': self.sound_keys._names, 'sound_keys': self.sound_keys._keys, } # prepare content _data = json.dumps(_data_dict) # save content _f = open(file_path, 'wb') try: _f.write(_data) finally: _f.close() def close(self, skip_save=False): # stop the thread self._thread.kill() # sound preview _screen = self.get_screen('sounds_add') if _screen is None: pass elif _screen.item_preview._thread is None: pass else: _screen.item_preview._thread.kill() # .. activity.Activity.close(self, skip_save=True)