# python import import logging, os, re, shutil # ... from functools import partial from gettext import gettext as _ # gtk import import gtk, glib # sugar import from sugar.activity import activity # sugar import from sugar.graphics.toolbutton import ToolButton # atoidejouer import from atoidejouer.tools import config, storage from atoidejouer.ui import screens # get application logger logger = logging.getLogger('atoidejouer') def _clean_dir(dir_path): # little check first if os.path.exists(dir_path): pass # ??? else: return # .. for _filename in os.listdir(dir_path): # .. _path = os.path.join(dir_path, _filename) # little check if os.path.isfile(_path): os.remove(_path) elif os.path.isdir(_path): _clean_dir(_path) else: # ERRROR logger.error('[toolbar] _clean_dir - path error: %s' % dir_path) # remove dir at the end os.removedirs(dir_path) def _cb_seq_new(widget, toolbar): # get screen _screen = toolbar.activity.get_current_screen() # remove items from preview boxes _screen.sequence_preview.clear() # .. _screen.notebook.current_sequence = None # clear entry toolbar._sequence_entry.set_text("") NON_ALPHA_NUM_PATTERN = re.compile('[\W_]+') def _cb_seq_name(entry): # ensure good string _str = NON_ALPHA_NUM_PATTERN.sub('-', entry.get_text()) # update entry entry.set_text(_str) def _cb_seq_remove(widget, toolbar): # get sequence name _name = toolbar._sequence_entry.get_text() # get screen _screen = toolbar.activity.get_current_screen() # type shortcut 'graphic' or 'sound' _type = _screen.notebook._type # little check if _name.strip() == '': # do nothing pass else: # get sequence path _seq_path = storage.get_sequence_path(_type, _name) # remove dir if os.path.exists(_seq_path): # do clean os.remove(_seq_path) # and clear all at the end _screen.sequence_preview.clear() # clear entry toolbar._sequence_entry.set_text("") # update notebook _screen.notebook._get_store_sequence() # update focus _screen.notebook.focus_current_seq() # nothing to do else: pass def _cb_seq_save(widget, toolbar, remove=False): storage.sequence_save(toolbar, remove=remove) # get screen _screen = toolbar.activity.get_current_screen() # get sequence name _name = toolbar._sequence_entry.get_text() # update focus _screen.notebook.focus_current_seq(name=_name) def _show_browser(toolbar, cls): # next screen name _screen_name = '%s_add' % toolbar.name # do switch toolbar._switch(_screen_name) # get or create screen _screen = toolbar.activity.get_screen(_screen_name)\ if toolbar.activity.has_screen(_screen_name)\ else cls(toolbar) # update activity screens toolbar.activity.set_current_screen(_screen_name, _screen) # do show _screen._show() # update entry _seq_name = _screen.notebook.current_sequence if _seq_name is None: pass else: # .. toolbar._sequence_entry.set_text(_seq_name) # pos _current_pos = _screen.sequence_preview.get_current_pos() # .. if toolbar._frame_entry is None: pass else: toolbar._frame_entry.set_text(str(_current_pos)) def _cb_add(widget, toolbar): # browser screen factory if toolbar.name == 'graphics': _show_browser(toolbar, screens.ScreenBrowserGraphics) # .. elif toolbar.name == 'sounds': _show_browser(toolbar, screens.ScreenBrowserSounds) # ?? else: # ERROR logger.error('[toolbar] _cb_add - unknown: %s' % toolbar.name) def _cb_remove(widget, toolbar): # browser screen factory if toolbar.name == 'graphics': pass # .. elif toolbar.name == 'sounds': pass # ?? else: # ERROR logger.error('[toolbar] _cb_remove - name: %s' % toolbar.name) def _cb_frame_after(widget, toolbar): if toolbar._frame_entry is None: pass else: # get previous value _value = int(toolbar._frame_entry.get_text()) # inc it _update_frame_entry(widget, toolbar, _value + 1) # update sequence file _cb_seq_save(widget, toolbar) def _cb_frame_before(widget, toolbar): if toolbar._frame_entry is None: pass else: # get previous value _value = int(toolbar._frame_entry.get_text()) # dec it _update_frame_entry(widget, toolbar, _value - 1) # update sequence file _cb_seq_save(widget, toolbar) def _update_frame_entry(entry, toolbar, value): # get screen _screen = toolbar.activity.get_current_screen() # get max value _max = _screen.sequence_preview.number_of_items() - 1 # prepare value _new_val = None if value > _max: _new_val = _max elif value < 0: _new_val = 0 # reset max just in case else: _new_val = value # update entry toolbar._frame_entry.set_text(str(_new_val)) # update sequence _screen.sequence_preview.move_current(_new_val) def _cb_open(widget, toolbar): pass def _cb_back(widget, toolbar): # do switch toolbar._switch(toolbar.name.replace('_add', '')) # restore screen toolbar.activity._change_screen(toolbar) # get screen now _screen = toolbar.activity.get_current_screen() _screen.scene.refresh() def _cb_import(widget, toolbar): # get the current sequence name _sequence_name = toolbar._sequence_entry.get_text() # get filenames _screen = toolbar.activity.get_current_screen() # shortcut _filenames = _screen.sequence_preview.items # add sequence to the story keys if toolbar.story_keys.add_sequence(_sequence_name, _filenames): # screen name factory _screen_name = toolbar.name.replace('_add', '') # get screen now _screen = toolbar.activity.get_screen(_screen_name) # add sequence to the timeline _screen.timeline.add_sequence(_sequence_name) # already added else: pass def _cb_play(widget, toolbar): # replace play button toolbar._replace_button('play', 'pause') # trigger playing toolbar.activity._thread.play() def _cb_pause(widget, toolbar): # replace pause button toolbar._replace_button('pause', 'play') # trigger pausing toolbar.activity._thread.pause() def _cb_stop(widget, toolbar): # replace pause button - if playing if toolbar._has_button('pause'): # .. toolbar._replace_button('pause', 'play') else: pass # update main thread toolbar.activity._thread.pause(stop=True) # .. toolbar.activity._thread.set_time() def _cb_view_fullscreen(widget, toolbar): # replace fullscreen button with return button toolbar._replace_button('view_fullscreen', 'view_return') # ask_clear toolbar.story_keys.ask_clear() # get current screen _screen = toolbar.activity.get_current_screen() # enbale fullscreen _screen.set_fullscreen(True) def _cb_view_return(widget, toolbar): # remove return button with fullscreen button toolbar._replace_button('view_return', 'view_fullscreen') # ask_clear toolbar.story_keys.ask_clear() # get current screen _screen = toolbar.activity.get_current_screen() # disable fullscreen _screen.set_fullscreen(False) def _cb_slider(widget, event, toolbar): """action = 'press' or 'release' """ # ... if event.type == gtk.gdk.BUTTON_PRESS: pass elif event.type == gtk.gdk.BUTTON_RELEASE: toolbar.activity._thread.set_time(time_=widget.get_value()) # ?? else: pass def _cb_format_value(widget, value, toolbar): """Format the slider value to display """ # return formated value return '%1d:%02d' % divmod(value, 60) TOOLBAR_INDEXES = ['activity', 'story', 'graphics', 'sounds', 'help'] def _cb_help_back(widget, toolbar): _previous = toolbar.activity._previous # restore default tab toolbar.activity._toolbox.set_current_toolbar( TOOLBAR_INDEXES.index(_previous.replace('_add', ''))) # restore previous toolbar.activity._change_screen(name=_previous) BUTTONS = { 'add' : ['list-add', _cb_add], 'back' : ['edit-undo', _cb_back], 'backward' : ['media-seek-backward', None], 'forward' : ['media-seek-forward', None], 'frame_after' : ['go-right', _cb_frame_after], 'frame_before' : ['go-left', _cb_frame_before], 'frame_entry' : [None, None], 'help_back' : ['edit-undo', _cb_help_back], 'import' : ['insert-image', _cb_import], 'open' : ['media', _cb_open], 'pause' : ['media-playback-pause', _cb_pause], 'play' : ['media-playback-start', _cb_play], 'remove' : ['list-remove', _cb_remove], 'separator' : [None, None], 'seq_new' : ['document-generic', _cb_seq_new], 'seq_name' : [None, _cb_seq_name], 'seq_remove' : ['button_cancel', _cb_seq_remove], 'seq_save' : ['dialog-apply', _cb_seq_save], 'slider' : [None, _cb_slider], 'stop' : ['media-playback-stop', _cb_stop], 'view_fullscreen' : ['view-fullscreen', _cb_view_fullscreen], 'view_return' : ['view-return', _cb_view_return], } TOOLBARS = { 'graphics' : [ ['stop', 'play', 'slider', # 'backward', 'forward' 'separator', 'add'], [] ], 'graphics_add' : [ ['seq_new', 'seq_name', 'seq_save', 'seq_remove', # 'separator', # 'add', 'remove', # ''separator', # 'frame_before', 'frame_entry', 'frame_after' ], ['import', 'back'] ], 'sounds' : [ ['stop', 'play', 'slider', # 'backward', 'forward' 'separator', 'add'], [] ], 'sounds_add' : [ ['seq_new', 'seq_name', 'seq_save', 'seq_remove', # 'separator', # 'add', 'remove', # ''separator', # 'frame_before', 'frame_entry', 'frame_after' ], ['import', 'back'] ], 'story' : [ ['stop', 'play', 'slider', # 'backward', 'forward' 'separator', 'view_fullscreen'], [] ], 'help' : [ [], ['help_back'] ] } TITLES = { 'graphics' : { 'toolbox': _('Graphic'), 'buttons': { # 'backward': _('Seek Backward'), # 'forward': _('Seek Forward'), 'pause': _('Pause Story'), 'play': _('Play Story'), 'slider': _('Progress Bar'), 'stop': _('Stop Story'), 'add': _('Add Graphic'), } }, 'graphics_add' : { 'toolbox': None, 'buttons': { 'add': _('Add Graphic'), 'back': _('Back'), 'frame_after': _('Frame Before'), 'frame_before': _('Frame After'), 'frame_entry': None, 'import': _('Import Sequence'), 'remove': _('Remove Graphic'), 'seq_new': _('New Sequence'), 'seq_name': None, 'seq_remove': _('Remove Sequence'), 'seq_save': _('Save Sequence'), } }, 'sounds' : { 'toolbox': _('Sound'), 'buttons': { # 'backward': _('Seek Backward'), # 'forward': _('Seek Forward'), 'pause': _('Pause Story'), 'play': _('Play Story'), 'slider': _('Progress Bar'), 'stop': _('Stop Story'), 'add': _('Add Sound'), } }, 'sounds_add' : { 'toolbox': None, 'buttons': { 'add': _('Add Sound'), 'back': _('Back'), 'frame_after': _('Frame Before'), 'frame_before': _('Frame After'), 'frame_entry': None, 'import': _('Import Sequence'), 'remove': _('Remove Sound'), 'seq_new': _('New Sound'), 'seq_name': None, 'seq_remove': _('Remove Sequence'), 'seq_save': _('Save Sequence'), } }, 'story' : { 'toolbox': _('Story'), 'buttons': { # 'open': _('Open Story'), # 'backward': _('Seek Backward'), # 'forward': _('Seek Forward'), 'pause': _('Pause Story'), 'play': _('Play Story'), 'slider': _('Progress Bar'), 'stop': _('Stop Story'), 'view_fullscreen': _('Fullscreen'), 'view_return': _('Default Screen'), } }, 'help' : { 'toolbox': _('Help'), 'buttons': { 'help_back': _('Back') } } } class Toolbar(gtk.Toolbar): def __init__(self, activity, name='player'): # init parent gtk.Toolbar.__init__(self) # keep the name self.set_name(name) # keep activity self.activity = activity # .. if self.name == 'graphics'\ or self.name == 'story': self.story_keys = self.activity.graphic_keys else: self.story_keys = self.activity.sound_keys # adjustment self._adjustment = None self._number_of_keys = self.activity._number_of_keys # keep components self._sequence_entry = None self._frame_entry = None # init widget dict self._button_dict = dict() # init buttons self._init_buttons() # add tab in toolbox _toolbox_name = TITLES[self.name]['toolbox'] if _toolbox_name is None: pass else: _toolbox = self.activity.get_toolbox() _toolbox.add_toolbar(_toolbox_name, self) # connect focus event self.connect('focus', self._on_focus) # show self.show() def _switch(self, name): # update toolbar self._clear_buttons() # switch name self.set_name(name) # reset self._init_buttons() def _clear_buttons(self): # remove all for _k in self._button_dict.keys(): self._remove_button(_k) # remove separators for _c in self.get_children(): # remove it self.remove(_c) # and destroy it _c.destroy() def _init_buttons(self): # add buttons _b_left, _b_right = TOOLBARS[self.name] # place left buttons for _b in _b_left: # add button self._add_button(_b) # add expanded separator _separator = gtk.SeparatorToolItem() _separator.set_draw(False) _separator.set_expand(True) _separator.show() self.add(_separator) # place right buttons for _b in _b_right: # add button self._add_button(_b) def update_slider(self, time_, pause): # get slider _s = self.get_slider() # slider stuff if _s is None: pass else: _s.set_value(time_) # update pause status if pause is True: self._replace_button('pause', 'play') else: self._replace_button('play', 'pause') def get_slider(self): # little check if 'slider' in self._button_dict: _children = self._button_dict['slider'].get_children() return None if len(_children) == 0 else _children[0] else: return None def play(self): # do pause _cb_play(None, self) def pause(self): # do pause _cb_pause(None, self) def refresh(self, value): # ... if self._number_of_keys != self.activity._number_of_keys: # update nb of keys self._number_of_keys = self.activity._number_of_keys # update adjustment if hasattr(self._adjustment, 'set_upper'): self._adjustment.set_upper(self._number_of_keys-1) else: self._adjustment.upper = self._number_of_keys-1 else: pass # get slider _s = self.get_slider() # slider stuff if _s is None: # just in case value = 0 else: # update value _s.set_value(int(value)) # return _v to keep time value in thread return value def _on_focus(self, widget, direction): if self.name in ['graphics_add', 'sounds_add']: self._switch(self.name.replace('_add', '')) else: # update current screen self.activity._change_screen(self) if 'add' in self._button_dict: # enable or disble add _mode = config.Config().get('activity>mode') _conf = config.Config().get('mode>%s' % _mode, type_=list) # .. self._button_dict['add'].set_sensitive('remove' in _conf) else: pass def _has_button(self, button_id): return button_id in self._button_dict def _add_button(self, button_id, index=None): # get button icon and cb _icon, _cb = BUTTONS[button_id] # manage separator if button_id == 'separator': _buton = gtk.SeparatorToolItem() _buton.set_draw(True) # manage slider elif button_id == 'slider': # self._adjustment = gtk.Adjustment(0, 0, self._number_of_keys-1, 1) # .. _hscale = gtk.HScale(self._adjustment) _hscale.set_draw_value(True) _hscale.set_digits(False) _hscale.set_update_policy(gtk.UPDATE_CONTINUOUS) # manage cb _hscale.connect('button-release-event', _cb, self) _hscale.connect('format-value', _cb_format_value, self) # show _hscale.show() # .. _buton = gtk.ToolItem() _buton.set_expand(True) _buton.add(_hscale) elif button_id == 'seq_name': self._sequence_entry = gtk.Entry() # show self._sequence_entry.show() # .. self._sequence_entry.connect('changed', _cb) # .. _buton = gtk.ToolItem() _buton.set_expand(True) _buton.add(self._sequence_entry) elif button_id == 'frame_entry': # ... self._frame_entry = gtk.Entry() # .. self._frame_entry.set_editable(False) self._frame_entry.set_width_chars(2) self._frame_entry.set_size_request(44, -1) # set value self._frame_entry.set_text('0') # center text self._frame_entry.set_alignment(1) # show self._frame_entry.show() # .. _buton = gtk.ToolItem() _buton.add(self._frame_entry) # standard button elif button_id in BUTTONS: # get tooltip _tooltip = TITLES[self.name]['buttons'][button_id] # set icon _buton = ToolButton(_icon) # set tooltip _buton.set_tooltip(_tooltip) # do connect if _cb is None: pass else: _buton.connect('clicked', _cb, self) # ?? else: # ERROR logger.error('[toolbar] _add_button - ??: %s' % button_id) return # update the button dict self._button_dict[button_id] = _buton # add to the toolbar if index is None: self.add(_buton) else: self.insert(_buton, index) # show it _buton.show() def _remove_button(self, button_id): # little check if button_id in self._button_dict: # get button _buton = self._button_dict.pop(button_id) # do remove - do it safe glib.idle_add(partial(self.remove, _buton)) # and destroy - safe glib.idle_add(_buton.destroy) # ?? else: # ERROR logger.error('[toolbar] _remove_button - unknown: %s' % button_id) def _replace_button(self, button_id_out, button_id_in): # little check if button_id_out in self._button_dict: # ... _index = self.get_item_index(self._button_dict[button_id_out]) # do remove self._remove_button(button_id_out) # do it safe glib.idle_add(partial(self._add_button, button_id_in, _index)) # ?? else: pass