diff options
Diffstat (limited to 'atoidejouerbeta/ui/preview.py')
-rw-r--r-- | atoidejouerbeta/ui/preview.py | 608 |
1 files changed, 608 insertions, 0 deletions
diff --git a/atoidejouerbeta/ui/preview.py b/atoidejouerbeta/ui/preview.py new file mode 100644 index 0000000..9da2df6 --- /dev/null +++ b/atoidejouerbeta/ui/preview.py @@ -0,0 +1,608 @@ + +# python import +import logging, os, threading, time +# .. +from functools import partial +from gettext import gettext as _ + +# gtk import +import gobject, gtk, glib + +# sugar import +from sugar.activity import activity + +# atoidejouerbeta import +from atoidejouerbeta.tools import image, sound, storage, ui + +# get application logger +logger = logging.getLogger('atoidejouerbeta') + + +COLOR_GREY_DARK = ui.get_color(0.5, 0.5, 0.5) +COLOR_GREY_LIGHT = ui.get_color(0.75, 0.75, 0.75) +COLOR_GREY_WHITE = ui.get_color(0.85, 0.85, 0.85) +COLOR_WHITE = ui.get_color(1.0, 1.0, 1.0) + + +def _cb_on_click(button, sequence_preview, filename): + # update current + sequence_preview.set_current(filename) + # udpate preview + sequence_preview.screen.item_preview.set_item(filename) + # get current item pos + _pos = sequence_preview + # get toolbar frame entry + if sequence_preview.screen.toolbar._frame_entry is None: + pass + else: + # get current + _current = str(sequence_preview.get_current_pos()) + # update toolbar entry + sequence_preview.screen.toolbar._frame_entry.set_text(_current) + + +def _cb_on_remove(sequence_preview, filename, button): + # set current first + sequence_preview.set_current(filename) + # udpate sequence preview + sequence_preview.remove_current() + # seq name + _seq_name = sequence_preview.screen.notebook.current_sequence + # .. + _keys = sequence_preview.screen.toolbar.activity.graphic_keys\ + if sequence_preview.screen.toolbar.name == 'graphics_add'\ + else sequence_preview.screen.toolbar.activity.sound_keys + # remove from keys + _keys.remove_filename_from_all(_seq_name, filename) + # update sequence file + storage.sequence_save(sequence_preview.screen.toolbar) + + +def _cb_on_move(sequence_preview, move, button): + # .. + _current = sequence_preview.get_current_pos() + if move == 'left': + _current -= 1 + else: + _current += 1 + # get max value + _max = sequence_preview.number_of_items() - 1 + # prepare value + _new_val = None + if _current > _max: + _current = _max + elif _current < 0: + _current = 0 + # reset max just in case + else: + pass + # update entry + if sequence_preview.screen.toolbar._frame_entry is None: + pass + else: + sequence_preview.screen.toolbar._frame_entry.set_text(str(_current)) + # update sequence + sequence_preview.move_current(_current) + + +def _set_preview_buttom_bg(button): + # set color + button.modify_bg(gtk.STATE_NORMAL, COLOR_GREY_LIGHT) + button.modify_bg(gtk.STATE_PRELIGHT, COLOR_GREY_WHITE) + button.modify_bg(gtk.STATE_ACTIVE, COLOR_WHITE) + + +def _add_simple_button(parent, icon_name, tooltip, cb): + # .. remove button + _button = gtk.Button() + _button.show() + _button.set_tooltip_text(tooltip) # _('Remove ') + filename + # cb + _button.connect('clicked', cb) # cb, self, filename + # add + parent.pack_start(_button, expand=False, fill=False) + # add a remove image here + _img = gtk.Image() + _img.show() + _button.add(_img) + _button.set_size_request(30, 30) + # .. + _set_preview_buttom_bg(_button) + # get pixbuff and update image + _path = storage.get_icon_path(icon_name) + _img.set_from_pixbuf(image.get_pixbuf(_path, 24, 24)) + +class SequencePreview(gtk.Frame): + + def __init__(self, screen, type_): + # keep type + self._type = type_ + # specific frame name + _frame_name = _('Sequence Graphics') if self._type=='graphics'\ + else _('Sequence Sounds') + # init parent + gtk.Frame.__init__(self, _frame_name) + self.set_border_width(2) + self.set_size_request(-1, 140) + # do show + self.show() + # keep the screen + self.screen = screen + self._current = None + # keep item list for the sequence + self.items = list() + # prepare scrolled window + self._scrolled_window = gtk.ScrolledWindow() + self._scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_NEVER) + self._scrolled_window.show() + # a box + _hbox = gtk.HBox(homogeneous=False, spacing=2) + _hbox.show() + self.add(_hbox) + # .. move left button + _add_simple_button(_hbox, 'go_left', _('Move Before'), + partial(_cb_on_move, self, 'left')) + # a box + self._scrolled_hbox = gtk.HBox(homogeneous=False, spacing=2) + self._scrolled_hbox.show() + # add box in viewport + self._scrolled_window.add_with_viewport(self._scrolled_hbox) + # add + _hbox.add(self._scrolled_window) + # .. move left button + _add_simple_button(_hbox, 'go_right', _('Move After'), + partial(_cb_on_move, self, 'right')) + + def clear(self): + # ... + self._current = None + # keep item list for the sequence + self.items = list() + # remove graphics + _children = self._scrolled_hbox.get_children() + for _c in _children: + _c.destroy() + # remove image from preview + self.screen.item_preview.unset_item() + # add box in viewport + self._scrolled_window.add_with_viewport(self._scrolled_hbox) + + def move_current(self, new_pos): + # get current pos + _current_pos = self.get_current_pos() + # little check + _filename = None + if _current_pos == new_pos: + return + # remove current + else: + # update list + _filename = self.items.pop(_current_pos) + self.items.insert(new_pos, _filename) + # .. + self._scrolled_hbox.reorder_child(self._current, new_pos) + + def get_current_pos(self): + # get children + _children = self._scrolled_hbox.get_children() + # get button index + return _children.index(self._current)\ + if self._current in _children else 0 + + def set_current(self, filename): + # get children + _children = self._scrolled_hbox.get_children() + # get new idx index + _index = self.items.index(filename)\ + if filename in self.items else 1000 + # little check + if _index < len(_children): + # update current + self._current = _children[_index] + # update preview + self.screen.item_preview.set_item(filename) + # update toolbar frame entry + if self.screen.toolbar._frame_entry is None: + pass + else: + self.screen.toolbar._frame_entry.set_text(str(_index)) + # ?? + else: + pass + + def number_of_items(self): + return len(self._scrolled_hbox.get_children()) + + def __remove(self, index): + # update list + if index + 1 <= len(self.items): + self.items.pop(index) + # clear current + self._current.destroy() + self._current = None + # remove image from preview + self.screen.item_preview.unset_item() + else: + pass + + def remove_current(self): + # get button index + _index = self.get_current_pos() + # do remove + self.__remove(_index) + + def remove_item(self, item_name): + # get children + _children = self._scrolled_hbox.get_children() + # get button index + _index = _children.index(item_name)\ + if item_name in _children else 0 + # do remove + self.__remove(_index) + + def add_item(self, filename, pos=None): + # .. + _item_box = gtk.HBox(homogeneous=False, spacing=2) + _item_box.show() + self._scrolled_hbox.pack_start(_item_box, expand=False, fill=False) + # prepare vbox item + _vbox = gtk.VBox(homogeneous=False, spacing=2) + _vbox.show() + _item_box.pack_start(_vbox, expand=False, fill=False) + # ... + # simple add + if filename in self.items: + pass + elif pos is None: + # update list + self.items.append(filename) + # add at pos + else: + # insert filename + self.items.insert(pos, filename) + # second pass .. reorder + self._scrolled_hbox.reorder_child(_vbox, pos) + # init event box to manage color + _item = gtk.Button() + _vbox.pack_start(_item, expand=False, fill=True) + # .. + _set_preview_buttom_bg(_item) + # set size + _item.set_size_request(96, 78) + # set relief + _item.set_relief(gtk.RELIEF_NONE) + # cb + _item.connect('clicked', _cb_on_click, self, filename) + # .. + _item.show() + # add a picture here + _item_img = gtk.Image() + _item_img.show() + _item.add(_item_img) + # get graphics path + if self._type == 'graphics': + _path = storage.get_image_path(filename) + elif self._type == 'sounds': + _path = storage.get_image_path('sound', dir_='data') + # ?? do nothing - TODO maybe log something + else: + _path = storage.get_image_path('blank', dir_='data') + # get pixbuff and update image + _item_img.set_from_pixbuf(image.get_pixbuf(_path, 96, 62)) + # add label + _label = gtk.Label(filename) + # ... + _label.show() + # ... + _vbox.pack_start(_label, expand=False, fill=True) + # .. remove button + _add_simple_button(_item_box, 'less_small', _('Remove ') + filename, + partial(_cb_on_remove, self, filename)) + # set current file nam eat the end + self.set_current(filename) + + +class ItemPreview(gtk.VBox): + + def __init__(self, screen, type_=None): + # init parent + gtk.VBox.__init__(self, homogeneous=False, spacing=0) + # keep screen and type + self.screen = screen + self._type = type_ + # .. + self._screen_height = gtk.gdk.screen_height() - 140 + self._screen_width = gtk.gdk.screen_width() - 360 + # update size request + self.set_size_request(self._screen_width, self._screen_height) + # show self + self.show() + + def unset_item(self): + for _c in self.get_children(): + _c.destroy() + + def __set_image(self, path): + # eventbox for the background + _ebox_image = gtk.EventBox() + _ebox_image.modify_bg(gtk.STATE_NORMAL, COLOR_WHITE) + _ebox_image.show() + # add a picture here + _image = gtk.Image() + # show + _image.show() + # .. + _ebox_image.add(_image) + # get pixbuff + _pixbuf = image.get_pixbuf(path, self._screen_width, + self._screen_height) + # set image + _image.set_from_pixbuf(_pixbuf) + # ... + self.pack_start(_ebox_image, expand=True, fill=True) + + def __set_label(self, filename): + # eventbox for the background + _ebox_label = gtk.EventBox() + _ebox_label.modify_bg(gtk.STATE_NORMAL, COLOR_GREY_DARK) + _ebox_label.set_size_request(-1, 24) + _ebox_label.show() + # add label + _label = gtk.Label('<b>%s</b>' % filename) + _label.set_property('use-markup', True) + _ebox_label.modify_bg(gtk.STATE_NORMAL, COLOR_WHITE) + # ... + _label.show() + # ... + _ebox_label.add(_label) + # ... + self.pack_start(_ebox_label, expand=False, fill=True) + + def set_item(self, filename): + # get path + if self._type == 'graphics': + _path = storage.get_image_path(filename) + elif self._type == 'sounds': + _path = storage.get_image_path('sound', dir_='data') + else: + _path = storage.get_image_path('blank', dir_='data') + # little check + if os.path.exists(_path): + # unset first + self.unset_item() + # .. + self.__set_image(_path) + # .. + self.__set_label(filename) + # OK + return True + else: + return False + + +class ImagePreview(ItemPreview): + + def __init__(self, screen): + # init parent + ItemPreview.__init__(self, screen, type_='graphics') + + +def _on_stop(widget, sound_view, filename): + # update playing flag + sound_view.playing = False + # thread update + sound_view._thread.pause(stop=True) + + +def _on_play_pause(widget, sound_view, filename): + # update playing flag + sound_view.playing = not sound_view.playing + # thread update + if sound_view.playing is True: + sound_view._thread.play() + else: + sound_view._thread.pause() + + +def _cb_slider(widget, event, sound_view): + """action = 'press' or 'release' + """ + # ... + if event.type == gtk.gdk.BUTTON_PRESS: + sound_view._thread._set_value = False + elif event.type == gtk.gdk.BUTTON_RELEASE: + # get time + _time = widget.get_value() + # udpate thread time + sound_view._thread._time = _time + sound_view._thread._set_value = True + # seek player + sound_view.player.seek(_time) + # ?? + else: + pass + + +def _cb_format_value(widget, value, sound_view): + """Format the slider value to display + """ + # return formated value + return '%1d:%02d' % divmod(value, 60) + + +class ThreadPlayer(threading.Thread): + + def __init__(self, sound_view, rate=1): + # init parent + threading.Thread.__init__(self) + # main flag + self._die = False + self._pause = True + self._set_value = True + # main vars + self.sound_view = sound_view + self._rate = rate + self._time = 0 + self._max = 0 + # start right now + self.start() + + def set_max(self, max_): + self._max = max_ + + def pause(self, stop=False): + self._pause = True + # .. + self.sound_view.switch_button() + # .. + if self.sound_view._adjustment is None: + return + # reset time on stop + elif stop is True: + # reset time + self._time = 0 + # update slider + self.sound_view._adjustment.set_value(0) + # stop player + self.sound_view.player.stop() + # .. + self.sound_view._slider.set_property('sensitive', False) + else: + # pause player + self.sound_view.player.pause() + + def play(self): + self._pause = False + # pause player + self.sound_view.player.play() + # seek player + self.sound_view.player.seek(self._time) + # .. + self.sound_view.switch_button() + # .. + self.sound_view._slider.set_property('sensitive', True) + + def kill(self): + # stop player + self.sound_view.player.stop() + # .. + self._die = True + + def run(self): + # ... + while self._die is False: + # ... + time.sleep(self._rate) + if self._time >= self._max: + self.pause(stop=True) + # do pause + elif self._pause is False: + # just in case + self._time += self._rate + # ... + if self.sound_view._adjustment is None: + pass + # ... + elif self._set_value is True: + self.sound_view._adjustment.set_value(self._time) + else: + pass + # .. do nothing + else: + pass + +class SoundPreview(ItemPreview): + + def __init__(self, screen): + # init parent + ItemPreview.__init__(self, screen, type_='sounds') + # .. + self.playing = False + # .. + self.player = sound.Player() + # .. + self._adjustment = None + self._slider = None + self._button_play = None + self._thread = ThreadPlayer(self) + + def switch_button(self): + # image stuff + _img = gtk.Image() + _img.show() + # .. + _stock_id = 'pause' if self.playing is True else 'play' + # update image + _img.set_from_file(storage.get_icon_path(_stock_id)) + # update button + if self._button_play is None: + pass + else: + self._button_play.set_image(_img) + + def unset_item(self): + # call parent + ItemPreview.unset_item(self) + # stop player + self.player.stop() + + def __set_slider(self, filename): + # eventbox for the background + _ebox_player = gtk.EventBox() + _ebox_player.modify_bg(gtk.STATE_NORMAL, COLOR_WHITE) + _ebox_player.show() + # init player row + _hbox = gtk.HBox(homogeneous=False, spacing=12) + _hbox.set_border_width(8) + _hbox.set_size_request(-1, 64) + # .. + _hbox.show() + # .. + _ebox_player.add(_hbox) + # add button stop + _button_stop = ui.get_button(stock_id='stop') + # set cb + _button_stop.connect('clicked', _on_stop, self, filename) + _button_stop.modify_bg(gtk.STATE_NORMAL, COLOR_WHITE) + # .. + _hbox.pack_start(_button_stop, expand=False, fill=True) + # add button play + self._button_play = ui.get_button(stock_id='play') + # set cb + self._button_play.connect('clicked', _on_play_pause, self, filename) + self._button_play.modify_bg(gtk.STATE_NORMAL, COLOR_WHITE) + # .. + _hbox.pack_start(self._button_play, expand=False, fill=True) + # add slider + _timedelta = self.player.get_duration() + self._adjustment = gtk.Adjustment(0, 0, _timedelta.seconds, 1) + # udpate max + self._thread.set_max(_timedelta.seconds) + # .. + self._slider = gtk.HScale(self._adjustment) + self._slider.set_draw_value(True) + self._slider.set_digits(False) + self._slider.set_update_policy(gtk.UPDATE_CONTINUOUS) + self._slider.set_property('sensitive', False) + # manage cb + self._slider.connect('button-press-event', _cb_slider, self) + self._slider.connect('button-release-event', _cb_slider, self) + self._slider.connect('format-value', _cb_format_value, self) + # show + self._slider.show() + # .. + _hbox.pack_start(self._slider, expand=True, fill=True) + # ... + self.pack_start(_ebox_player, expand=False, fill=True) + + def set_item(self, filename): + # call parent + if ItemPreview.set_item(self, filename): + # get sound path + _soundfile = storage.get_sound_path(filename) + # load player + self.player.load(_soundfile) + # add player + self.__set_slider(filename) + else: + pass |