Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/atoidejouer/tools/storage.py
diff options
context:
space:
mode:
Diffstat (limited to 'atoidejouer/tools/storage.py')
-rw-r--r--atoidejouer/tools/storage.py345
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