1 /**
2  * @defgroup Store Elementary Store
3  * @ingroup Elementary
4  *
5  * Store is an abstracting API that is intended to farm off fetching of data
6  * to threads running asynchronously from the mainloop that actually fetch
7  * data needed for a genlist (or possibly future other widgets) so scrolling
8  * never blocks waiting on IO (though normally this should be the users
9  * job - if using genlist, to ensure all data genlist needs is in memory at
10  * the time it needs it, and if it isn't to queue and defer a fetch and let
11  * genlist know later when its ready. Store actually does this and implements
12  * the infrastructure of this, leaving the actual fetch and convert up to
13  * functions provided by the user).
14  *
15  * It is possible for store to run inline without a thread, but this is
16  * highly inadvisable. you can disable this with:
17  *
18  * elm_store_fetch_thread_set(store, EINA_FALSE);
19  *
20  * Store works first by creating a store, setting up functions to list items
21  * and fetch items. Currently the only store type supported is the
22  * filesystem store, which will list the files inside a directory (not
23  * recursively) and then hand each file it finds (the file path) to the
24  * list function for evaluation.
25  *
26  * The list function may look at filename, may open the file or do
27  * anything it likes to determine something about the file. Either it
28  * filters it out (returns @c EINA_FALSE) and it is discarded or it
29  * returns @c EINA_TRUE and also provides a "sort id" which is a string
30  * store uses to figure out sorting. This string could be the filename, or
31  * some data based on its contents. The strings are sorted alphabetically
32  * like any normal ASCII strings, with case being important. As this listing
33  * function runs in a thread, it can do blocking IO and parsing without
34  * hurting the fluidity of the main loop and GUI. The list function also
35  * returns information on how to map fields in the source file to elements
36  * of the genlist item. For example, how the fetcher reads the private
37  * data struct of the user (what memory offset in the struct the data is at)
38  * and what type is there (it's a label of some sort, an icon, or with a
39  * custom mapping function that figures it out itself and creates the
40  * content needed for the genlist item).
41  *
42  * Store then uses this sort id to build (over time) a sorted list of items
43  * that then map 1:1 to genlist items. When these items are visible and
44  * need content, Store calls the fetch function per item, which is responsible
45  * for fetching the data from the given item and returning data to store
46  * so it can map this to some item content. This function also runs in a
47  * thread, and thus can do blocking IO work to later return the data. Sorting
48  * is optional and can be enabled or disabled too.
49  *
50  * When items are no longer needed, store will cal the unfetch function to
51  * free data in memory about that item that is no longer needed. This function
52  * is called in the mainloop and is expected to take minimal or almost no time
53  * to simply free up memory resources.
54  *
55  * @{
56  */
57 
58 typedef struct _Elm_Store                      Elm_Store; /**< A store object */
59 typedef struct _Elm_Store_Item                 Elm_Store_Item; /**< A handle of a store item passed to store fetch/unfetch functions */
60 typedef struct _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 */
61 typedef struct _Elm_Store_Item_Info_Filesystem Elm_Store_Item_Info_Filesystem; /**< Filesystem specific information about a store item */
62 typedef struct _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 */
63 typedef struct _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 */
64 typedef struct _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 */
65 typedef struct _Elm_Store_Item_Mapping_Photo   Elm_Store_Item_Mapping_Photo; /**< The data is a photo, so use these parameters to find it */
66 typedef struct _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. */
67 
68 typedef Eina_Bool                            (*Elm_Store_Item_List_Cb)(void *data, Elm_Store_Item_Info *info); /**< Function to call for listing an item */
69 typedef void                                 (*Elm_Store_Item_Fetch_Cb)(void *data, Elm_Store_Item *sti); /**< Function to call to fetch item data */
70 typedef void                                 (*Elm_Store_Item_Unfetch_Cb)(void *data, Elm_Store_Item *sti); /**< Function to cal lto un-fetch (free) an item */
71 typedef void                                *(*Elm_Store_Item_Mapping_Cb)(void *data, Elm_Store_Item *sti, const char *part); /**< Custom mapping function to call */
72 
73 /**
74  * Possible mappings types.
75  * @since 1.7
76  */
77 typedef enum
78 {
79    ELM_STORE_ITEM_MAPPING_NONE = 0,
80    ELM_STORE_ITEM_MAPPING_LABEL, /**< const char * -> label */
81    ELM_STORE_ITEM_MAPPING_STATE, /**< Eina_Bool -> state */
82    ELM_STORE_ITEM_MAPPING_ICON, /**< char * -> icon path */
83    ELM_STORE_ITEM_MAPPING_PHOTO, /**< char * -> photo path */
84    ELM_STORE_ITEM_MAPPING_CUSTOM, /**< item->custom(it->data, it, part) -> void * (-> any) */
85    ELM_STORE_ITEM_MAPPING_LAST, /** canary value: any value greater or equal to ELM_STORE_ITEM_MAPPING_LAST is forbidden. */
86 } Elm_Store_Item_Mapping_Type;
87 
88 struct _Elm_Store_Item_Mapping_Icon
89 {
90    int                   w, h; /**< The desired icon size in addition to the file path returned from the mapping */
91    Elm_Icon_Lookup_Order lookup_order; /**< The order in which to find the icon */
92    Eina_Bool             standard_name : 1; /**< Use a standard name to find it (@c EINA_TRUE) or not */
93    Eina_Bool             no_scale : 1; /**< @c EINA_TRUE is you don't want the icon scaled */
94    Eina_Bool             smooth : 1; /**< @c EINA_TRUE if icon is to be smooth scaled */
95    Eina_Bool             scale_up : 1; /**< @c EINA_TRUE if scaling up is allowed */
96    Eina_Bool             scale_down : 1; /**< @c EINA_TRUE if scaling down is allowed */
97 };
98 
99 struct _Elm_Store_Item_Mapping_Empty
100 {
101    Eina_Bool dummy; /**< dummy entry - set to anything you like */
102 };
103 
104 struct _Elm_Store_Item_Mapping_Photo
105 {
106    int size; /**< Photo size to use (see elm_photo_add()) with the given photo path */
107 };
108 
109 struct _Elm_Store_Item_Mapping_Custom
110 {
111    Elm_Store_Item_Mapping_Cb func; /**< The function called to do the custom mapping and return it */
112 };
113 
114 struct _Elm_Store_Item_Mapping
115 {
116    Elm_Store_Item_Mapping_Type type; /**< what kind of mapping is this */
117    const char                 *part; /**< what part name in the genlist item is this filling in */
118    int                         offset; /**< offset in memory (in bytes) relative to base of structure for item data where the data for the mapping lives */
119    union
120    {
121       Elm_Store_Item_Mapping_Empty  empty;
122       Elm_Store_Item_Mapping_Icon   icon;
123       Elm_Store_Item_Mapping_Photo  photo;
124       Elm_Store_Item_Mapping_Custom custom;
125       // add more types here
126    } details; /**< Allowed to be one of these possible mapping types */
127 };
128 
129 struct _Elm_Store_Item_Info
130 {
131    Elm_Genlist_Item_Class       *item_class; /**< The genlist item class that should be used for the item that has been listed */
132    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 */
133    void                         *data; /**< Pointer to pass to struct data in memory if its already there, of not, NULL */
134    char                         *sort_id; /**< Sort ID string (strduped()) to know how to wort items, or NULL, if you don't care */
135 };
136 
137 struct _Elm_Store_Item_Info_Filesystem
138 {
139    Elm_Store_Item_Info base; /**< Base information about an item */
140    char               *path; /**< Extra information specific to the filesystem store */
141 };
142 
143 #define ELM_STORE_ITEM_MAPPING_END { ELM_STORE_ITEM_MAPPING_NONE, NULL, 0, { .empty = { EINA_TRUE } } } /**< Use this to end a list of mappings */
144 #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 */
145 
146 /**
147  * Create a new store object
148  *
149  * This creates a new store object to then configure so it works.
150  *
151  * @return A new store object, or NULL if creation fails
152  *
153  * @ingroup Store
154  */
155 EAPI Elm_Store              *elm_store_filesystem_new(void);
156 /**
157  * Free the store object and all items it manages
158  *
159  * This frees the given @p st store and all the items it manages. It will
160  * clear the List that it populated, but otherwise leave it alone. It will
161  * cancel background threads (and may have to wait for them to complete a
162  * pending operation to do this).
163  *
164  * @param st The store to free
165  *
166  * @ingroup Store
167  */
168 EAPI void                    elm_store_free(Elm_Store *st);
169 
170 /**
171  * Set the path to the directory to scan for a filesystem store
172  *
173  * This sets the directory (@p dir) to scan and begins scanning in the
174  * the background in threads (or not if threading is disabled with
175  * elm_store_fetch_thread_set()). Note that Listing is always done in a thread
176  * but fetching may not be if disabled here. This should be the last thing
177  * called after fetch, list and unfetch functions are set, as well as target
178  * genlist etc. You also should not change the directory once set. If you
179  * need a new directory scanned, create a new store.
180  *
181  * @param st The store to modify
182  * @param dir A string giving the path to the directory to scan
183  *
184  * @ingroup Store
185  */
186 EAPI void                    elm_store_filesystem_directory_set(Elm_Store *st, const char *dir);
187 
188 /**
189  * Get the directory set on a filesystem store
190  *
191  * This gets the directory set by elm_store_filesystem_directory_set(). This
192  * string returned will be valid until elm_store_filesystem_directory_set()
193  * changes it or until the store is freed with elm_store_free().
194  *
195  * @return A string with the path set, or NULL if none set.
196  *
197  * @ingroup Store
198  */
199 EAPI const char             *elm_store_filesystem_directory_get(const Elm_Store *st);
200 
201 /**
202  * Get the path of a specific store item
203  *
204  * This returns the full path of a store item. This string is valid only
205  * during the list function set by elm_store_list_func_set() or during the
206  * fetch function set by elm_store_fetch_func_set() or during the unfetch
207  * function set by elm_store_unfetch_func_set().
208  *
209  * @param sti The store item to get the path from
210  * @return A full path in a string or NULL if none available
211  *
212  * @ingroup Store
213  */
214 EAPI const char             *elm_store_item_filesystem_path_get(const Elm_Store_Item *sti);
215 
216 /**
217  * Set the target genlist to fill in from the store
218  *
219  * This tells the store the target genlist to use to fill in content from
220  * the store. Once a store starts "going" via elm_store_filesystem_directory_set()
221  * The target should never be changed again.
222  *
223  * @param st The store to do the filling.
224  * @param obj The genlist object to fill in and control the content of from the store.
225  *
226  * @ingroup Store
227  */
228 EAPI void                    elm_store_target_genlist_set(Elm_Store *st, Evas_Object *obj);
229 
230 /**
231  * Set the maximum number of items that are not visible to keep cached
232  *
233  * Store may keep some items around for caching purposes that cannot be seen,
234  * so this controls the maximum number. The default is 128, but may change
235  * at any point in time in the future.
236  *
237  * @param st The store to modify
238  * @param max The number of items to keep (should be greater than or equal to 0)
239  *
240  * @ingroup Store
241  */
242 EAPI void                    elm_store_cache_set(Elm_Store *st, int max);
243 
244 /**
245  * Get the maximum number if items to cache
246  *
247  * This returns the number of items at most to cache.
248  *
249  * @param st The store to query
250  * @return The maximum number of items to cache (>= 0)
251  * @see elm_store_cache_set()
252  *
253  * @ingroup Store
254  */
255 EAPI int                     elm_store_cache_get(const Elm_Store *st);
256 
257 /**
258  * Set the function used to deal with listing of items
259  *
260  * This function is called per item that is found so it can examine the item
261  * and discard it (return @c EINA_FALSE to discard, or @c EINA_TRUE to accept),
262  * and work out some sorting ID (that may be filename or anything else based on
263  * content). This function is always called from a thread.
264  *
265  * @param st The store to set the function of
266  * @param func The function to be called
267  * @param data the data pointer to be passed to the @p func function when called
268  *
269  * @ingroup Store
270  */
271 EAPI void                    elm_store_list_func_set(Elm_Store *st, Elm_Store_Item_List_Cb func, const void *data);
272 
273 /**
274  * Set the function used to deal with fetching of items
275  *
276  * This function is called per item that needs data to be fetched when it
277  * becomes visible and such data is needed. This function is normally run
278  * from a thread (unless elm_store_fetch_thread_set() disables this). The
279  * fetch function is to read data from the source and fill a structure
280  * allocated for this item with fields and then rely on the mapping setup
281  * to tell Store how to take a field in the structure and apply it to a
282  * genlist item.
283  *
284  * @param st The store to set the function of
285  * @param func The function to be called
286  * @param data the data pointer to be passed to the @p func function when called
287  *
288  * @ingroup Store
289  */
290 EAPI void                    elm_store_fetch_func_set(Elm_Store *st, Elm_Store_Item_Fetch_Cb func, const void *data);
291 
292 /**
293  * Set the function used to free the structure allocated for the item
294  *
295  * This function is called per item when it is not needed in memory anymore
296  * and should free the structure allocated in and filled in the function set
297  * by elm_store_fetch_func_set().
298  *
299  * @param st The store to set the function of
300  * @param func The function to be called
301  * @param data the data pointer to be passed to the @p func function when called
302  *
303  * @ingroup Store
304  */
305 EAPI void                    elm_store_unfetch_func_set(Elm_Store *st, Elm_Store_Item_Unfetch_Cb func, const void *data);
306 
307 /**
308  * Enable or disable fetching in a thread for Store
309  *
310  * @param st The store to modify
311  * @param use_thread @c EINA_TRUE to use a thread to fetch, @c EINA_FALSE don't
312  * use a thread.
313  *
314  * @ingroup Store
315  */
316 EAPI void                    elm_store_fetch_thread_set(Elm_Store *st, Eina_Bool use_thread);
317 
318 /**
319  * Get the thread enabled fetching option for Store
320  *
321  * @return The state set currently for the store.
322  * @see elm_store_fetch_thread_set()
323  *
324  * @ingroup Store
325  */
326 EAPI Eina_Bool               elm_store_fetch_thread_get(const Elm_Store *st);
327 
328 /**
329  * Set if items are to be sorted or not.
330  *
331  * By default items are not sorted, but read "in order" as they are found. If
332  * you want to sort, your list function set by elm_store_list_func_set() must
333  * provide a sort ID to sort by, and then Store will take care of sorting when
334  * it inserts items. You should set this up before you begin listing items
335  * in the store and then never change it again.
336  *
337  * @param st The store to modify
338  * @param sorted @c EINA_TRUE if we are to sort, @c EINA_FALSE if not.
339  *
340  * @ingroup Store
341  */
342 EAPI void                    elm_store_sorted_set(Elm_Store *st, Eina_Bool sorted);
343 
344 /**
345  * Get the sorting flag
346  *
347  * Get the sorted flag as set by elm_store_sorted_set().
348  *
349  * @param st The store to query
350  * @return @c EINA_TRUE if sorted, @c EINA_FALSE if not.
351  *
352  * @ingroup Store
353  */
354 EAPI Eina_Bool               elm_store_sorted_get(const Elm_Store *st);
355 
356 /**
357  * Set the item data holding item fields to map to item values in genlist
358  *
359  * Once you decode an item, allocate a structure for it and fill the structure,
360  * you should set the item data with this function (eg in the fetch function).
361  * This item pointer is the base offset to use when mapping fields to item
362  * values. Once you unfetch, store will handle NULLing the data pointer for you.
363  *
364  * @param sti The store item to set the data pointer of
365  * @param data The data pointer to set.
366  *
367  * @ingroup Store
368  */
369 EAPI void                    elm_store_item_data_set(Elm_Store_Item *sti, void *data);
370 
371 /**
372  * Get the item data
373  *
374  * This gets the data pointer set by elm_store_item_data_set().
375  *
376  * @param sti The store item to query
377  * @return The data pointer set on the item
378  *
379  * @ingroup Store
380  */
381 EAPI void                   *elm_store_item_data_get(Elm_Store_Item *sti);
382 
383 /**
384  * Fetch the store than a store item belongs to
385  *
386  * This fetches the store object that owns the store item.
387  *
388  * @param sti The store item to query
389  * @return The store the item belongs to
390  *
391  * @ingroup Store
392  */
393 EAPI const Elm_Store        *elm_store_item_store_get(const Elm_Store_Item *sti);
394 
395 /**
396  * Fetch the genlist item that this store item controls
397  *
398  * @param sti The store item to query
399  * @return The genlist object item handle controlled by this store item
400  *
401  * @ingroup Store
402  */
403 EAPI const Elm_Object_Item *elm_store_item_genlist_item_get(const Elm_Store_Item *sti);
404 
405 /**
406  * @}
407  */
408