Initialize Tizen 2.3
[framework/uifw/elementary.git] / src / lib / elm_store.c
1 #include <Elementary.h>
2 #include <Elementary_Cursor.h>
3 #include "elm_priv.h"
4
5 typedef struct _Elm_Store_Filesystem           Elm_Store_Filesystem;
6 typedef struct _Elm_Store_Item_Filesystem      Elm_Store_Item_Filesystem;
7
8 #define ELM_STORE_MAGIC            0x3f89ea56
9 #define ELM_STORE_FILESYSTEM_MAGIC 0x3f89ea57
10 #define ELM_STORE_ITEM_MAGIC       0x5afe8c1d
11
12 struct _Elm_Store
13 {
14    EINA_MAGIC;
15    void           (*free)(Elm_Store *store);
16    struct
17      {
18         void        (*free)(Elm_Store_Item *item);
19      } item;
20    Evas_Object   *genlist;
21    Ecore_Thread  *list_th;
22    Eina_Inlist   *items;
23    Eina_List     *realized;
24    int            realized_count;
25    int            cache_max;
26    struct
27      {
28         struct
29           {
30              Elm_Store_Item_List_Cb     func;
31              void                      *data;
32           } list;
33         struct
34           {
35              Elm_Store_Item_Fetch_Cb    func;
36              void                      *data;
37           } fetch;
38         struct
39           {
40              Elm_Store_Item_Unfetch_Cb  func;
41              void                      *data;
42           } unfetch;
43      } cb;
44    Eina_Bool sorted : 1;
45    Eina_Bool fetch_thread : 1;
46 };
47
48 struct _Elm_Store_Item
49 {
50    EINA_INLIST;
51    EINA_MAGIC;
52    Elm_Store                    *store;
53    Elm_Object_Item              *item;
54    Ecore_Thread                 *fetch_th;
55    Ecore_Job                    *eval_job;
56    const Elm_Store_Item_Mapping *mapping;
57    void                         *data;
58    Eina_Lock                     lock;
59    Eina_Bool                     live : 1;
60    Eina_Bool                     was_live : 1;
61    Eina_Bool                     realized : 1;
62    Eina_Bool                     fetched : 1;
63 };
64
65 struct _Elm_Store_Filesystem
66 {
67    Elm_Store base;
68    EINA_MAGIC;
69    const char *dir;
70 };
71
72 struct _Elm_Store_Item_Filesystem
73 {
74    Elm_Store_Item base;
75    const char *path;
76 };
77
78 static Elm_Genlist_Item_Class _store_item_class;
79
80 static void
81 _store_cache_trim(Elm_Store *st)
82 {
83    while ((st->realized) &&
84           (((int)eina_list_count(st->realized) - st->realized_count)
85            > st->cache_max))
86      {
87         Elm_Store_Item *sti = st->realized->data;
88         if (sti->realized)
89           {
90              st->realized = eina_list_remove_list(st->realized, st->realized);
91              sti->realized = EINA_FALSE;
92           }
93         eina_lock_take(&sti->lock);
94         if (!sti->fetched)
95           {
96              eina_lock_release(&sti->lock);
97              if (sti->fetch_th)
98                {
99                   ecore_thread_cancel(sti->fetch_th);
100                   sti->fetch_th = NULL;
101                }
102              eina_lock_take(&sti->lock);
103           }
104         sti->fetched = EINA_FALSE;
105 //// let fetch/unfetch do the locking
106 //        eina_lock_release(&sti->lock);
107         if (st->cb.unfetch.func)
108           st->cb.unfetch.func(st->cb.unfetch.data, sti);
109 //        eina_lock_take(&sti->lock);
110         sti->data = NULL;
111         eina_lock_release(&sti->lock);
112      }
113 }
114
115 static void
116 _store_genlist_del(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
117 {
118    Elm_Store *st = data;
119    st->genlist = NULL;
120    if (st->list_th)
121      {
122         ecore_thread_cancel(st->list_th);
123         st->list_th = NULL;
124      }
125    st->realized = eina_list_free(st->realized);
126    while (st->items)
127      {
128         Elm_Store_Item *sti = (Elm_Store_Item *)st->items;
129         if (sti->eval_job)
130           {
131              ecore_job_del(sti->eval_job);
132              sti->eval_job = NULL;
133           }
134         if (sti->fetch_th)
135           {
136              ecore_thread_cancel(sti->fetch_th);
137              sti->fetch_th = NULL;
138           }
139         if (sti->store->item.free) sti->store->item.free(sti);
140         eina_lock_take(&sti->lock);
141         if (sti->data)
142           {
143              if (st->cb.unfetch.func)
144                st->cb.unfetch.func(st->cb.unfetch.data, sti);
145              sti->data = NULL;
146           }
147         eina_lock_release(&sti->lock);
148         eina_lock_free(&sti->lock);
149         st->items = NULL;
150         free(sti);
151      }
152    // FIXME: kill threads and more
153 }
154
155 ////// **** WARNING ***********************************************************
156 ////   * This function runs inside a thread outside efl mainloop. Be careful! *
157 //     ************************************************************************
158 /* TODO: refactor lock part into core? this does not depend on filesystm part */
159 static void
160 _store_filesystem_fetch_do(void *data, Ecore_Thread *th __UNUSED__)
161 {
162    Elm_Store_Item *sti = data;
163    eina_lock_take(&sti->lock);
164    if (sti->data)
165      {
166         eina_lock_release(&sti->lock);
167         return;
168      }
169    if (!sti->fetched)
170      {
171 //// let fetch/unfetch do the locking
172 //        eina_lock_release(&sti->lock);
173         if (sti->store->cb.fetch.func)
174           sti->store->cb.fetch.func(sti->store->cb.fetch.data, sti);
175 //        eina_lock_take(&sti->lock);
176         sti->fetched = EINA_TRUE;
177      }
178    eina_lock_release(&sti->lock);
179 }
180 //     ************************************************************************
181 ////   * End of separate thread function.                                     *
182 ////// ************************************************************************
183 /* TODO: refactor lock part into core? this does not depend on filesystm part */
184 static void
185 _store_filesystem_fetch_end(void *data, Ecore_Thread *th)
186 {
187    Elm_Store_Item *sti = data;
188    eina_lock_take(&sti->lock);
189    if (sti->data) elm_genlist_item_update(sti->item);
190    eina_lock_release(&sti->lock);
191    if (th == sti->fetch_th) sti->fetch_th = NULL;
192 }
193
194 /* TODO: refactor lock part into core? this does not depend on filesystm part */
195 static void
196 _store_filesystem_fetch_cancel(void *data, Ecore_Thread *th)
197 {
198    Elm_Store_Item *sti = data;
199    eina_lock_take(&sti->lock);
200    if (th == sti->fetch_th) sti->fetch_th = NULL;
201    if (sti->data) elm_genlist_item_update(sti->item);
202    eina_lock_release(&sti->lock);
203 }
204
205 static void
206 _store_item_eval(void *data)
207 {
208    Elm_Store_Item *sti = data;
209    sti->eval_job = NULL;
210    if (sti->live == sti->was_live) return;
211    sti->was_live = sti->live;
212    if (sti->live)
213      {
214         _store_cache_trim(sti->store);
215         if (sti->realized)
216           sti->store->realized = eina_list_remove(sti->store->realized, sti);
217         sti->store->realized = eina_list_append(sti->store->realized, sti);
218         sti->realized = EINA_TRUE;
219         if ((sti->store->fetch_thread) && (!sti->fetch_th))
220           sti->fetch_th = ecore_thread_run(_store_filesystem_fetch_do,
221                                            _store_filesystem_fetch_end,
222                                            _store_filesystem_fetch_cancel,
223                                            sti);
224         else if ((!sti->store->fetch_thread))
225           {
226              _store_filesystem_fetch_do(sti, NULL);
227              _store_filesystem_fetch_end(sti, NULL);
228           }
229      }
230    else
231      {
232         if (sti->fetch_th)
233           {
234              ecore_thread_cancel(sti->fetch_th);
235              sti->fetch_th = NULL;
236           }
237         _store_cache_trim(sti->store);
238      }
239 }
240
241 static void
242 _store_genlist_item_realized(void *data, Evas_Object *obj __UNUSED__, void *event_info)
243 {
244    Elm_Store *st = data;
245    Elm_Object_Item *gli = event_info;
246    Elm_Store_Item *sti = elm_object_item_data_get(gli);
247    if (!sti) return;
248    st->realized_count++;
249    sti->live = EINA_TRUE;
250    if (sti->eval_job) ecore_job_del(sti->eval_job);
251    sti->eval_job = ecore_job_add(_store_item_eval, sti);
252 }
253
254 static void
255 _store_genlist_item_unrealized(void *data, Evas_Object *obj __UNUSED__, void *event_info)
256 {
257    Elm_Store *st = data;
258    Elm_Object_Item *gli = event_info;
259    Elm_Store_Item *sti = elm_object_item_data_get(gli);
260    if (!sti) return;
261    st->realized_count--;
262    sti->live = EINA_FALSE;
263    if (sti->eval_job) ecore_job_del(sti->eval_job);
264    sti->eval_job = ecore_job_add(_store_item_eval, sti);
265 }
266
267 static const Elm_Store_Item_Mapping *
268 _store_item_mapping_find(Elm_Store_Item *sti, const char *part)
269 {
270    const Elm_Store_Item_Mapping *m;
271
272    for (m = sti->mapping; m; m ++)
273      {
274         if (m->type == ELM_STORE_ITEM_MAPPING_NONE) break;
275         if (!strcmp(part, m->part)) return m;
276      }
277    return NULL;
278 }
279
280 static char *
281 _store_item_text_get(void *data, Evas_Object *obj __UNUSED__, const char *part)
282 {
283    Elm_Store_Item *sti = data;
284    const char *s = "";
285    eina_lock_take(&sti->lock);
286    if (sti->data)
287      {
288         const Elm_Store_Item_Mapping *m = _store_item_mapping_find(sti, part);
289         if (m)
290           {
291              switch (m->type)
292                {
293                 case ELM_STORE_ITEM_MAPPING_LABEL:
294                    s = *(char **)(((unsigned char *)sti->data) + m->offset);
295                    break;
296                 case ELM_STORE_ITEM_MAPPING_CUSTOM:
297                    if (m->details.custom.func)
298                      s = m->details.custom.func(sti->data, sti, part);
299                    break;
300                 default:
301                    break;
302                }
303           }
304      }
305    eina_lock_release(&sti->lock);
306    return s ? strdup(s) : NULL;
307 }
308
309 static Evas_Object *
310 _store_item_content_get(void *data, Evas_Object *obj, const char *part)
311 {
312    Elm_Store_Item *sti = data;
313    eina_lock_take(&sti->lock);
314    if (sti->data)
315      {
316         const Elm_Store_Item_Mapping *m = _store_item_mapping_find(sti, part);
317         if (m)
318           {
319              Evas_Object *ic = NULL;
320              const char *s = NULL;
321
322              switch (m->type)
323                {
324                 case ELM_STORE_ITEM_MAPPING_ICON:
325                    ic = elm_icon_add(obj);
326                    s = *(char **)(((unsigned char *)sti->data) + m->offset);
327                    elm_icon_order_lookup_set(ic, m->details.icon.lookup_order);
328                    evas_object_size_hint_aspect_set(ic,
329                                                     EVAS_ASPECT_CONTROL_VERTICAL,
330                                                     m->details.icon.w,
331                                                     m->details.icon.h);
332                    elm_image_smooth_set(ic, m->details.icon.smooth);
333                    elm_image_no_scale_set(ic, m->details.icon.no_scale);
334                    elm_image_resizable_set(ic,
335                                       m->details.icon.scale_up,
336                                       m->details.icon.scale_down);
337                    if (s)
338                      {
339                         if (m->details.icon.standard_name)
340                           elm_icon_standard_set(ic, s);
341                         else
342                           elm_image_file_set(ic, s, NULL);
343                      }
344                    break;
345                 case ELM_STORE_ITEM_MAPPING_PHOTO:
346                    ic = elm_icon_add(obj);
347                    s = *(char **)(((unsigned char *)sti->data) + m->offset);
348                    elm_photo_size_set(ic, m->details.photo.size);
349                    if (s)
350                      elm_photo_file_set(ic, s);
351                    break;
352                 case ELM_STORE_ITEM_MAPPING_CUSTOM:
353                    if (m->details.custom.func)
354                      ic = m->details.custom.func(sti->data, sti, part);
355                    break;
356                 default:
357                    break;
358                }
359              eina_lock_release(&sti->lock);
360              return ic;
361           }
362      }
363    eina_lock_release(&sti->lock);
364    return NULL;
365 }
366
367 static void
368 _store_item_del(void *data __UNUSED__, Evas_Object *obj __UNUSED__)
369 {
370 }
371
372 ////// **** WARNING ***********************************************************
373 ////   * This function runs inside a thread outside efl mainloop. Be careful! *
374 //     ************************************************************************
375 static int
376 _store_filesystem_sort_cb(void *d1, void *d2)
377 {
378    Elm_Store_Item_Info *info1 = d1, *info2 = d2;
379    if ((!info1->sort_id) || (!info2->sort_id)) return 0;
380    return strcoll(info1->sort_id, info2->sort_id);
381 }
382
383 static void
384 _store_filesystem_list_do(void *data, Ecore_Thread *th __UNUSED__)
385 {
386    Elm_Store_Filesystem *st = data;
387    Eina_Iterator *it;
388    const Eina_File_Direct_Info *finf;
389    Eina_List *sorted = NULL;
390    Elm_Store_Item_Info_Filesystem *info;
391
392    // FIXME: need a way to abstract the open, list, feed items from list
393    // and maybe get initial sortable key vals etc.
394    it = eina_file_stat_ls(st->dir);
395    if (!it) return;
396    EINA_ITERATOR_FOREACH(it, finf)
397      {
398         Eina_Bool ok;
399         size_t pathsz = finf->path_length + 1;
400
401         if (finf->path[finf->name_start] == '.') continue ;
402
403         info = calloc(1, sizeof(Elm_Store_Item_Info_Filesystem) + pathsz);
404         if (!info) continue;
405         info->path = ((char *)info) + sizeof(Elm_Store_Item_Info_Filesystem);
406         memcpy(info->path, finf->path, pathsz);
407         ok = EINA_TRUE;
408         if (st->base.cb.list.func)
409           ok = st->base.cb.list.func(st->base.cb.list.data, &info->base);
410         if (ok)
411           {
412              if (!st->base.sorted) ecore_thread_feedback(th, info);
413              else sorted = eina_list_append(sorted, info);
414           }
415         else
416           {
417              if (info->base.sort_id) free(info->base.sort_id);
418              free(info);
419           }
420         if (ecore_thread_check(th)) break;
421      }
422    eina_iterator_free(it);
423    if (sorted)
424      {
425         sorted = eina_list_sort(sorted, 0,
426                                 EINA_COMPARE_CB(_store_filesystem_sort_cb));
427         EINA_LIST_FREE(sorted, info)
428           {
429              if (!ecore_thread_check(th)) ecore_thread_feedback(th, info);
430           }
431      }
432 }
433 //     ************************************************************************
434 ////   * End of separate thread function.                                     *
435 ////// ************************************************************************
436
437 static void
438 _store_filesystem_list_end(void *data, Ecore_Thread *th)
439 {
440    Elm_Store *st = data;
441    if (th == st->list_th) st->list_th = NULL;
442 }
443
444 static void
445 _store_filesystem_list_cancel(void *data, Ecore_Thread *th)
446 {
447    Elm_Store *st = data;
448    if (th == st->list_th) st->list_th = NULL;
449 }
450
451 static void
452 _store_filesystem_list_update(void *data, Ecore_Thread *th __UNUSED__, void *msg)
453 {
454    Elm_Store *st = data;
455    Elm_Store_Item_Filesystem *sti;
456    Elm_Genlist_Item_Class *itc;
457    Elm_Store_Item_Info_Filesystem *info = msg;
458
459    sti = calloc(1, sizeof(Elm_Store_Item_Filesystem));
460    if (!sti) goto done;
461    eina_lock_new(&sti->base.lock);
462    EINA_MAGIC_SET(&(sti->base), ELM_STORE_ITEM_MAGIC);
463    sti->base.store = st;
464    sti->base.data = info->base.data;
465    sti->base.mapping = info->base.mapping;
466    sti->path = eina_stringshare_add(info->path);
467
468    itc = info->base.item_class;
469    if (!itc) itc = &_store_item_class;
470    else
471      {
472         itc->func.text_get = _store_item_text_get;
473         itc->func.content_get  = _store_item_content_get;
474         itc->func.state_get = NULL; // FIXME: support state gets later
475         itc->func.del       = _store_item_del;
476      }
477
478    // FIXME: handle being a parent (tree)
479    sti->base.item = elm_genlist_item_append(st->genlist, itc,
480                                             sti/* item data */,
481                                             NULL/* parent */,
482                                             ELM_GENLIST_ITEM_NONE,
483                                             NULL/* func */,
484                                             NULL/* func data */);
485    st->items = eina_inlist_append(st->items, (Eina_Inlist *)sti);
486 done:
487    if (info->base.sort_id) free(info->base.sort_id);
488    free(info);
489 }
490
491 // public api calls
492 static Elm_Store *
493 _elm_store_new(size_t size)
494 {
495    Elm_Store *st = calloc(1, size);
496    EINA_SAFETY_ON_NULL_RETURN_VAL(st, NULL);
497
498    // TODO: BEGIN - move to elm_store_init()
499    eina_magic_string_set(ELM_STORE_MAGIC, "Elm_Store");
500    eina_magic_string_set(ELM_STORE_FILESYSTEM_MAGIC, "Elm_Store_Filesystem");
501    eina_magic_string_set(ELM_STORE_ITEM_MAGIC, "Elm_Store_Item");
502    // setup default item class (always the same) if list cb doesnt provide one
503    _store_item_class.item_style = "default";
504    _store_item_class.func.text_get = _store_item_text_get;
505    _store_item_class.func.content_get  = _store_item_content_get;
506    _store_item_class.func.state_get = NULL; // FIXME: support state gets later
507    _store_item_class.func.del       = _store_item_del;
508    // TODO: END - move to elm_store_init()
509
510    EINA_MAGIC_SET(st, ELM_STORE_MAGIC);
511    st->cache_max = 128;
512    st->fetch_thread = EINA_TRUE;
513    return st;
514 }
515 #define elm_store_new(type) (type*)_elm_store_new(sizeof(type))
516
517 static void
518 _elm_store_filesystem_free(Elm_Store *store)
519 {
520    Elm_Store_Filesystem *st = (Elm_Store_Filesystem *)store;
521    eina_stringshare_del(st->dir);
522 }
523
524 static void
525 _elm_store_filesystem_item_free(Elm_Store_Item *item)
526 {
527    Elm_Store_Item_Filesystem *sti = (Elm_Store_Item_Filesystem *)item;
528    eina_stringshare_del(sti->path);
529 }
530
531 EAPI Elm_Store *
532 elm_store_filesystem_new(void)
533 {
534    Elm_Store_Filesystem *st = elm_store_new(Elm_Store_Filesystem);
535    EINA_SAFETY_ON_NULL_RETURN_VAL(st, NULL);
536
537    EINA_MAGIC_SET(st, ELM_STORE_FILESYSTEM_MAGIC);
538    st->base.free = _elm_store_filesystem_free;
539    st->base.item.free = _elm_store_filesystem_item_free;
540
541    return &st->base;
542 }
543
544 EAPI void
545 elm_store_free(Elm_Store *st)
546 {
547    void (*item_free)(Elm_Store_Item *);
548    if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
549    if (st->list_th)
550      {
551         ecore_thread_cancel(st->list_th);
552         st->list_th = NULL;
553      }
554    st->realized = eina_list_free(st->realized);
555    item_free = st->item.free;
556    while (st->items)
557      {
558         Elm_Store_Item *sti = (Elm_Store_Item *)st->items;
559         if (sti->eval_job)
560           {
561              ecore_job_del(sti->eval_job);
562              sti->eval_job = NULL;
563           }
564         if (sti->fetch_th)
565           {
566              ecore_thread_cancel(sti->fetch_th);
567              sti->fetch_th = NULL;
568           }
569         if (item_free) item_free(sti);
570         eina_lock_take(&sti->lock);
571         if (sti->data)
572           {
573              if (st->cb.unfetch.func)
574                st->cb.unfetch.func(st->cb.unfetch.data, sti);
575              sti->data = NULL;
576           }
577         eina_lock_release(&sti->lock);
578         eina_lock_free(&sti->lock);
579         free(sti);
580      }
581    if (st->genlist)
582      {
583         evas_object_event_callback_del_full(st->genlist, EVAS_CALLBACK_DEL, _store_genlist_del, st);
584         evas_object_smart_callback_del(st->genlist, "realized", _store_genlist_item_realized);
585         evas_object_smart_callback_del(st->genlist, "unrealized", _store_genlist_item_unrealized);
586         elm_genlist_clear(st->genlist);
587         st->genlist = NULL;
588      }
589    if (st->free) st->free(st);
590    free(st);
591 }
592
593 EAPI void
594 elm_store_target_genlist_set(Elm_Store *st, Evas_Object *obj)
595 {
596    if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
597    if (st->genlist == obj) return;
598    if (st->genlist)
599      {
600         evas_object_event_callback_del_full(st->genlist, EVAS_CALLBACK_DEL, _store_genlist_del, st);
601         evas_object_smart_callback_del(st->genlist, "realized", _store_genlist_item_realized);
602         evas_object_smart_callback_del(st->genlist, "unrealized", _store_genlist_item_unrealized);
603         elm_genlist_clear(st->genlist);
604      }
605    st->genlist = obj;
606    if (!st->genlist) return;
607    evas_object_smart_callback_add(st->genlist, "realized", _store_genlist_item_realized, st);
608    evas_object_smart_callback_add(st->genlist, "unrealized", _store_genlist_item_unrealized, st);
609    evas_object_event_callback_add(st->genlist, EVAS_CALLBACK_DEL, _store_genlist_del, st);
610    elm_genlist_clear(st->genlist);
611 }
612
613 EAPI void
614 elm_store_filesystem_directory_set(Elm_Store *store, const char *dir)
615 {
616    Elm_Store_Filesystem *st = (Elm_Store_Filesystem *)store;
617    if (!EINA_MAGIC_CHECK(store, ELM_STORE_MAGIC)) return;
618    if (!EINA_MAGIC_CHECK(st, ELM_STORE_FILESYSTEM_MAGIC)) return;
619    if (store->list_th)
620      {
621         ecore_thread_cancel(store->list_th);
622         store->list_th = NULL;
623      }
624    if (!eina_stringshare_replace(&st->dir, dir)) return;
625    store->list_th = ecore_thread_feedback_run(_store_filesystem_list_do,
626                                               _store_filesystem_list_update,
627                                               _store_filesystem_list_end,
628                                               _store_filesystem_list_cancel,
629                                               st, EINA_TRUE);
630 }
631
632 EAPI const char *
633 elm_store_filesystem_directory_get(const Elm_Store *store)
634 {
635    const Elm_Store_Filesystem *st = (const Elm_Store_Filesystem *)store;
636    if (!EINA_MAGIC_CHECK(store, ELM_STORE_MAGIC)) return NULL;
637    if (!EINA_MAGIC_CHECK(st, ELM_STORE_FILESYSTEM_MAGIC)) return NULL;
638    return st->dir;
639 }
640
641 EAPI void
642 elm_store_cache_set(Elm_Store *st, int max)
643 {
644    if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
645    if (max < 0) max = 0;
646    st->cache_max = max;
647    _store_cache_trim(st);
648 }
649
650 EAPI int
651 elm_store_cache_get(const Elm_Store *st)
652 {
653    if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return 0;
654    return st->cache_max;
655 }
656
657 EAPI void
658 elm_store_list_func_set(Elm_Store *st, Elm_Store_Item_List_Cb func, const void *data)
659 {
660    if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
661    st->cb.list.func = func;
662    st->cb.list.data = (void *)data;
663 }
664
665 EAPI void
666 elm_store_fetch_func_set(Elm_Store *st, Elm_Store_Item_Fetch_Cb func, const void *data)
667 {
668    if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
669    st->cb.fetch.func = func;
670    st->cb.fetch.data = (void *)data;
671 }
672
673 EAPI void
674 elm_store_fetch_thread_set(Elm_Store *st, Eina_Bool use_thread)
675 {
676    if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
677    st->fetch_thread = !!use_thread;
678 }
679
680 EAPI Eina_Bool
681 elm_store_fetch_thread_get(const Elm_Store *st)
682 {
683    if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return EINA_FALSE;
684    return st->fetch_thread;
685 }
686
687 EAPI void
688 elm_store_unfetch_func_set(Elm_Store *st, Elm_Store_Item_Unfetch_Cb func, const void *data)
689 {
690    if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
691    st->cb.unfetch.func = func;
692    st->cb.unfetch.data = (void *)data;
693 }
694
695 EAPI void
696 elm_store_sorted_set(Elm_Store *st, Eina_Bool sorted)
697 {
698    if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
699    st->sorted = sorted;
700 }
701
702 EAPI Eina_Bool
703 elm_store_sorted_get(const Elm_Store *st)
704 {
705    if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return EINA_FALSE;
706    return st->sorted;
707 }
708
709 EAPI void
710 elm_store_item_data_set(Elm_Store_Item *sti, void *data)
711 {
712    if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return;
713 //// let fetch/unfetch do the locking
714 //   eina_lock_take(&sti->lock);
715    sti->data = data;
716 //   eina_lock_release(&sti->lock);
717 }
718
719 EAPI void *
720 elm_store_item_data_get(Elm_Store_Item *sti)
721 {
722    if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return NULL;
723    void *d;
724 //// let fetch/unfetch do the locking
725 //   eina_lock_take(&sti->lock);
726    d = sti->data;
727 //   eina_lock_release(&sti->lock);
728    return d;
729 }
730
731 EAPI const Elm_Store *
732 elm_store_item_store_get(const Elm_Store_Item *sti)
733 {
734    if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return NULL;
735    // dont need lock
736    return sti->store;
737 }
738
739 EAPI const Elm_Object_Item *
740 elm_store_item_genlist_item_get(const Elm_Store_Item *sti)
741 {
742    if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return NULL;
743    // dont need lock
744    return sti->item;
745 }
746
747 EAPI const char *
748 elm_store_item_filesystem_path_get(const Elm_Store_Item *item)
749 {
750    Elm_Store_Item_Filesystem *sti = (Elm_Store_Item_Filesystem *)item;
751    Elm_Store_Filesystem *st;
752    if (!EINA_MAGIC_CHECK(item, ELM_STORE_ITEM_MAGIC)) return NULL;
753    if (!EINA_MAGIC_CHECK(item->store, ELM_STORE_MAGIC)) return NULL;
754    /* ensure we're dealing with filesystem item */
755    st = (Elm_Store_Filesystem *)item->store;
756    if (!EINA_MAGIC_CHECK(st, ELM_STORE_FILESYSTEM_MAGIC)) return NULL;
757    // dont need lock
758    return sti->path;
759 }