diff options
Diffstat (limited to 'atoidejouer/tools/storage.py')
-rw-r--r-- | atoidejouer/tools/storage.py | 345 |
1 files changed, 144 insertions, 201 deletions
diff --git a/atoidejouer/tools/storage.py b/atoidejouer/tools/storage.py index 6db569e..2dad46b 100644 --- a/atoidejouer/tools/storage.py +++ b/atoidejouer/tools/storage.py @@ -4,15 +4,22 @@ import dbus, logging, os, shutil, tarfile, time # .. from gettext import gettext as _ -# gtk import -import gtk - # png import from pypng from lib import png # sugar import -from sugar.activity import activity -from sugar.datastore import datastore +try: + from sugar.activity import activity + from sugar.datastore import datastore + import gtk + ROOT = activity.get_activity_root() + BUND = activity.get_bundle_path() +except Exception, e: + datastore = None + gtk = None + ROOT = os.path.join(os.path.dirname(__file__), '..', '..', + '..', 'atdj_root') + BUND = os.path.join(os.path.dirname(__file__), '..', '..') # get application logger logger = logging.getLogger('atoidejouer') @@ -22,126 +29,38 @@ ACTIVITY_NAMES = { 'record': 'org.laptop.RecordActivity', } +ACTIVITY_PER_MIME_TYPES = { + 'image/png': 'org.laptop.Oficina', + 'audio/ogg': 'org.laptop.RecordActivity', + } + def get_tmp_path(ext='png'): - return os.path.join(activity.get_activity_root(), 'tmp.%s' % ext) + return os.path.join(ROOT, 'tmp.%s' % ext) def get_config_path(): # get bundle path - _bundle_path = activity.get_bundle_path() + _bundle_path = BUND # return path return os.path.join(_bundle_path, 'static', 'data', 'config', 'config.ini') -def list_sequence_names(type_): - # init result - _names = list() - # prepare dir path - _seq_dir = os.path.join(activity.get_activity_root(), 'data', - 'sequences', type_) - # .. - for _filename in os.listdir(_seq_dir): - # .. - _path = os.path.join(_seq_dir, _filename) - # little check - if os.path.isfile(_path): - # check name - try: - _n, _ext = os.path.splitext(_filename) - # check ext - if _ext == '.seq': - _names.append((_n, _path)) - else: - continue - except Exception, e: - # TODO log something - continue - # .. - return _names - - -def get_sequence_items(sequence_path): - if os.path.exists(sequence_path): - _f = open(sequence_path) - _rows = _f.readlines() - _f.close() - else: - return [] - # .. - _names = list() - for _n in _rows: - _n = _n.strip() - if _n == '': - continue - else: - _names.append(_n) - # .. - return _names - - -def get_sequence_path(type_, sequence_name): - return os.path.join(activity.get_activity_root(), 'data', - 'sequences', type_, '%s.seq' % sequence_name) - - -def get_sequence_first_graphic_name(type_, sequence_name): - # seq file - _f = open(get_sequence_path(type_, sequence_name)) - _names = _f.readlines() - _f.close() - # .. - return None if len(_names) == 0 else _names[0].strip() - - -def sequence_save(toolbar, remove=False): - # get sequence name - _name = toolbar._sequence_entry.get_text() - # get screen - _screen = toolbar.activity.get_current_screen() - # get nb of graphics - _nb_of_items = _screen.sequence_preview.number_of_items() - # type shortcut 'graphic' or 'sound' - _type = _screen.notebook._type - # get sequence path - _seq_path = get_sequence_path(_type, _name) - # little check - if _name.strip() == '': - return - elif _nb_of_items == 0\ - and remove is True: - # remove from files - os.remove(_seq_path) - # .. - _keys = toolbar.activity.graphic_keys\ - if toolbar.name == 'graphics_add'\ - else toolbar.activity.sound_keys - # remove from keys - _keys.remove_sequence(_name) - else: - # open file - _file = open(_seq_path, 'wb') - # update - for _filename in _screen.sequence_preview.items: - _filename = _filename.strip() - if _filename == '': - continue - else: - _file.write('%s\n' % _filename) - _file.close() - # update notebook - _screen.notebook._get_store_sequence() +def get_db_path(filename, dir_='db'): + # return path + return os.path.join(ROOT, 'data', dir_, + '%s.db' % filename) def get_sound_path(filename, dir_='sounds'): # return path - return os.path.join(activity.get_activity_root(), 'data', dir_, + return os.path.join(ROOT, 'data', dir_, '%s.ogg' % filename) def get_icon_path(stock_id): # return path - return os.path.join(activity.get_bundle_path(), 'static', 'data', 'icons', + return os.path.join(BUND, 'static', 'data', 'icons', '%s.png' % stock_id) @@ -149,31 +68,40 @@ def get_image_path(filename, dir_='graphics'): # return path if filename in ['background_default', 'mask_default']\ or dir_=='data': - return os.path.join(activity.get_bundle_path(), 'static', 'data', + return os.path.join(BUND, 'static', 'data', 'graphics', '%s.png' % filename) else: - return os.path.join(activity.get_activity_root(), 'data', dir_, + return os.path.join(ROOT, 'data', dir_, '%s.png' % filename) def get_html_path(page): # return path - return os.path.join(activity.get_bundle_path(), 'static', 'data', 'html', + return os.path.join(BUND, 'static', 'data', 'html', '%s.html' % page) def get_pixbuf_from_data(data, image_type=None, size=None): # load it - if image_type: + if gtk is None: + return + elif image_type: _loader = gtk.gdk.PixbufLoader(image_type=image_type) else: _loader = gtk.gdk.PixbufLoader() + # DEBUG + logger.debug('[tools.storage] get_pixbuf_from_data - size: %s/%s' % size) # size check if size is None: pass else: + # get image size + from atoidejouer.tools import image + _info, _w, _h = image.get_image_info(data=data) # parse size - _w, _h = size + _max_w, _max_h = size + # compute target size to keep ratio + _w, _h = image.compute_width_height(_w, _h, _max_w, _max_h) # set loader size _loader.set_size(_w, _h) # load data @@ -318,40 +246,30 @@ def png_from_pixbuf(filename, timestamp): del _new_new_pixels -def __do_query(query): +def journal_query(query): + if not datastore: + return # find in ds _results, _count = datastore.find(query, sorting='timestamp') for _r in _results: - # get meta - _m = _r.get_metadata() - if 'activity' in query: - yield _r - elif _m['activity'] == '': - yield _r - else: - continue + yield _r def get_journal_objects(activity_name=None, mime_type=None): - # init - _query = dict() - # prepare query name if activity_name is None\ and mime_type is None: return [] elif mime_type is None: - return __do_query({'activity': ACTIVITY_NAMES[activity_name]}) + return journal_query({'activity': ACTIVITY_NAMES[activity_name]}) else: - return __do_query({'mime_type': mime_type}) + return journal_query({'mime_type': mime_type}) -def list_info_from_journal(activity_name=None, mime_type=None): - # get objects first - _objs = get_journal_objects(activity_name=activity_name, mime_type=mime_type) +def list_info_from_journal(mime_type=None): # make unique titles _titles = {} # return infos - for _o in _objs: + for _o in journal_query({'mime_type': mime_type}): # get meta _m = _o.get_metadata() # get title @@ -388,16 +306,16 @@ def list_files_from_journal(activity_name=None, mime_type=None): def get_path_from_journal(timestamp, mime_type): - # .. + if not datastore: + return + # prepare datastore query _query = { 'timestamp': int(timestamp), 'mime_type': mime_type } # find in ds _results, _count = datastore.find(_query) - # .. if _count == 1: - # get path return _results[0].get_file_path() else: return None @@ -406,9 +324,9 @@ def get_path_from_journal(timestamp, mime_type): def __check_dir(dir_name, parent='data'): # get activity path if parent is None: - _dir = os.path.join(activity.get_activity_root(), dir_name) + _dir = os.path.join(ROOT, dir_name) else: - _dir = os.path.join(activity.get_activity_root(), parent, dir_name) + _dir = os.path.join(ROOT, parent, dir_name) # ensure activity path if os.path.exists(_dir): pass @@ -416,50 +334,107 @@ def __check_dir(dir_name, parent='data'): os.mkdir(_dir) -def __check_file(sub_path, file_name): - # .. +def __check_file_in_bundle(sub_path, file_name, mime_type=None, in_journal=False): + # ensure dir exist in bundle __check_dir(sub_path) # file path - _path = os.path.join(activity.get_activity_root(), 'data', sub_path, - file_name) + _path = os.path.join(ROOT, 'data', sub_path, file_name) # ensure file if os.path.exists(_path): pass else: # get bundle path - _p = os.path.join(activity.get_bundle_path(), 'static', 'ext', - sub_path, file_name) - # copy + _p = os.path.join(BUND, 'static', 'ext', sub_path, file_name) + # copy to the bundle shutil.copy(_p, _path) -def __check_dir_files(sub_path): +def is_in_journal(file_name, mime_type): + if not datastore: + return + # prepare query + _query = { + 'activity': ACTIVITY_PER_MIME_TYPES[mime_type], + 'mime_type': mime_type + } + # has records ? + _res, _count = datastore.find(_query) + # manual check because query with title doesnt work ? + return file_name in [o.metadata['title'] for o in _res] + + +def __get_preview(file_path): + """Creates preview from file path for ds metadata. + cf.: http://en.flossmanuals.net/make-your-own-sugar-activities/fun-with-the-journal + """ + # DEBUG + logger.debug('[tools.storage] __get_preview - file_path: %s' % file_path) + # avoid inter-dependance loop + from atoidejouer.tools import image + # prepare pixbuf + _pixbuf = image.get_pixbuf(file_path, 128, 96) + # data cb + def _save_func(buf, data): + data.append(buf) + # save data + _data = [] + _pixbuf.save_to_callback(_save_func, 'png', user_data=_data) + # done + return dbus.ByteArray(''.join(_data)) + + +def add_file_to_journal(file_name, file_path, mime_type): + if not datastore: + return + _props = { + 'activity': ACTIVITY_PER_MIME_TYPES[mime_type], + 'mime_type': mime_type, + 'title': file_name, + 'preview': __get_preview(file_path) + } + # prepare meta + _meta = datastore.DSMetadata(_props) + # prepare ds object + _dsobject = datastore.create() + _dsobject.metadata = _meta + _dsobject.file_path = file_path + # write it + datastore.write(_dsobject) + + +def __check_file_in_journal(sub_path, file_name, mime_type=None): + # is already in the journal + if is_in_journal(file_name, mime_type): + pass + else: + # file path + _path = os.path.join(ROOT, 'data', sub_path, file_name) + # ensure dir exist in bundle + add_file_to_journal(file_name, _path, mime_type) + + +def __check_dir_files(sub_path, mime_type=None, in_journal=False): # get bundle path - _path = os.path.join(activity.get_bundle_path(), 'static', 'ext', sub_path) + _path = os.path.join(BUND, 'static', 'ext', sub_path) # file by file for _f in os.listdir(_path): # full path _p = os.path.join(_path, _f) # little check - if os.path.isdir(_p): + if os.path.isdir(_p) or _f in ['blank']: pass + elif in_journal is True: + __check_file_in_journal(sub_path, _f, mime_type=mime_type) else: - __check_file(sub_path, _f) - - -def init_activity_folder(): - # check folders - _root = activity.get_activity_root() - # graphics - __check_dir_files('graphics') - # sounds - __check_dir_files('sounds') - # sequences - __check_dir('sequences') - __check_dir_files(os.path.join('sequences', 'graphics')) - __check_dir_files(os.path.join('sequences', 'sounds')) - # stories + __check_file_in_bundle(sub_path, _f) + + +def init_activity_files(): + __check_dir_files('db') __check_dir_files('stories') + # add embedded resources to the journal for common usage + __check_dir_files('graphics', mime_type='image/png', in_journal=True) + __check_dir_files('sounds', mime_type='audio/ogg', in_journal=True) def __show_in_out_result_message(label, message): @@ -470,12 +445,12 @@ def __show_in_out_result_message(label, message): def __merge_dir(project_name, dir_name, exist_list=None): # archive path - _path_src = os.path.join(activity.get_activity_root(), 'tmp', project_name, + _path_src = os.path.join(ROOT, 'tmp', project_name, dir_name) # little check if os.path.exists(_path_src): # project path - _path_dst = os.path.join(activity.get_activity_root(), 'data', + _path_dst = os.path.join(ROOT, 'data', dir_name) # init existing list exist_list = list() if exist_list is None else exist_list @@ -502,7 +477,7 @@ def __merge_dir(project_name, dir_name, exist_list=None): def __import_keys(activity_, project_name): # .. - _path_data = os.path.join(activity.get_activity_root(), 'tmp', + _path_data = os.path.join(ROOT, 'tmp', project_name, 'story.keys') # init content _data = None @@ -534,7 +509,7 @@ def import_project(activity_, file_path, msg_label): __remove_dir('tmp', parent=None) __check_dir('tmp', parent=None) # .. - _tmp_root = os.path.join(activity.get_activity_root(), 'tmp') + _tmp_root = os.path.join(ROOT, 'tmp') try: # copy file to tmp _tar_path = os.path.join(_tmp_root, '__tmp.tar.bz2') @@ -557,11 +532,7 @@ def import_project(activity_, file_path, msg_label): # merge dirs _exist_list = list() if __merge_dir(_p_name, 'graphics', exist_list=_exist_list)\ - and __merge_dir(_p_name, 'sounds', exist_list=_exist_list)\ - and __merge_dir(_p_name, os.path.join('sequences', 'graphics'), - exist_list=_exist_list)\ - and __merge_dir(_p_name, os.path.join('sequences', 'sounds'), - exist_list=_exist_list): + and __merge_dir(_p_name, 'sounds', exist_list=_exist_list): # init result message _msg = _('Project sucessfully imported') else: @@ -610,10 +581,10 @@ def import_project(activity_, file_path, msg_label): def __remove_dir(dir_name, parent=None): # get activity path if parent is None: - _dir = os.path.join(activity.get_activity_root(), dir_name) + _dir = os.path.join(ROOT, dir_name) _next_parent = dir_name else: - _dir = os.path.join(activity.get_activity_root(), parent, dir_name) + _dir = os.path.join(ROOT, parent, dir_name) _next_parent = os.path.join(parent, dir_name) # remove files and dir recursively if os.path.exists(_dir): @@ -633,31 +604,6 @@ def __remove_dir(dir_name, parent=None): pass -def __export_seq_and_res(activity_, tmp_root, type_='graphics'): - # path updates - _seq_src = os.path.join(activity.get_activity_root(), 'data', 'sequences', - type_) - _seq_dst = os.path.join(tmp_root, 'sequences', type_) - # .. - _res_root = os.path.join(activity.get_activity_root(), 'data', type_) - _res_dst = os.path.join(tmp_root, type_) - # keys factory - _keys = activity_.graphic_keys if type_ == 'graphics'\ - else activity_.sound_keys - # set res ext - _ext = '.png' if type_ == 'graphics' else '.ogg' - # copy - for _n in _keys._names: - if _n.strip() == '': - continue - else: - _s_path = os.path.join(_seq_src, '%s.seq' % _n) - shutil.copy(_s_path, _seq_dst) - for _res in get_sequence_items(_s_path): - _res_path = os.path.join(_res_root, '%s%s' % (_res, _ext)) - shutil.copy(_res_path, _res_dst) - - def export_project(activity_, msg_label, media): # get the toolbar _toolbar = activity_._toolbox.get_activity_toolbar() @@ -669,19 +615,16 @@ def export_project(activity_, msg_label, media): # create a tmp stucture __check_dir(_name, parent='tmp') __check_dir(os.path.join(_name, 'graphics'), parent='tmp') - __check_dir(os.path.join(_name, 'sequences'), parent='tmp') - __check_dir(os.path.join(_name, 'sequences', 'graphics'), parent='tmp') - __check_dir(os.path.join(_name, 'sequences', 'sounds'), parent='tmp') __check_dir(os.path.join(_name, 'sounds'), parent='tmp') # .. - _tmp_root = os.path.join(activity.get_activity_root(), 'tmp') + _tmp_root = os.path.join(ROOT, 'tmp') _out_root = os.path.join(_tmp_root, _name) # copy keys _keys_path = os.path.join(_out_root, 'story.keys') activity_.write_file(_keys_path) # copy sequences and resources - __export_seq_and_res(activity_, _out_root, type_='graphics') - __export_seq_and_res(activity_, _out_root, type_='sounds') + # __export_seq_and_res(activity_, _out_root, type_='graphics') + # __export_seq_and_res(activity_, _out_root, type_='sounds') # change dir for zipping os.chdir(_tmp_root) # zip all |