Elementary: Initial implementation for Store. Still needs work on

creating the data struct, maybe using memoryviews.

Includes some internal changes for Genlist.
This commit is contained in:
Kai Huuhko 2013-04-18 15:46:52 +00:00
parent 8033275e70
commit 285856ea03
8 changed files with 1043 additions and 30 deletions

View File

@ -369,6 +369,15 @@ cdef extern from "Elementary.h":
ELM_SOFTCURSOR_MODE_ON
ELM_SOFTCURSOR_MODE_OFF
ctypedef enum Elm_Store_Item_Mapping_Type:
ELM_STORE_ITEM_MAPPING_NONE
ELM_STORE_ITEM_MAPPING_LABEL
ELM_STORE_ITEM_MAPPING_STATE
ELM_STORE_ITEM_MAPPING_ICON
ELM_STORE_ITEM_MAPPING_PHOTO
ELM_STORE_ITEM_MAPPING_CUSTOM
ELM_STORE_ITEM_MAPPING_LAST
ctypedef enum Elm_Text_Format:
ELM_TEXT_FORMAT_PLAIN_UTF8
ELM_TEXT_FORMAT_MARKUP_UTF8

View File

@ -51,7 +51,7 @@ cdef extern from "Elementary.h":
void elm_genlist_item_bring_in(Elm_Object_Item *item, Elm_Genlist_Item_Scrollto_Type scrollto_type)
void elm_genlist_item_update(Elm_Object_Item *item)
void elm_genlist_item_item_class_update(Elm_Object_Item *it, Elm_Genlist_Item_Class *itc)
Elm_Genlist_Item_Class *elm_genlist_item_item_class_get(Elm_Object_Item *it)
# TODO: Elm_Genlist_Item_Class *elm_genlist_item_item_class_get(Elm_Object_Item *it)
int elm_genlist_item_index_get(Elm_Object_Item *it)
void elm_genlist_realized_items_update(Evas_Object *obj)
unsigned int elm_genlist_items_count(Evas_Object *obj)
@ -104,3 +104,13 @@ cdef extern from "Elementary.h":
void elm_genlist_select_mode_set(Evas_Object *obj, Elm_Object_Select_Mode mode)
Elm_Object_Select_Mode elm_genlist_select_mode_get(Evas_Object *obj)
cdef class GenlistItemClass(object):
cdef:
Elm_Genlist_Item_Class cls
object _text_get_func
object _content_get_func
object _state_get_func
object _del_func
object _item_style
object _decorate_item_style
object _decorate_all_item_style

View File

@ -658,27 +658,22 @@ cdef class GenlistItemClass(object):
constructor parameters.
"""
cdef:
Elm_Genlist_Item_Class cls
Elm_Genlist_Item_Class *obj
object _text_get_func
object _content_get_func
object _state_get_func
object _del_func
object _item_style
object _decorate_item_style
object _decorate_all_item_style
# In pxd:
# Elm_Genlist_Item_Class cls
# object _text_get_func
# object _content_get_func
# object _state_get_func
# object _del_func
# object _item_style
# object _decorate_item_style
# object _decorate_all_item_style
def __cinit__(self):
self.obj = &self.cls
self.obj.item_style = NULL
self.obj.decorate_item_style = NULL
self.obj.decorate_all_item_style = NULL
self.obj.func.text_get = _py_elm_genlist_item_text_get
self.obj.func.content_get = _py_elm_genlist_item_content_get
self.obj.func.state_get = _py_elm_genlist_item_state_get
self.cls.func.text_get = _py_elm_genlist_item_text_get
self.cls.func.content_get = _py_elm_genlist_item_content_get
self.cls.func.state_get = _py_elm_genlist_item_state_get
# TODO: Check if the struct member is named del_
self.obj.func.del_ = _py_elm_genlist_object_item_del
self.cls.func.del_ = _py_elm_genlist_object_item_del
def __init__(self, item_style=None, text_get_func=None,
content_get_func=None, state_get_func=None, del_func=None,
@ -773,15 +768,15 @@ cdef class GenlistItemClass(object):
self._decorate_item_style = a2
self._decorate_all_item_style = a3
self.obj.item_style = <char *>self._item_style if self._item_style is not None else NULL
self.obj.decorate_item_style = <char *>self._decorate_item_style if self._decorate_item_style is not None else NULL
self.obj.decorate_all_item_style = <char *>self._decorate_all_item_style if self._decorate_all_item_style is not None else NULL
self.cls.item_style = <char *>self._item_style if self._item_style is not None else NULL
self.cls.decorate_item_style = <char *>self._decorate_item_style if self._decorate_item_style is not None else NULL
self.cls.decorate_all_item_style = <char *>self._decorate_all_item_style if self._decorate_all_item_style is not None else NULL
def __str__(self):
return ("%s(item_style=%r, text_get_func=%s, content_get_func=%s, "
"state_get_func=%s, del_func=%s)") % \
(self.__class__.__name__,
_ctouni(self.obj.item_style),
_ctouni(self.cls.item_style),
self._text_get_func,
self._content_get_func,
self._state_get_func,
@ -794,8 +789,8 @@ cdef class GenlistItemClass(object):
(self.__class__.__name__,
<unsigned long><void *>self,
PY_REFCOUNT(self),
<unsigned long>&self.obj,
_ctouni(self.obj.item_style),
<unsigned long>&self.cls,
_ctouni(self.cls.item_style),
self._text_get_func,
self._content_get_func,
self._state_get_func,
@ -809,7 +804,7 @@ cdef class GenlistItemClass(object):
def __set__(self, style):
if isinstance(style, unicode): style = style.encode("UTF-8")
self._item_style = style
self.obj.item_style = <char *>style if style is not None else NULL
self.cls.item_style = <char *>style if style is not None else NULL
property decorate_item_style:
"""The decoration style of this item class."""
@ -819,7 +814,7 @@ cdef class GenlistItemClass(object):
def __set__(self, style):
if isinstance(style, unicode): style = style.encode("UTF-8")
self._decorate_item_style = style
self.obj.decorate_item_style = <char *>style if style is not None else NULL
self.cls.decorate_item_style = <char *>style if style is not None else NULL
property decorate_all_item_style:
"""Decorate all style of this item class."""
@ -829,7 +824,7 @@ cdef class GenlistItemClass(object):
def __set__(self, style):
if isinstance(style, unicode): style = style.encode("UTF-8")
self._decorate_all_item_style = style
self.obj.decorate_all_item_style = <char *>style if style is not None else NULL
self.cls.decorate_all_item_style = <char *>style if style is not None else NULL
def text_get(self, evasObject obj, part, item_data):
"""To be called by Genlist for each row to get its label.
@ -927,7 +922,7 @@ cdef class GenlistItem(ObjectItem):
"""
self.item_class = item_class.obj
self.item_class = &item_class.cls
self.parent_item = _object_item_from_python(parent_item) if parent_item is not None else NULL
@ -1238,7 +1233,7 @@ cdef class GenlistItem(ObjectItem):
called on the item.
"""
elm_genlist_item_item_class_update(self.item, itc.obj)
elm_genlist_item_item_class_update(self.item, &itc.cls)
#TODO: def item_class_get(self):
"""This returns the Genlist_Item_Class for the given item. It can be

111
efl/elementary/store.pxd Normal file
View File

@ -0,0 +1,111 @@
from libc.stdlib cimport const_void
from libc.string cimport const_char
from efl cimport Eina_Bool
from efl.evas cimport Evas_Object
from enums cimport Elm_Icon_Lookup_Order, Elm_Store_Item_Mapping_Type
from genlist cimport Elm_Genlist_Item_Class
from object_item cimport Elm_Object_Item, const_Elm_Object_Item
cdef extern from "Python.h":
void PyEval_InitThreads()
cdef extern from "Elementary.h":
struct _Elm_Store:
pass
struct _Elm_Store_Item:
pass
ctypedef _Elm_Store Elm_Store # A store object
ctypedef _Elm_Store const_Elm_Store
ctypedef _Elm_Store_Item Elm_Store_Item # A handle of a store item passed to store fetch/unfetch functions
ctypedef _Elm_Store_Item const_Elm_Store_Item
ctypedef void (*Elm_Store_Item_Fetch_Cb)(void *data, Elm_Store_Item *sti) # Function to call to fetch item data
ctypedef void (*Elm_Store_Item_Unfetch_Cb)(void *data, Elm_Store_Item *sti) # Function to cal lto un-fetch (free) an item
ctypedef void *(*Elm_Store_Item_Mapping_Cb)(void *data, Elm_Store_Item *sti, const_char *part) # Custom mapping function to call
struct _Elm_Store_Item_Mapping_Icon:
int w, h # The desired icon size in addition to the file path returned from the mapping
Elm_Icon_Lookup_Order lookup_order # The order in which to find the icon
Eina_Bool standard_name # Use a standard name to find it (EINA_TRUE) or not
Eina_Bool no_scale # EINA_TRUE is you don't want the icon scaled
Eina_Bool smooth # EINA_TRUE if icon is to be smooth scaled
Eina_Bool scale_up # EINA_TRUE if scaling up is allowed
Eina_Bool scale_down # EINA_TRUE if scaling down is allowed
ctypedef _Elm_Store_Item_Mapping_Icon Elm_Store_Item_Mapping_Icon # The data being mapped at the given address is an icon, so use these properties for finding it
struct _Elm_Store_Item_Mapping_Empty:
Eina_Bool dummy # dummy entry - set to anything you like
ctypedef _Elm_Store_Item_Mapping_Empty Elm_Store_Item_Mapping_Empty # An empty piece of mapping information. Useful for String labels as they get used directly
struct _Elm_Store_Item_Mapping_Photo:
int size # Photo size to use (see elm_photo_add()) with the given photo path
ctypedef _Elm_Store_Item_Mapping_Photo Elm_Store_Item_Mapping_Photo # The data is a photo, so use these parameters to find it
struct _Elm_Store_Item_Mapping_Custom:
Elm_Store_Item_Mapping_Cb func # The function called to do the custom mapping and return it
ctypedef _Elm_Store_Item_Mapping_Custom Elm_Store_Item_Mapping_Custom # The item needs a custom mapping which means calling a function and returning a string from it, as opposed to a static lookup. It should not be allocated, and should live in a buffer in memory that survives the return of this function if its a label, or an allocated icon object if its an icon needed etc.
union _Elm_Store_Item_Mapping_Details:
# Allowed to be one of these possible mapping types
Elm_Store_Item_Mapping_Empty empty
Elm_Store_Item_Mapping_Icon icon
Elm_Store_Item_Mapping_Photo photo
Elm_Store_Item_Mapping_Custom custom
# add more types here
struct _Elm_Store_Item_Mapping:
Elm_Store_Item_Mapping_Type type # what kind of mapping is this
const_char *part # what part name in the genlist item is this filling in
int offset # offset in memory (in bytes) relative to base of structure for item data where the data for the mapping lives
_Elm_Store_Item_Mapping_Details details
ctypedef _Elm_Store_Item_Mapping Elm_Store_Item_Mapping # A basic way of telling Store how to take your return data (string, or something else from your struct) and convert it into something genlist can use
ctypedef _Elm_Store_Item_Mapping const_Elm_Store_Item_Mapping
struct _Elm_Store_Item_Info:
Elm_Genlist_Item_Class *item_class # The genlist item class that should be used for the item that has been listed
const_Elm_Store_Item_Mapping *mapping # What kind of mappings do we use for the fields of this item to fill in the genlist item. Terminate array pointed to here with ELM_STORE_ITEM_MAPPING_END
void *data # Pointer to pass to struct data in memory if its already there, of not, NULL
char *sort_id # Sort ID string (strduped()) to know how to wort items, or NULL, if you don't care
ctypedef _Elm_Store_Item_Info Elm_Store_Item_Info # Basic information about a store item - always cast into a specific type like Elm_Store_Item_Info_Filesystem
ctypedef Eina_Bool (*Elm_Store_Item_List_Cb)(void *data, Elm_Store_Item_Info *info) # Function to call for listing an item
struct _Elm_Store_Item_Info_Filesystem:
Elm_Store_Item_Info base # Base information about an item
char *path # Extra information specific to the filesystem store
ctypedef _Elm_Store_Item_Info_Filesystem Elm_Store_Item_Info_Filesystem # Filesystem specific information about a store item
#define ELM_STORE_ITEM_MAPPING_END { ELM_STORE_ITEM_MAPPING_NONE, NULL, 0, { .empty = { EINA_TRUE } } } # Use this to end a list of mappings
#define ELM_STORE_ITEM_MAPPING_OFFSET(st, it) offsetof(st, it) # Use this to get the offset in bytes in memory for where the data for the mapping lives relative to the item data (a private struct pointed to owned by the user
Elm_Store *elm_store_filesystem_new()
void elm_store_free(Elm_Store *st)
void elm_store_filesystem_directory_set(Elm_Store *st, const_char *dir)
const_char *elm_store_filesystem_directory_get(const_Elm_Store *st)
const_char *elm_store_item_filesystem_path_get(const_Elm_Store_Item *sti)
void elm_store_target_genlist_set(Elm_Store *st, Evas_Object *obj)
void elm_store_cache_set(Elm_Store *st, int max)
int elm_store_cache_get(const_Elm_Store *st)
void elm_store_list_func_set(Elm_Store *st, Elm_Store_Item_List_Cb func, const_void *data)
void elm_store_fetch_func_set(Elm_Store *st, Elm_Store_Item_Fetch_Cb func, const_void *data)
void elm_store_unfetch_func_set(Elm_Store *st, Elm_Store_Item_Unfetch_Cb func, const_void *data)
void elm_store_fetch_thread_set(Elm_Store *st, Eina_Bool use_thread)
Eina_Bool elm_store_fetch_thread_get(const_Elm_Store *st)
void elm_store_sorted_set(Elm_Store *st, Eina_Bool sorted)
Eina_Bool elm_store_sorted_get(const_Elm_Store *st)
void elm_store_item_data_set(Elm_Store_Item *sti, void *data)
void *elm_store_item_data_get(Elm_Store_Item *sti)
const_Elm_Store *elm_store_item_store_get(const_Elm_Store_Item *sti)
const_Elm_Object_Item *elm_store_item_genlist_item_get(const_Elm_Store_Item *sti)

551
efl/elementary/store.pyx Normal file
View File

@ -0,0 +1,551 @@
# Copyright (C) 2007-2013 various contributors (see AUTHORS)
#
# This file is part of Python-EFL.
#
# Python-EFL is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# Python-EFL is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this Python-EFL. If not, see <http://www.gnu.org/licenses/>.
"""
Store Elementary Store
Store is an abstracting API that is intended to farm off fetching of data
to threads running asynchronously from the mainloop that actually fetch
data needed for a genlist (or possibly future other widgets) so scrolling
never blocks waiting on IO (though normally this should be the users
job - if using genlist, to ensure all data genlist needs is in memory at
the time it needs it, and if it isn't to queue and defer a fetch and let
genlist know later when its ready. Store actually does this and implements
the infrastructure of this, leaving the actual fetch and convert up to
functions provided by the user).
It is possible for store to run inline without a thread, but this is
highly inadvisable. you can disable this with::
st.fetch_thread = False
Store works first by creating a store, setting up functions to list items
and fetch items. Currently the only store type supported is the
filesystem store, which will list the files inside a directory (not
recursively) and then hand each file it finds (the file path) to the
list function for evaluation.
The list function may look at filename, may open the file or do
anything it likes to determine something about the file. Either it
filters it out (returns EINA_FALSE) and it is discarded or it
returns EINA_TRUE and also provides a "sort id" which is a string
store uses to figure out sorting. This string could be the filename, or
some data based on its contents. The strings are sorted alphabetically
like any normal ASCII strings, with case being important. As this listing
function runs in a thread, it can do blocking IO and parsing without
hurting the fluidity of the main loop and GUI. The list function also
returns information on how to map fields in the source file to elements
of the genlist item. For example, how the fetcher reads the private
data struct of the user (what memory offset in the struct the data is at)
and what type is there (it's a label of some sort, an icon, or with a
custom mapping function that figures it out itself and creates the
content needed for the genlist item).
Store then uses this sort id to build (over time) a sorted list of items
that then map 1:1 to genlist items. When these items are visible and
need content, Store calls the fetch function per item, which is responsible
for fetching the data from the given item and returning data to store
so it can map this to some item content. This function also runs in a
thread, and thus can do blocking IO work to later return the data. Sorting
is optional and can be enabled or disabled too.
When items are no longer needed, store will cal the unfetch function to
free data in memory about that item that is no longer needed. This function
is called in the mainloop and is expected to take minimal or almost no time
to simply free up memory resources.
.. _Elm_Store_Item_Mapping_Type:
.. rubric:: Store item mapping types
.. data:: ELM_STORE_ITEM_MAPPING_NONE
None
.. data:: ELM_STORE_ITEM_MAPPING_LABEL
const_char * -> label
.. data:: ELM_STORE_ITEM_MAPPING_STATE
Eina_Bool -> state
.. data:: ELM_STORE_ITEM_MAPPING_ICON
char * -> icon path
.. data:: ELM_STORE_ITEM_MAPPING_PHOTO
char * -> photo path
.. data:: ELM_STORE_ITEM_MAPPING_CUSTOM
item->custom(it->data, it, part) -> void * (-> any)
"""
from libc.string cimport strdup
from cpython cimport Py_INCREF, Py_DECREF
from efl.eo cimport _ctouni, _touni
from object cimport Object
from object_item cimport _object_item_to_python
from genlist cimport GenlistItemClass
import traceback
PyEval_InitThreads()
cdef Eina_Bool store_fs_item_list_cb(void *data, Elm_Store_Item_Info *info) with gil:
"""Function to call for listing an item (filesystem)"""
cdef StoreItemInfoFilesystem ifs = StoreItemInfoFilesystem.__new__(StoreItemInfoFilesystem)
ifs.info_fs = <Elm_Store_Item_Info_Filesystem *>info
func, args, kwargs = <object>data
try:
ret = func(ifs, args, kwargs)
except Exception, e:
traceback.print_exc()
ifs.info_fs = NULL
if ret is not None:
return bool(ret)
else:
return 0
cdef void store_item_fetch_cb(void *data, Elm_Store_Item *sti) with gil:
"""Function to call to fetch item data"""
cdef StoreItem it = StoreItem.__new__(StoreItem)
it.sti = sti
func, args, kwargs = <object>data
try:
func(it, args, kwargs)
except Exception, e:
traceback.print_exc()
it.sti = NULL
cdef void store_item_unfetch_cb(void *data, Elm_Store_Item *sti) with gil:
"""Function to call to un-fetch (free) an item"""
cdef StoreItem it = StoreItem.__new__(StoreItem)
it.sti = sti
func, args, kwargs = <object>data
try:
func(it, args, kwargs)
except Exception, e:
traceback.print_exc()
it.sti = NULL
cdef void *store_item_mapping_cb(void *data, Elm_Store_Item *sti, const_char *part) with gil:
"""Custom mapping function to call"""
pass
cimport enums
ELM_STORE_ITEM_MAPPING_NONE = enums.ELM_STORE_ITEM_MAPPING_NONE
ELM_STORE_ITEM_MAPPING_LABEL = enums.ELM_STORE_ITEM_MAPPING_LABEL
ELM_STORE_ITEM_MAPPING_STATE = enums.ELM_STORE_ITEM_MAPPING_STATE
ELM_STORE_ITEM_MAPPING_ICON = enums.ELM_STORE_ITEM_MAPPING_ICON
ELM_STORE_ITEM_MAPPING_PHOTO = enums.ELM_STORE_ITEM_MAPPING_PHOTO
ELM_STORE_ITEM_MAPPING_CUSTOM = enums.ELM_STORE_ITEM_MAPPING_CUSTOM
"""
struct _Elm_Store_Item_Mapping_Custom:
Elm_Store_Item_Mapping_Cb func # The function called to do the custom mapping and return it
#define ELM_STORE_ITEM_MAPPING_END { ELM_STORE_ITEM_MAPPING_NONE, NULL, 0, { .empty = { EINA_TRUE } } } # Use this to end a list of mappings
#define ELM_STORE_ITEM_MAPPING_OFFSET(st, it) offsetof(st, it)
"""
include "store_item_mapping.pxi"
cdef class StoreItemInfo(object):
cdef:
Elm_Store_Item_Info *info
property item_class:
"""The genlist item class that should be used for the item that has been
listed
:type: :py:class:`GenlistItemClass <efl.elementary.genlist.GenlistItemClass>`
"""
def __set__(self, GenlistItemClass value):
self.info.item_class = &value.cls
def __get__(self):
cdef GenlistItemClass ret = GenlistItemClass.__new__(GenlistItemClass)
ret.cls = self.info.item_class[0]
return ret
# property mapping:
# """What kind of mappings do we use for the fields of this item to fill
# in the genlist item. Terminate array pointed to here with
# ELM_STORE_ITEM_MAPPING_END
# :type: StoreItemMapping
# """
# def __set__(self, value):
# self.info.mapping = value
# def __get__(self):
# cdef StoreItemMapping
# return self.info.mapping
property data:
"""Pointer to pass to struct data in memory if its already there, or
NULL if not.
:type: object
"""
def __set__(self, value):
self.info.data = <void *>value
def __get__(self):
if not self.info.data == NULL:
return <object>self.info.data
property sort_id:
"""Sort ID string (strduped()) to know how to sort items, or NULL, if
you don't care.
:type: unicode
"""
def __set__(self, value):
if isinstance(value, unicode): value = value.encode("UTF-8")
self.info.sort_id = strdup(value)
def __get__(self):
return _touni(self.info.sort_id)
cdef class StoreItemInfoFilesystem(object):
cdef Elm_Store_Item_Info_Filesystem *info_fs
property base:
"""Base information about an item
:type: StoreItemInfo
"""
def __get__(self):
cdef StoreItemInfo ret = StoreItemInfo.__new__(StoreItemInfo)
ret.info = &self.info_fs.base
return ret
property path:
"""Extra information specific to the filesystem store
:type: unicode
"""
def __set__(self, value):
if isinstance(value, unicode): value = value.encode("UTF-8")
self.info_fs.path = strdup(value)
def __get__(self):
return _touni(self.info_fs.path)
cdef class Store(object):
"""The class that holds the implementation of the widget."""
cdef Elm_Store *st
def __init__(self, store_type = None):
self.st = elm_store_filesystem_new()
if self.st == NULL:
Py_DECREF(self)
def delete(self):
"""Free the store object and all items it manages
This frees the given @p st store and all the items it manages. It will
clear the List that it populated, but otherwise leave it alone. It will
cancel background threads (and may have to wait for them to complete a
pending operation to do this).
"""
elm_store_free(self.st)
property filesystem_directory:
"""The path to the directory to scan for a filesystem store
This sets the directory (@p dir) to scan and begins scanning in the
the background in threads (or not if threading is disabled with
elm_store_fetch_thread_set()). Note that Listing is always done in a thread
but fetching may not be if disabled here. This should be the last thing
called after fetch, list and unfetch functions are set, as well as target
genlist etc. You also should not change the directory once set. If you
need a new directory scanned, create a new store.
This gets the directory set by elm_store_filesystem_directory_set(). This
string returned will be valid until elm_store_filesystem_directory_set()
changes it or until the store is freed with elm_store_free().
:type: unicode
"""
def __set__(self, value):
self.filesystem_directory_set(value)
def __get__(self):
return self.filesystem_directory_get()
cpdef filesystem_directory_set(self, directory):
if isinstance(directory, unicode): directory = directory.encode("UTF-8")
elm_store_filesystem_directory_set(self.st,
<const_char *>directory if directory is not None else NULL)
cpdef filesystem_directory_get(self):
return _ctouni(elm_store_filesystem_directory_get(self.st))
property target_genlist:
"""Set the target genlist to fill in from the store
This tells the store the target genlist to use to fill in content from
the store. Once a store starts "going" via elm_store_filesystem_directory_set()
The target should never be changed again.
:type: :py:class:`Genlist <efl.elementary.genlist.Genlist>`
"""
def __set__(self, value):
self.target_genlist_set(value)
cpdef target_genlist_set(self, Object target):
elm_store_target_genlist_set(self.st, target.obj)
property cache_size:
"""Set the maximum number of items that are not visible to keep cached
Store may keep some items around for caching purposes that cannot be seen,
so this controls the maximum number. The default is 128, but may change
at any point in time in the future.
:param max: The number of items to keep (should be greater than or equal to 0)
"""
def __set__(self, value):
self.cache_set(value)
def __get__(self):
return self.cache_get()
cpdef cache_size_set(self, int maximum):
elm_store_cache_set(self.st, maximum)
cpdef cache_size_get(self):
return elm_store_cache_get(self.st)
def fs_list_func_set(self, func, *args, **kwargs):
"""Set the function used to deal with listing of items
This function is called per item that is found so it can examine the
item and discard it (return EINA_FALSE to discard, or EINA_TRUE to
accept), and work out some sorting ID (that may be filename or anything
else based on content). This function is always called from a thread.
:param func: The function to be called
"""
if not callable(func):
raise TypeError("func is not callable.")
data = (func, args, kwargs)
Py_INCREF(data)
elm_store_list_func_set(self.st, store_fs_item_list_cb,
<const_void *>data)
def fetch_func_set(self, func, *args, **kwargs):
"""Set the function used to deal with fetching of items
This function is called per item that needs data to be fetched when it
becomes visible and such data is needed. This function is normally run
from a thread (unless elm_store_fetch_thread_set() disables this). The
fetch function is to read data from the source and fill a structure
allocated for this item with fields and then rely on the mapping setup
to tell Store how to take a field in the structure and apply it to a
genlist item.
:param func: The function to be called
"""
if not callable(func):
raise TypeError("func is not callable.")
data = (func, args, kwargs)
Py_INCREF(data)
elm_store_fetch_func_set(self.st, store_item_fetch_cb,
<const_void *>data)
def unfetch_func_set(self, func, *args, **kwargs):
"""Set the function used to free the structure allocated for the item
This function is called per item when it is not needed in memory anymore
and should free the structure allocated in and filled in the function
set by elm_store_fetch_func_set().
:param func: The function to be called
"""
if not callable(func):
raise TypeError("func is not callable.")
data = (func, args, kwargs)
Py_INCREF(data)
elm_store_unfetch_func_set(self.st, store_item_unfetch_cb,
<const_void *>data)
property fetch_thread:
"""Enable or disable fetching in a thread for Store
:type: bool
"""
def __set__(self, value):
self.fetch_thread_set(value)
def __get__(self):
return self.fetch_thread_get()
cpdef fetch_thread_set(self, bint use_thread):
elm_store_fetch_thread_set(self.st, use_thread)
cpdef bint fetch_thread_get(self):
return elm_store_fetch_thread_get(self.st)
property items_sorted:
"""Set if items are to be sorted or not.
By default items are not sorted, but read "in order" as they are found. If
you want to sort, your list function set by elm_store_list_func_set() must
provide a sort ID to sort by, and then Store will take care of sorting when
it inserts items. You should set this up before you begin listing items
in the store and then never change it again.
:type: bool
"""
def __set__(self, value):
self.sorted_set(value)
def __get__(self):
return self.sorted_get()
cpdef sorted_set(self, bint items_sorted):
elm_store_sorted_set(self.st, items_sorted)
cpdef bint sorted_get(self):
return elm_store_sorted_get(self.st)
cdef class StoreItem(object):
cdef Elm_Store_Item *sti
property filesystem_path:
"""Get the path of a specific store item
This returns the full path of a store item. This string is valid only
during the list function set by elm_store_list_func_set() or during the
fetch function set by elm_store_fetch_func_set() or during the unfetch
function set by elm_store_unfetch_func_set().
:param sti: The store item to get the path from
:return: A full path in a string or NULL if none available
"""
def __get__(self):
return self.filesystem_path_get()
cpdef filesystem_path_get(self):
return _ctouni(elm_store_item_filesystem_path_get(self.sti))
property data:
"""Set the item data holding item fields to map to item values in genlist
Once you decode an item, allocate a structure for it and fill the structure,
you should set the item data with this function (eg in the fetch function).
This item pointer is the base offset to use when mapping fields to item
values. Once you unfetch, store will handle NULLing the data pointer for you.
:param sti: The store item to set the data pointer of
:param data: The data pointer to set.
"""
def __set__(self, value):
self.data_set(value)
def __get__(self):
return self.data_get()
cpdef data_set(self, data):
elm_store_item_data_set(self.sti, <void *>data)
cpdef data_get(self):
cdef void *data = elm_store_item_data_get(self.sti)
if data == NULL: return None
return <object>elm_store_item_data_get(self.sti)
property store:
"""Fetch the store than a store item belongs to
This fetches the store object that owns the store item.
:param sti: The store item to query
:return: The store the item belongs to
"""
def __get__(self):
return self.store_get()
cpdef store_get(self):
cdef:
Store ret
Elm_Store *st = <Elm_Store *>elm_store_item_store_get(self.sti)
if st == NULL:
return None
ret = Store.__new__()
ret.st = st
return ret
property genlist_item:
"""Fetch the genlist item that this store item controls
:param sti: The store item to query
:return: The genlist object item handle controlled by this store item
"""
def __get__(self):
return self.genlist_item_get()
cpdef genlist_item_get(self):
return _object_item_to_python(<Elm_Object_Item *>elm_store_item_genlist_item_get(self.sti))

View File

@ -0,0 +1,202 @@
cdef class StoreItemMapping(object):
cdef Elm_Store_Item_Mapping mapping
property mapping_type:
"""What kind of mapping is this
:type: :ref:`Mapping type <Elm_Store_Item_Mapping_Type>`
"""
def __set__(self, value):
self.mapping.type = value
def __get__(self):
return self.mapping.type
property part:
"""What part name in the genlist item is this filling in
:type: unicode
"""
def __set__(self, value):
if isinstance(value, unicode): value = value.encode("UTF-8")
self.mapping.part = strdup(value)
def __get__(self):
return _ctouni(self.mapping.part)
property offset:
"""Offset in memory (in bytes) relative to base of structure for item
data where the data for the mapping lives.
:type: int
"""
def __set__(self, value):
self.mapping.offset = value
def __get__(self):
return self.mapping.offset
cdef class StoreItemMappingIcon(StoreItemMapping):
cdef Elm_Store_Item_Mapping_Icon details
property w:
"""The desired icon size in addition to the file path returned from
the mapping
:type: int
"""
def __set__(self, int value):
self.details.w = value
def __get__(self):
return self.details.w
property h:
"""The desired icon size in addition to the file path returned from
the mapping
:type: int
"""
def __set__(self, int value):
self.details.h = value
def __get__(self):
return self.details.h
property lookup_order:
"""The order in which to find the icon
:type: Elm_Icon_Lookup_Order
"""
def __set__(self, Elm_Icon_Lookup_Order value):
self.details.lookup_order = value
def __get__(self):
return self.details.lookup_order
property standard_name:
"""Use a standard name to find it (EINA_TRUE) or not
:type: bool
"""
def __set__(self, bint value):
self.details.standard_name = value
def __get__(self):
return bool(self.details.standard_name)
property no_scale:
"""EINA_TRUE is you don't want the icon scaled
:type: bool
"""
def __set__(self, bint value):
self.details.no_scale = value
def __get__(self):
return bool(self.details.no_scale)
property smooth:
"""EINA_TRUE if icon is to be smooth scaled
:type: bool
"""
def __set__(self, bint value):
self.details.smooth = value
def __get__(self):
return bool(self.details.smooth)
property scale_up:
"""EINA_TRUE if scaling up is allowed
:type: bool
"""
def __set__(self, bint value):
self.details.scale_up = value
def __get__(self):
return bool(self.details.scale_up)
property scale_down:
"""EINA_TRUE if scaling down is allowed
:type: bool
"""
def __set__(self, bint value):
self.details.scale_down = value
def __get__(self):
return bool(self.details.scale_down)
cdef class StoreItemMappingEmpty(StoreItemMapping):
cdef Elm_Store_Item_Mapping_Empty details
def __cinit__(self):
self.details.dummy = 1
self.mapping.details.empty = self.details
cdef class StoreItemMappingNone(StoreItemMappingEmpty):
def __init__(self, part, data):
if isinstance(part, unicode): part = part.encode("UTF-8")
self.mapping.type = enums.ELM_STORE_ITEM_MAPPING_NONE
self.mapping.part = part
self.mapping.offset = 0
cdef class StoreItemMappingLabel(StoreItemMappingEmpty):
def __init__(self, part, data):
if isinstance(part, unicode): part = part.encode("UTF-8")
self.mapping.type = enums.ELM_STORE_ITEM_MAPPING_LABEL
self.mapping.part = part
self.mapping.offset = 0
cdef class StoreItemMappingState(StoreItemMappingEmpty):
def __init__(self, part, data):
if isinstance(part, unicode): part = part.encode("UTF-8")
self.mapping.type = enums.ELM_STORE_ITEM_MAPPING_STATE
self.mapping.part = part
self.mapping.offset = 0
cdef class StoreItemMappingPhoto(StoreItemMapping):
cdef Elm_Store_Item_Mapping_Photo details
def __init__(self, part, data, size):
if isinstance(part, unicode): part = part.encode("UTF-8")
self.mapping.type = enums.ELM_STORE_ITEM_MAPPING_PHOTO
self.mapping.part = part
self.mapping.offset = 0
self.details.size = size
self.mapping.details.photo = self.details
property size:
"""Photo size to use (see elm_photo_add()) with the given photo path
:type: int
"""
def __set__(self, value):
self.mapping.details.photo.size = value
def __get__(self):
return self.mapping.details.photo.size

View File

@ -0,0 +1,134 @@
#!/usr/bin/env python
# encoding: utf-8
from efl.evas import EVAS_HINT_EXPAND, EVAS_HINT_FILL
from efl import elementary
from efl.elementary.genlist import Genlist, GenlistItemClass, ELM_LIST_COMPRESS
from efl.elementary.store import Store, StoreItemMappingLabel, StoreItemMappingNone
from efl.elementary.box import Box
from efl.elementary.window import StandardWindow
class My_Item(object):
sender = None
subject = None
date = None
head_content = None
# callbacks just to see user interacting with genlist
def st_selected(obj, event_info):
print("selected: %s" % event_info)
def st_double_clicked(obj, event_info):
print("double clicked: %s" % event_info)
def st_longpress(obj, event_info):
print("longpress %s" % event_info)
mapping = [
StoreItemMappingLabel("elm.title.1", 1),
StoreItemMappingLabel("elm.title.2", 2),
StoreItemMappingLabel("elm.text", 3),
StoreItemMappingNone("elm.swallow.icon", 0),
StoreItemMappingNone("elm.swallow.end", 0),
]
def st_store_list(info, *args, **kwargs):
if info.path.endswith("py"):
info.base.item_class = GenlistItemClass(item_style="default")
return True
else:
return False
# char sort_id[7];
# # create a sort id based on the filename itself assuming it is a numeric
# # value like the id number in mh mail folders which is what this test
# # uses as a data source
# file = strrchr(info.path, '/')
# if file: file++
# else file = info.path
# id = atoi(file);
# sort_id[0] = ((id >> 30) & 0x3f) + 32;
# sort_id[1] = ((id >> 24) & 0x3f) + 32;
# sort_id[2] = ((id >> 18) & 0x3f) + 32;
# sort_id[3] = ((id >> 12) & 0x3f) + 32;
# sort_id[4] = ((id >> 6) & 0x3f) + 32;
# sort_id[5] = ((id >> 0) & 0x3f) + 32;
# sort_id[6] = 0;
# info.base.sort_id = strdup(sort_id);
# # choose the item genlist item class to use (only item style should be
# # provided by the app, store will fill everything else in, so it also
# # has to be writable
# info.base.item_class = itc1; # based on item info - return the item class wanted (only style field used - rest reset to internal funcs store sets up to get label/icon etc)
# info.base.mapping = it1_mapping;
# info.base.data = NULL; # if we can already parse and load all of item here and want to - set this
# return True; # return true to include this, false not to
def st_store_fetch(sti, *args, **kwargs):
if sti.data: return
path = sti.filesystem_path
have_content = None
content = []
myit = My_Item()
with open(path, "r", encoding="UTF-8") as f:
for line in f:
if have_content is None:
if line.startswith("From:"):
myit.sender = line[5:]
elif line.startswith("Subject:"):
myit.subject = line[8:]
elif line.startswith("Date:"):
myit.date = line[5:]
elif line == "\n":
have_content = True
else:
content.append(line)
myit.head_content = content #elm_entry_utf8_to_markup(content)
sti.data = myit
def st_store_unfetch(sti, *args, **kwargs):
print("unfetch")
def store_clicked(obj):
win = StandardWindow("store", "Store")
win.autodel = True
if obj is None:
win.callback_delete_request_add(lambda o: elementary.exit())
bx = Box(win)
bx.size_hint_weight = EVAS_HINT_EXPAND, EVAS_HINT_EXPAND
win.resize_object_add(bx)
bx.show()
gl = Genlist(win)
gl.mode = ELM_LIST_COMPRESS
gl.callback_selected_add(st_selected)
gl.callback_clicked_double_add(st_double_clicked)
gl.callback_longpressed_add(st_longpress)
gl.size_hint_weight = EVAS_HINT_EXPAND, EVAS_HINT_EXPAND
gl.size_hint_align = EVAS_HINT_FILL, EVAS_HINT_FILL
bx.pack_end(gl)
gl.show()
itc1 = GenlistItemClass()
itc1.item_style = "message"
st = Store()
st.fs_list_func_set(st_store_list)
st.fetch_func_set(st_store_fetch)
#st.fetch_thread = False
#st.unfetch_func_set(st_store_unfetch)
st.items_sorted = False
st.target_genlist = gl
st.filesystem_directory = "."
win.size = 480, 800
win.show()
if __name__ == "__main__":
elementary.init()
store_clicked(None)
elementary.run()
elementary.shutdown()

View File

@ -200,6 +200,7 @@ else:
Extension("efl.elementary.slider", ["efl/elementary/slider.pyx"]),
Extension("efl.elementary.slideshow", ["efl/elementary/slideshow.pyx"]),
Extension("efl.elementary.spinner", ["efl/elementary/spinner.pyx"]),
#Extension("efl.elementary.store", ["efl/elementary/store.pyx"]),
Extension("efl.elementary.table", ["efl/elementary/table.pyx"]),
Extension("efl.elementary.theme", ["efl/elementary/theme.pyx"]),
Extension("efl.elementary.thumb", ["efl/elementary/thumb.pyx"]),