diff options
Diffstat (limited to 'atoidejouerbeta/ui/notebook.py')
-rw-r--r-- | atoidejouerbeta/ui/notebook.py | 574 |
1 files changed, 574 insertions, 0 deletions
diff --git a/atoidejouerbeta/ui/notebook.py b/atoidejouerbeta/ui/notebook.py new file mode 100644 index 0000000..3ab3e60 --- /dev/null +++ b/atoidejouerbeta/ui/notebook.py @@ -0,0 +1,574 @@ + +# python import +import logging, os, shutil +# .. +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, 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.7, 0.7, 0.7) +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_swicth_page(widget, page, page_num, notebook): + if page_num == 1: + notebook.remove_button.show() + else: + notebook.remove_button.hide() + notebook.remove_label.hide() + # get current child + _child = widget.get_nth_page(page_num) + # get current label + _label = widget.get_tab_label(_child) + # force white + glib.idle_add(partial(_label.modify_fg, gtk.STATE_NORMAL, COLOR_WHITE)) + + +def _cb_cursor_changed(treeview, notebook, type_): + # get the current cursor and path + _path, _column = treeview.get_cursor() + # DEBUG + if _column is None: + return + else: + pass + # get model + _model = treeview.get_model() + # get resource info + _info = _model + # get iter + _iter = _model.get_iter(_path) + # update current + if type_ in ['graphics', 'sounds']: + # get value + _filename = _model.get_value(_iter, 1) + # udpate preview + notebook.screen.item_preview.set_item(filename=_filename) + # update current + notebook.current_item = _filename + # update current + elif type_ == 'journal': + # get value + _pixbuf = _model.get_value(_iter, 0) + _filename = _model.get_value(_iter, 1) + _metadata = _model.get_value(_iter, 3) + # copy journal item to library to work on it + if notebook._type == 'graphics': + storage.png_from_pixbuf(_filename, _metadata['timestamp']) + # .. + notebook._get_store_graphic() + # for sound + else: + # get source path + _src_path = storage.get_path_from_journal(_metadata['timestamp'], + 'audio/ogg') + # get dst path + _dst_path = storage.get_sound_path(_filename) + # copy + shutil.copy(_src_path, _dst_path) + # .. + notebook._get_store_sound() + # udpate preview + notebook.screen.item_preview.set_item(filename=_filename) + # update current + notebook.current_item = _filename + elif type_ == 'sequence': + # clear sequence preview + notebook.screen.sequence_preview.clear() + # get value + _sequence_path = _model.get_value(_iter, 2) + # update sequence .. + _fnames = storage.get_sequence_items(_sequence_path) + for _f in _fnames: + notebook.screen.sequence_preview.add_item(_f.strip()) + # get sequence name + _sequence_name = _model.get_value(_iter, 1) + # get toolbar sequence entry + _entry = notebook.screen.toolbar._sequence_entry + # update toolbar entry + _entry.set_text(_sequence_name) + # update current + notebook.current_sequence = _sequence_name + # .. + notebook.update_store_sequence() + else: + pass + # .. add action - add column as no title + if _column.get_title() is None: + # get graphic name + _item_name = notebook.current_item + _sequence_name = notebook.current_sequence + if _sequence_name is None\ + or _sequence_name.strip() == ''\ + or _item_name is None: + pass + else: + # udpate sequence preview + notebook.screen.sequence_preview.add_item(_item_name) + # update sequence file + storage.sequence_save(notebook.screen.toolbar) + else: + pass + + +def __remove_filename_from_sequence(type_, sequence, filename): + # little check + if filename.strip() == '': + # do nothing + return True + else: + # get sequence path + _seq_path = storage.get_sequence_path(type_, sequence) + # get current names + _fnames = storage.get_sequence_items(_seq_path) + # has remaining files + if filename in _fnames: + _fnames.remove(filename) + else: + return True + # .. + if len(_fnames) == 0: + os.remove(_seq_path) + return False + else: + # open file + _file = open(_seq_path, 'wb') + # update + for _f in _fnames: + _file.write('%s\n' % _f) + # close + _file.close() + # .. + return True + + +def _on_button_click(button, notebook): + # get file path + if notebook._type == 'graphics': + _path = storage.get_image_path(notebook.current_item) + elif notebook._type == 'sounds': + _path = storage.get_sound_path(notebook.current_item) + # do nothing + else: + return + # remove file + os.remove(_path) + # shortcuts + _screen = notebook.screen + _toolbar = _screen.toolbar + _activity = _toolbar.activity + # .. + _keys = _activity.graphic_keys\ + if _toolbar.name == 'graphics_add'\ + else _activity.sound_keys + # .. + _type = 'graphics' if _toolbar.name == 'graphics_add' else 'sounds' + # prepare seq path + _seq_dir = os.path.join(activity.get_activity_root(), 'data', + 'sequences', _type) + # get sequence names + for _seq_name in os.listdir(_seq_dir): + # get sequence name from corresponding file name + _seq_name = _seq_name.replace('.seq', '') + # remove from file system + if __remove_filename_from_sequence(_type, _seq_name, + notebook.current_item) is True: + # remove from keys + _keys.remove_filename_from_all(_seq_name, notebook.current_item) + # remove the entire sequence + else: + # from keys + _keys.remove_sequence(_seq_name) + # .. + notebook._get_store_sequence() + # remove item in treview + notebook.remove_current_row() + # remove current sequence + _screen.sequence_preview.remove_item(notebook.current_item) + # avoid current + notebook.current_item = None + + +class ResourceNotebook(gtk.Frame): + + def __init__(self, screen, type_): + # init parent + gtk.Frame.__init__(self) + self.set_shadow_type(gtk.SHADOW_NONE) + # do show + self.show() + # keep the screen + self.screen = screen + # keep the type + self._type = type_ + # keep the current item + self.current_item = None + self.current_sequence = None + # .. + self.library_treeview = None + self.sequence_treeview = None + # keep stores + self._store_sequence = None + self._store_graphic = None + self._store_sound = None + self._store_journal = None + # init main box + _main_box = gtk.VBox(homogeneous=False, spacing=0) + _main_box.show() + # .. + self.add(_main_box) + # init remove button and label + self.remove_button, self.remove_label = self._get_remove_button() + # .. + _main_box.pack_start(self._get_notebook(), expand=True, fill=True) + # .. + _main_box.pack_start(self.remove_button, expand=False, fill=True) + _main_box.pack_start(self.remove_label, expand=False, fill=True) + + def _get_remove_button(self): + # init button + _button = ui.get_button(label=_('Remove Item from Disk'), + stock_id='delete', width=48, padding=(5, 0)) + _button.set_border_width(2) + _button.hide() + # set cb + _button.connect('clicked', _on_button_click, self) + # init + _label = gtk.Label() + # set markup + _label.set_use_markup(True) + # align + _label.set_padding(5, 5) + _label.set_alignment(0, 0.5) + # return it + return _button, _label + + def focus_current_seq(self, name=None): + # get seq names + _seq_names = [_n for _n, _p in storage.list_sequence_names(self._type)] + _seq_names.sort() + # .. + self.current_sequence = name\ + if len(_seq_names) == 0 or name is not None\ + else _seq_names[0] + if len(_seq_names) == 0: + return + else: + # .. + _index = 0 if self.current_sequence is None\ + or self.current_sequence not in _seq_names\ + else _seq_names.index(self.current_sequence) + # get the current cursor and path + self.sequence_treeview.set_cursor(_index) + + + def remove_current_row(self): + # get the current cursor and path + _path, _column = self.library_treeview.get_cursor() + # get model + _model = self.library_treeview.get_model() + # get resource info + _info = _model + # get iter + _iter = _model.get_iter(_path) + # and remove + _model.remove(_iter) + + def update_store_sequence(self): + # .. + if self.current_sequence is None: + return + else: + # .. + _filename = storage.get_sequence_first_graphic_name( + self._type, self.current_sequence) + if _filename is None: + return + # set current + else: + self.screen.sequence_preview.set_current(_filename) + + def _get_store_sequence(self): + # init store + if self._store_sequence is None: + self._store_sequence = gtk.ListStore( + gtk.gdk.Pixbuf, + gobject.TYPE_STRING, + gobject.TYPE_PYOBJECT + ) + else: + self._store_sequence.clear() + # liste seq names + _seq_names = storage.list_sequence_names(self._type) + # .. + for _name, _path in _seq_names: + # ... + _pixbuf = image.get_sequence_first_graphic(self._type, _name) + # do update + self._store_sequence.append([_pixbuf, _name, _path]) + # return the store + return self._store_sequence + + def _get_store_graphic(self): + # init/reset store + if self._store_graphic is None: + self._store_graphic = gtk.ListStore( + gtk.gdk.Pixbuf, + gobject.TYPE_STRING, + gtk.gdk.Pixbuf, + gobject.TYPE_PYOBJECT + ) + else: + self._store_graphic.clear() + # .. + _add_path = storage.get_icon_path('more_small') + # .. + _graphic_dir = os.path.join(activity.get_activity_root(), 'data', + 'graphics') + # .. + for _filename in os.listdir(_graphic_dir): + # .. + _path = os.path.join(_graphic_dir, _filename) + # little check + if os.path.isfile(_path): + # check name + try: + _filename, _ext = os.path.splitext(_filename) + # check ext + if _ext in ['.png']: + pass + else: + continue + except Exception, e: + # TODO log something + continue + # .. + _pixbuf = image.get_pixbuf(_path, 64, 48) + _pix_a = image.get_pixbuf(_add_path, 24, 24) + # do update + self._store_graphic.append([_pixbuf, _filename, _pix_a, _path]) + else: + continue + # return the store + return self._store_graphic + + def _get_store_sound(self): + # init/reset store + if self._store_sound is None: + self._store_sound = gtk.ListStore( + gtk.gdk.Pixbuf, + gobject.TYPE_STRING, + gtk.gdk.Pixbuf, + gobject.TYPE_PYOBJECT + ) + else: + self._store_sound.clear() + # prepare icon path + _pix_path = storage.get_image_path('sound', dir_='data') + _add_path = storage.get_icon_path('more_small') + # .. + _sound_dir = os.path.join(activity.get_activity_root(), 'data', + 'sounds') + # .. + for _filename in os.listdir(_sound_dir): + # .. + _path = os.path.join(_sound_dir, _filename) + # little check + if os.path.isfile(_path): + # check name + try: + _filename, _ext = os.path.splitext(_filename) + # check ext + if _ext in ['.ogg']: + pass + else: + continue + except Exception, e: + # TODO log something + continue + # .. + _pixbuf = image.get_pixbuf(_pix_path, 64, 48) + _pix_a = image.get_pixbuf(_add_path, 24, 24) + # do update + self._store_sound.append([_pixbuf, _filename, _pix_a, _path]) + else: + continue + # return the store + return self._store_sound + + def __update_store(self, default_pix_path, **query): + # update store + for _i in storage.list_info_from_journal(**query): + if _i['preview'] is None: + # .. + _pixbuf = image.get_pixbuf(default_pix_path, 64, 48) + else: + # prepare preview + _pixbuf = storage.get_pixbuf_from_data(_i['preview'], + size=(64, 48)) + # .. + _add_path = storage.get_icon_path('more_small') + _pix_a = image.get_pixbuf(_add_path, 24, 24) + # store info + _store_info = { + 'activity_id':_i['activity_id'], + 'timestamp': _i['timestamp'] + } + # do update + _row = [_pixbuf, _i['title'], _pix_a, _store_info] + self._store_journal.append(_row) + + def _get_store_journal(self): + # init/reset store + if self._store_journal is None: + self._store_journal = gtk.ListStore( + gtk.gdk.Pixbuf, + gobject.TYPE_STRING, + gtk.gdk.Pixbuf, + gobject.TYPE_PYOBJECT + ) + else: + self._store_journal.clear() + # app to get the journal entries + _a_name = 'paint' if self._type=='graphics' else 'record' + # prepare icon path + _default_pix_path = storage.get_image_path(_a_name, dir_='data') + # manage image from app for paint only + if self._type=='graphics': + self.__update_store(_default_pix_path, activity_name=_a_name) + else: + pass + # .. + _mime_type = 'image/png' if self._type=='graphics' else 'audio/ogg' + # import based on myme type + self.__update_store(_default_pix_path, mime_type=_mime_type) + # return the store + return self._store_journal + + def _get_treeview(self, type_=None): + # .. + _scrolled_win = gtk.ScrolledWindow() + _scrolled_win.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC) + _scrolled_win.show() + # prepare colums + _col_preview = gtk.TreeViewColumn(_('Preview')) + _col_description = gtk.TreeViewColumn(_('Name')) + _col_add = gtk.TreeViewColumn() + # set renderers + _cell_pix = gtk.CellRendererPixbuf() + _cell_pix.set_property('height', 50) + _col_preview.pack_start(_cell_pix, expand=False) + _col_preview.add_attribute(_cell_pix, 'pixbuf', 0) + # .. + _cell_text = gtk.CellRendererText() + _cell_text.set_property('height', 50) + _col_description.pack_start(_cell_text, expand=False) + _col_description.add_attribute(_cell_text, 'text', 1) + _col_description.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED) + # .. + if type_ == 'sequence': + _col_description.set_fixed_width(220) + else: + _col_description.set_fixed_width(250) + # .. + _cell_add = gtk.CellRendererPixbuf() + _cell_add.set_property('height', 50) + _col_add.pack_start(_cell_add, expand=False) + _col_add.add_attribute(_cell_add, 'pixbuf', 2) + _col_add.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED) + _col_add.set_fixed_width(30) + # update store + if type_ == 'sequence': + _store = self._get_store_sequence() + elif type_ == 'graphics': + _store = self._get_store_graphic() + elif type_ == 'sounds': + _store = self._get_store_sound() + elif type_ == 'journal': + _store = self._get_store_journal() + else: + return None + # ensure sorting + _store.set_sort_column_id(1, gtk.SORT_ASCENDING) + # init treeview + _treeview = gtk.TreeView(_store) + _treeview.set_reorderable(False) + # cb + _treeview.connect('cursor-changed', _cb_cursor_changed, self, type_) + # show it + _treeview.show() + # add columns + _treeview.append_column(_col_preview) + _treeview.append_column(_col_description) + # .. + if type_ == 'sequence': + pass + else: + _treeview.append_column(_col_add) + # .. + _scrolled_win.add(_treeview) + # return it + return _scrolled_win + + def _get_notebook(self): + # get list 1 + _list1 = self._get_treeview(type_='sequence') + # keep sequence treeview + self.sequence_treeview = _list1.get_children()[0] + # create a label for the button + _label1 = gtk.Label(_('Sequences')) + # ... + _label1.modify_fg(gtk.STATE_ACTIVE, COLOR_WHITE) + # ... + _label1.show() + # get list 2 + _list2 = self._get_treeview(type_=self._type) + # keep library treeview + self.library_treeview = _list2.get_children()[0] + # create a label for the button + _label2 = gtk.Label(_('Library')) + # ... + _label2.modify_fg(gtk.STATE_ACTIVE, COLOR_WHITE) + # ... + _label2.show() + # get list 2 + _list3 = self._get_treeview(type_='journal') + # create a label for the button + _label3 = gtk.Label(_('Journal')) + # ... + _label3.modify_fg(gtk.STATE_ACTIVE, COLOR_WHITE) + # ... + _label3.show() + # init notebook + _notebook = gtk.Notebook() + _notebook.set_show_border(True) + _notebook.set_border_width(2) + _notebook.set_tab_pos(gtk.POS_TOP) + _notebook.set_size_request(360, -1) + # .. + _notebook.modify_bg(gtk.STATE_NORMAL, COLOR_GREY_DARK) + _notebook.modify_bg(gtk.STATE_ACTIVE, COLOR_GREY_LIGHT) + # .. + _notebook.connect('switch-page', _cb_swicth_page, self) + # .. + _notebook.show() + # add tabs + _notebook.append_page(_list1, _label1) + _notebook.append_page(_list2, _label2) + _notebook.append_page(_list3, _label3) + # return it + return _notebook |