Merge "els_icon/elm_image - added features to aspect_ratio changeable"
[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 #ifndef EFL_HAVE_THREADS
6 # error "No thread support. Required."
7 #endif
8
9 #ifdef EFL_HAVE_POSIX_THREADS
10 # include <pthread.h>
11 # define LK(x)  pthread_mutex_t x
12 # define LKI(x) pthread_mutex_init(&(x), NULL);
13 # define LKD(x) pthread_mutex_destroy(&(x));
14 # define LKL(x) pthread_mutex_lock(&(x));
15 # define LKU(x) pthread_mutex_unlock(&(x));
16 #else /* EFL_HAVE_WIN32_THREADS */
17 # define WIN32_LEAN_AND_MEAN
18 # include <windows.h>
19 # undef WIN32_LEAN_AND_MEAN
20 # define LK(x)  HANDLE x
21 # define LKI(x) x = CreateMutex(NULL, FALSE, NULL)
22 # define LKD(x) CloseHandle(x)
23 # define LKL(x) WaitForSingleObject(x, INFINITE)
24 # define LKU(x) ReleaseMutex(x)
25 #endif
26
27 #define ELM_STORE_MAGIC            0x3f89ea56
28 #define ELM_STORE_FILESYSTEM_MAGIC 0x3f89ea57
29 #define ELM_STORE_DBSYSTEM_MAGIC   0x3f89ea58
30 #define ELM_STORE_ITEM_MAGIC       0x5afe8c1d
31 #define CACHE_COUNT                127
32 #define SCREEN_ITEM_COUNT    10
33
34 struct _Elm_Store
35 {
36    EINA_MAGIC;
37    void         (*free)(Elm_Store *store);
38    struct {
39         void        (*free)(Elm_Store_Item *item);
40    } item;
41    Evas_Object   *genlist;
42    Ecore_Thread  *list_th;
43    Eina_Inlist   *items;
44    Eina_List     *realized;
45    int            realized_count;
46    int            cache_max;
47    int            start_fetch_index;
48    int            end_fetch_index;
49    int            item_count;
50    int            total_item_count;
51    int            block_count;
52    int            type;
53    Eina_List     *header_items;
54    struct {
55         struct {
56              Elm_Store_Item_List_Cb     func;
57              void                      *data;
58         } list;
59         struct {
60              Elm_Store_Item_Fetch_Cb    func;
61              void                      *data;
62         } fetch;
63         struct {
64              Elm_Store_Item_Unfetch_Cb  func;
65              void                      *data;
66         } unfetch;
67         struct {
68              Elm_Store_Item_Select_Cb func;
69              void                    *data;
70         } item_select;
71         struct {
72              Elm_Store_Item_Sort_Cb func;
73              void                  *data;
74         } item_sort;
75         struct {
76              Elm_Store_Item_Free_Cb func;
77              void                  *data;
78         } item_free;
79    } cb;
80    Eina_Bool      sorted : 1;
81    Eina_Bool      fetch_thread : 1;
82    Eina_Bool      multi_load : 1;
83    Eina_Bool      live : 1;
84 };
85
86 struct _Elm_Store_Item
87 {
88    EINA_INLIST;
89    EINA_MAGIC;
90    Elm_Store                    *store;
91    Elm_Genlist_Item             *item;
92    Ecore_Thread                 *fetch_th;
93    Ecore_Job                    *eval_job;
94    const Elm_Store_Item_Mapping *mapping;
95    void                         *data;
96    Elm_Store_Item_Info          *item_info;
97    LK(lock);
98    Eina_Bool                     live : 1;
99    Eina_Bool                     was_live : 1;
100    Eina_Bool                     realized : 1;
101    Eina_Bool                     fetched : 1;
102 };
103
104 struct _Elm_Store_Filesystem
105 {
106    Elm_Store   base;
107    EINA_MAGIC;
108    const char *dir;
109 };
110
111 struct _Elm_Store_Item_Filesystem
112 {
113    Elm_Store_Item base;
114    const char    *path;
115 };
116
117 struct _Elm_Store_DBsystem
118 {
119    Elm_Store   base;
120    EINA_MAGIC;
121    void       *p_db;
122 };
123
124 typedef enum
125 {
126    ELM_STORE_ITEM_SORT_LOW = -1,
127    ELM_STORE_ITEM_SORT_SAME = 0,
128    ELM_STORE_ITEM_SORT_HIGH = 1,
129    ELM_STORE_ITEM_SORT_UNKNOWN = 2,
130    ELM_STORE_ITEM_SORT_LAST
131 } Elm_Store_Item_Sort_Type;
132
133 static Elm_Genlist_Item_Class _store_item_class;
134
135 static char *_item_label_get(void *data, Evas_Object *obj __UNUSED__, const char *part);
136 static Evas_Object *_item_icon_get(void *data, Evas_Object *obj, const char *part);
137 static void _item_del(void *data __UNUSED__, Evas_Object *obj __UNUSED__);
138 static void _store_free(Elm_Store *st);
139 static void _item_free(Elm_Store_Item *sti);
140 static void _item_realized(void *data, Evas_Object *obj __UNUSED__, void *event_info);
141 static void _item_unrealized(void *data, Evas_Object *obj __UNUSED__, void *event_info);
142 static void _genlist_del(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__);
143 static Elm_Store_Item *_item_unfetch(Elm_Store *st, int index);
144
145 static void
146 _store_cache_trim(Elm_Store *st)
147 {
148    while ((st->realized ) &&
149           (((int)eina_list_count(st->realized) - st->realized_count)
150            > st->cache_max))
151      {
152         Elm_Store_Item *sti = st->realized->data;
153         if (sti->realized)
154           {
155              st->realized = eina_list_remove_list(st->realized, st->realized);
156              sti->realized = EINA_FALSE;
157           }
158         LKL(sti->lock);
159         if (!sti->fetched)
160           {
161              LKU(sti->lock);
162              if (sti->fetch_th)
163                {
164                   ecore_thread_cancel(sti->fetch_th);
165                   sti->fetch_th = NULL;
166                }
167              LKL(sti->lock);
168           }
169         sti->fetched = EINA_FALSE;
170         LKU(sti->lock);
171         if (st->cb.unfetch.func)
172           st->cb.unfetch.func(st->cb.unfetch.data, sti, NULL);
173         LKL(sti->lock);
174         sti->data = NULL;
175         LKU(sti->lock);
176      }
177 }
178
179 static void
180 _store_genlist_del(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
181 {
182    Elm_Store *st = data;
183    st->genlist = NULL;
184    if (st->list_th)
185      {
186         ecore_thread_cancel(st->list_th);
187         st->list_th = NULL;
188      }
189    eina_list_free(st->realized);
190    while (st->items)
191      {
192         Elm_Store_Item *sti = (Elm_Store_Item *)st->items;
193         if (sti->eval_job) ecore_job_del(sti->eval_job);
194         if (sti->fetch_th)
195           {
196              ecore_thread_cancel(sti->fetch_th);
197              sti->fetch_th = NULL;
198           }
199         if (sti->store->item.free) sti->store->item.free(sti);
200         if (sti->data)
201           {
202              if (st->cb.unfetch.func)
203                st->cb.unfetch.func(st->cb.unfetch.data, sti, NULL);
204              sti->data = NULL;
205           }
206         LKD(sti->lock);
207         free(sti);
208      }
209    // FIXME: kill threads and more
210 }
211
212 ////// **** WARNING ***********************************************************
213 ////   * This function runs inside a thread outside efl mainloop. Be careful! *
214 //     ************************************************************************
215 /* TODO: refactor lock part into core? this does not depend on filesystm part */
216 static void
217 _store_filesystem_fetch_do(void *data, Ecore_Thread *th __UNUSED__)
218 {
219    Elm_Store_Item *sti = data;
220    LKL(sti->lock);
221    if (sti->data)
222      {
223         LKU(sti->lock);
224         return;
225      }
226    if (!sti->fetched)
227      {
228         LKU(sti->lock);
229         if (sti->store->cb.fetch.func)
230           sti->store->cb.fetch.func(sti->store->cb.fetch.data, sti, NULL);
231         LKL(sti->lock);
232         sti->fetched = EINA_TRUE;
233      }
234    LKU(sti->lock);
235 }
236 //     ************************************************************************
237 ////   * End of separate thread function.                                     *
238 ////// ************************************************************************
239 /* TODO: refactor lock part into core? this does not depend on filesystm part */
240 static void
241 _store_filesystem_fetch_end(void *data, Ecore_Thread *th)
242 {
243    Elm_Store_Item *sti = data;
244    LKL(sti->lock);
245    if (sti->data) elm_genlist_item_update(sti->item);
246    LKU(sti->lock);
247    if (th == sti->fetch_th) sti->fetch_th = NULL;
248 }
249
250 /* TODO: refactor lock part into core? this does not depend on filesystm part */
251 static void
252 _store_filesystem_fetch_cancel(void *data, Ecore_Thread *th)
253 {
254    Elm_Store_Item *sti = data;
255    LKL(sti->lock);
256    if (th == sti->fetch_th) sti->fetch_th = NULL;
257    if (sti->data) elm_genlist_item_update(sti->item);
258    LKU(sti->lock);
259 }
260
261 static void
262 _store_item_eval(void *data)
263 {
264    Elm_Store_Item *sti = data;
265    sti->eval_job = NULL;
266    if (sti->live == sti->was_live) return;
267    sti->was_live = sti->live;
268    if (sti->live)
269      {
270         _store_cache_trim(sti->store);
271         if (sti->realized)
272           sti->store->realized = eina_list_remove(sti->store->realized, sti);
273         sti->store->realized = eina_list_append(sti->store->realized, sti);
274         sti->realized = EINA_TRUE;
275         if ((sti->store->fetch_thread) && (!sti->fetch_th))
276           sti->fetch_th = ecore_thread_run(_store_filesystem_fetch_do,
277                                            _store_filesystem_fetch_end,
278                                            _store_filesystem_fetch_cancel,
279                                            sti);
280         else if ((!sti->store->fetch_thread))
281           {
282              _store_filesystem_fetch_do(sti, NULL);
283              _store_filesystem_fetch_end(sti, NULL);
284           }
285      }
286    else
287      {
288         if (sti->fetch_th)
289           {
290              ecore_thread_cancel(sti->fetch_th);
291              sti->fetch_th = NULL;
292           }
293         _store_cache_trim(sti->store);
294      }
295 }
296
297 static void
298 _store_genlist_item_realized(void *data, Evas_Object *obj __UNUSED__, void *event_info)
299 {
300    Elm_Store *st = data;
301    Elm_Genlist_Item *gli = event_info;
302    Elm_Store_Item *sti = elm_genlist_item_data_get(gli);
303    if (!sti) return;
304    st->realized_count++;
305    sti->live = EINA_TRUE;
306    if (sti->eval_job) ecore_job_del(sti->eval_job);
307    sti->eval_job = ecore_job_add(_store_item_eval, sti);
308 }
309
310 static void
311 _store_genlist_item_unrealized(void *data, Evas_Object *obj __UNUSED__, void *event_info)
312 {
313    Elm_Store *st = data;
314    Elm_Genlist_Item *gli = event_info;
315    Elm_Store_Item *sti = elm_genlist_item_data_get(gli);
316    if (!sti) return;
317    st->realized_count--;
318    sti->live = EINA_FALSE;
319    if (sti->eval_job) ecore_job_del(sti->eval_job);
320    sti->eval_job = ecore_job_add(_store_item_eval, sti);
321 }
322
323 static const Elm_Store_Item_Mapping *
324 _store_item_mapping_find(Elm_Store_Item *sti, const char *part)
325 {
326    const Elm_Store_Item_Mapping *m;
327
328    for (m = sti->mapping; m; m ++)
329      {
330         if (m->type == ELM_STORE_ITEM_MAPPING_NONE) break;
331         if (!strcmp(part, m->part)) return m;
332      }
333    return NULL;
334 }
335
336 static char *
337 _store_item_label_get(void *data, Evas_Object *obj __UNUSED__, const char *part)
338 {
339    Elm_Store_Item *sti = data;
340    const char *s = "";
341    LKL(sti->lock);
342    if (sti->data)
343      {
344         const Elm_Store_Item_Mapping *m = _store_item_mapping_find(sti, part);
345         if (m)
346           {
347              switch (m->type)
348                {
349                 case ELM_STORE_ITEM_MAPPING_LABEL:
350                    s = *(char **)(((unsigned char *)sti->data) + m->offset);
351                    break;
352                 case ELM_STORE_ITEM_MAPPING_CUSTOM:
353                    if (m->details.custom.func)
354                      s = m->details.custom.func(sti->data, sti, part);
355                    break;
356                 default:
357                    break;
358                }
359           }
360      }
361    LKU(sti->lock);
362    return strdup(s);
363 }
364
365 static Evas_Object *
366 _store_item_icon_get(void *data, Evas_Object *obj, const char *part)
367 {
368    Elm_Store_Item *sti = data;
369    LKL(sti->lock);
370    if (sti->data)
371      {
372         const Elm_Store_Item_Mapping *m = _store_item_mapping_find(sti, part);
373         if (m)
374           {
375              Evas_Object *ic = NULL;
376              const char *s = NULL;
377
378              switch (m->type)
379                {
380                 case ELM_STORE_ITEM_MAPPING_ICON:
381                    ic = elm_icon_add(obj);
382                    s = *(char **)(((unsigned char *)sti->data) + m->offset);
383                    elm_icon_order_lookup_set(ic, m->details.icon.lookup_order);
384                    evas_object_size_hint_aspect_set(ic,
385                                                     EVAS_ASPECT_CONTROL_VERTICAL,
386                                                     m->details.icon.w,
387                                                     m->details.icon.h);
388                    elm_icon_smooth_set(ic, m->details.icon.smooth);
389                    elm_icon_no_scale_set(ic, m->details.icon.no_scale);
390                    elm_icon_scale_set(ic,
391                                       m->details.icon.scale_up,
392                                       m->details.icon.scale_down);
393                    if (s)
394                      {
395                         if (m->details.icon.standard_name)
396                           elm_icon_standard_set(ic, s);
397                         else
398                           elm_icon_file_set(ic, s, NULL);
399                      }
400                    break;
401                 case ELM_STORE_ITEM_MAPPING_PHOTO:
402                    ic = elm_icon_add(obj);
403                    s = *(char **)(((unsigned char *)sti->data) + m->offset);
404                    elm_photo_size_set(ic, m->details.photo.size);
405                    if (s)
406                      elm_photo_file_set(ic, s);
407                    break;
408                 case ELM_STORE_ITEM_MAPPING_CUSTOM:
409                    if (m->details.custom.func)
410                      ic = m->details.custom.func(sti->data, sti, part);
411                    break;
412                 default:
413                    break;
414                }
415              LKU(sti->lock);
416              return ic;
417           }
418      }
419    LKU(sti->lock);
420    return NULL;
421 }
422
423 static void
424 _store_item_del(void *data __UNUSED__, Evas_Object *obj __UNUSED__)
425 {
426 }
427
428 ////// **** WARNING ***********************************************************
429 ////   * This function runs inside a thread outside efl mainloop. Be careful! *
430 //     ************************************************************************
431 static int
432 _store_filesystem_sort_cb(void *d1, void *d2)
433 {
434    Elm_Store_Item_Info *info1 = d1, *info2 = d2;
435    if ((!info1->sort_id) || (!info2->sort_id)) return 0;
436    return strcoll(info1->sort_id, info2->sort_id);
437 }
438
439 static void
440 _store_filesystem_list_do(void *data, Ecore_Thread *th __UNUSED__)
441 {
442    Elm_Store_Filesystem *st = data;
443    Eina_Iterator *it;
444    const Eina_File_Direct_Info *finf;
445    Eina_List *sorted = NULL;
446    Elm_Store_Item_Info_Filesystem *info;
447
448    // FIXME: need a way to abstract the open, list, feed items from list
449    // and maybe get initial sortable key vals etc.
450    it = eina_file_stat_ls(st->dir);
451    if (!it) return;
452    EINA_ITERATOR_FOREACH(it, finf)
453      {
454         Eina_Bool ok;
455         size_t pathsz = finf->path_length + 1;
456
457         info = calloc(1, sizeof(Elm_Store_Item_Info_Filesystem) + pathsz);
458         if (!info) continue;
459         info->path = ((char *)info) + sizeof(Elm_Store_Item_Info_Filesystem);
460         memcpy(info->path, finf->path, pathsz);
461         ok = EINA_TRUE;
462         if (st->base.cb.list.func)
463           ok = st->base.cb.list.func(st->base.cb.list.data, &info->base);
464         if (ok)
465           {
466              if (!st->base.sorted) ecore_thread_feedback(th, info);
467              else sorted = eina_list_append(sorted, info);
468           }
469         else
470           {
471              if (info->base.sort_id) free(info->base.sort_id);
472              free(info);
473           }
474         if (ecore_thread_check(th)) break;
475      }
476    eina_iterator_free(it);
477    if (sorted)
478      {
479         sorted = eina_list_sort(sorted, 0,
480                                 EINA_COMPARE_CB(_store_filesystem_sort_cb));
481         EINA_LIST_FREE(sorted, info)
482           {
483              if (!ecore_thread_check(th)) ecore_thread_feedback(th, info);
484           }
485      }
486 }
487 //     ************************************************************************
488 ////   * End of separate thread function.                                     *
489 ////// ************************************************************************
490
491 static void
492 _store_filesystem_list_end(void *data, Ecore_Thread *th)
493 {
494    Elm_Store *st = data;
495    if (th == st->list_th) st->list_th = NULL;
496 }
497
498 static void
499 _store_filesystem_list_cancel(void *data, Ecore_Thread *th)
500 {
501    Elm_Store *st = data;
502    if (th == st->list_th) st->list_th = NULL;
503 }
504
505 static void
506 _store_filesystem_list_update(void *data, Ecore_Thread *th __UNUSED__, void *msg)
507 {
508    Elm_Store *st = data;
509    Elm_Store_Item_Filesystem *sti;
510    Elm_Genlist_Item_Class *itc;
511    Elm_Store_Item_Info_Filesystem *info = msg;
512
513    sti = calloc(1, sizeof(Elm_Store_Item_Filesystem));
514    if (!sti) goto done;
515    LKI(sti->base.lock);
516    EINA_MAGIC_SET(&(sti->base), ELM_STORE_ITEM_MAGIC);
517    sti->base.store = st;
518    sti->base.data = info->base.data;
519    sti->base.mapping = info->base.mapping;
520    sti->path = eina_stringshare_add(info->path);
521
522    itc = info->base.item_class;
523    if (!itc) itc = &_store_item_class;
524    else
525      {
526         itc->func.label_get = (GenlistItemLabelGetFunc)_store_item_label_get;
527         itc->func.icon_get  = (GenlistItemIconGetFunc)_store_item_icon_get;
528         itc->func.state_get = NULL; // FIXME: support state gets later
529         itc->func.del = (GenlistItemDelFunc)_store_item_del;
530      }
531
532    // FIXME: handle being a parent (tree)
533    sti->base.item = elm_genlist_item_append(st->genlist, itc,
534                                             sti/* item data */,
535                                             NULL/* parent */,
536                                             ELM_GENLIST_ITEM_NONE,
537                                             NULL/* func */,
538                                             NULL/* func data */);
539    st->items = eina_inlist_append(st->items, (Eina_Inlist *)sti);
540 done:
541    if (info->base.sort_id) free(info->base.sort_id);
542    free(info);
543 }
544
545 // public api calls
546 static Elm_Store *
547 _elm_store_new(size_t size)
548 {
549    Elm_Store *st = calloc(1, size);
550    EINA_SAFETY_ON_NULL_RETURN_VAL(st, NULL);
551
552    // TODO: BEGIN - move to elm_store_init()
553    eina_magic_string_set(ELM_STORE_MAGIC, "Elm_Store");
554    eina_magic_string_set(ELM_STORE_FILESYSTEM_MAGIC, "Elm_Store_Filesystem");
555    eina_magic_string_set(ELM_STORE_ITEM_MAGIC, "Elm_Store_Item");
556    // setup default item class (always the same) if list cb doesnt provide one
557    _store_item_class.item_style = "default";
558    _store_item_class.func.label_get = (GenlistItemLabelGetFunc)_store_item_label_get;
559    _store_item_class.func.icon_get  = (GenlistItemIconGetFunc)_store_item_icon_get;
560    _store_item_class.func.state_get = NULL; // FIXME: support state gets later
561    _store_item_class.func.del       = (GenlistItemDelFunc)_store_item_del;
562    // TODO: END - move to elm_store_init()
563
564    EINA_MAGIC_SET(st, ELM_STORE_MAGIC);
565    st->cache_max = 128;
566    st->fetch_thread = EINA_TRUE;
567    st->type = 0;
568    return st;
569 }
570 #define elm_store_new(type) (type*)_elm_store_new(sizeof(type))
571
572 static void
573 _elm_store_filesystem_free(Elm_Store *store)
574 {
575    Elm_Store_Filesystem *st = (Elm_Store_Filesystem *)store;
576    eina_stringshare_del(st->dir);
577 }
578
579 static void
580 _elm_store_filesystem_item_free(Elm_Store_Item *item)
581 {
582    Elm_Store_Item_Filesystem *sti = (Elm_Store_Item_Filesystem *)item;
583    eina_stringshare_del(sti->path);
584 }
585
586 EAPI Elm_Store *
587 elm_store_filesystem_new(void)
588 {
589    Elm_Store_Filesystem *st = elm_store_new(Elm_Store_Filesystem);
590    EINA_SAFETY_ON_NULL_RETURN_VAL(st, NULL);
591
592    EINA_MAGIC_SET(st, ELM_STORE_FILESYSTEM_MAGIC);
593    st->base.free = _elm_store_filesystem_free;
594    st->base.item.free = _elm_store_filesystem_item_free;
595
596    return &st->base;
597 }
598
599 EAPI void
600 elm_store_free(Elm_Store *st)
601 {
602    void (*item_free)(Elm_Store_Item *);
603    if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
604    if (st->list_th)
605      {
606         ecore_thread_cancel(st->list_th);
607         st->list_th = NULL;
608      }
609
610    if (!st->type)
611      {
612         eina_list_free(st->realized);
613         item_free = st->item.free;
614         while (st->items)
615           {
616              Elm_Store_Item *sti = (Elm_Store_Item *)st->items;
617              if (sti->eval_job) ecore_job_del(sti->eval_job);
618              if (sti->fetch_th)
619                {
620                   ecore_thread_cancel(sti->fetch_th);
621                   sti->fetch_th = NULL;
622                }
623              if (item_free) item_free(sti);
624              if (sti->data)
625                {
626                   if (st->cb.unfetch.func)
627                     st->cb.unfetch.func(st->cb.unfetch.data, sti, NULL);
628                   sti->data = NULL;
629                }
630              LKD(sti->lock);
631              free(sti);
632           }
633         if (st->genlist)
634           {
635              evas_object_event_callback_del_full(st->genlist, EVAS_CALLBACK_DEL, _store_genlist_del, st);
636              evas_object_smart_callback_del(st->genlist, "realized", _store_genlist_item_realized);
637              evas_object_smart_callback_del(st->genlist, "unrealized", _store_genlist_item_unrealized);
638              elm_genlist_clear(st->genlist);
639              st->genlist = NULL;
640           }
641         if (st->free) st->free(st);
642      }
643    else
644      {
645         st->live = EINA_FALSE;
646         if (st->genlist)
647           {
648              evas_object_event_callback_del_full(st->genlist, EVAS_CALLBACK_DEL, _genlist_del, st);
649              evas_object_smart_callback_del(st->genlist, "realized", _item_realized);
650              evas_object_smart_callback_del(st->genlist, "unrealized", _item_unrealized);
651              elm_genlist_clear(st->genlist);
652              st->genlist = NULL;
653           }
654         Eina_List *l;
655         Eina_List *l_next;
656         Eina_List *header_list;
657
658         EINA_LIST_FOREACH_SAFE(st->header_items, l, l_next, header_list)
659           {
660              if (header_list)
661                {
662                   Eina_List *in_l;
663                   Eina_List *in_l_next;
664                   Elm_Store_Item *sti;
665                   EINA_LIST_FOREACH_SAFE(header_list, in_l, in_l_next, sti)
666                     {
667                        if(sti)
668                          {
669                             if (st->fetch_thread && sti->fetch_th)
670                               {
671                                  ecore_thread_cancel(sti->fetch_th);
672                                  sti->fetch_th = NULL;
673                               }
674                             if (st->cb.item_free.func)
675                               {
676                                  st->cb.item_free.func(st->cb.item_free.data, sti->item_info);
677                                  sti->item_info = NULL;
678                               }
679                             if (sti->fetched)
680                               {
681                                  int index = elm_store_item_index_get(sti);
682                                  if (index != -1) _item_unfetch(st, index);
683                               }
684                             header_list = eina_list_remove(header_list, sti);
685                             LKD(sti->lock);
686                             free(sti);
687                          }
688                     }
689                   st->header_items = eina_list_remove(st->header_items, header_list);
690                   header_list = eina_list_free(header_list);
691                }
692           }
693         st->header_items = eina_list_free(st->header_items);
694      }
695    free(st);
696 }
697
698 EAPI void
699 elm_store_target_genlist_set(Elm_Store *st, Evas_Object *obj)
700 {
701    if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
702    if (st->genlist == obj) return;
703    if (st->genlist)
704      {
705         if (!st->type)
706           {
707              evas_object_event_callback_del_full(st->genlist, EVAS_CALLBACK_DEL, _store_genlist_del, st);
708              evas_object_smart_callback_del(st->genlist, "realized", _store_genlist_item_realized);
709              evas_object_smart_callback_del(st->genlist, "unrealized", _store_genlist_item_unrealized);
710           }
711         else
712           {
713              evas_object_event_callback_del_full(st->genlist, EVAS_CALLBACK_DEL, _genlist_del, st);
714              evas_object_smart_callback_del(st->genlist, "realized", _item_realized);
715              evas_object_smart_callback_del(st->genlist, "unrealized", _item_unrealized);
716           }
717         elm_genlist_clear(st->genlist);
718      }
719    st->genlist = obj;
720    if (!st->genlist) return;
721    if (!st->type)
722      {
723         evas_object_smart_callback_add(st->genlist, "realized", _store_genlist_item_realized, st);
724         evas_object_smart_callback_add(st->genlist, "unrealized", _store_genlist_item_unrealized, st);
725         evas_object_event_callback_add(st->genlist, EVAS_CALLBACK_DEL, _store_genlist_del, st);
726      }
727    else
728      {
729         evas_object_smart_callback_add(st->genlist, "realized", _item_realized, st);
730         evas_object_smart_callback_add(st->genlist, "unrealized", _item_unrealized, st);
731         evas_object_event_callback_add(st->genlist, EVAS_CALLBACK_DEL, _genlist_del, st);
732         st->block_count = elm_genlist_block_count_get(st->genlist);
733      }
734    elm_genlist_clear(st->genlist);
735 }
736
737 EAPI void
738 elm_store_filesystem_directory_set(Elm_Store *store, const char *dir)
739 {
740    Elm_Store_Filesystem *st = (Elm_Store_Filesystem *)store;
741    if (!EINA_MAGIC_CHECK(store, ELM_STORE_MAGIC)) return;
742    if (!EINA_MAGIC_CHECK(st, ELM_STORE_FILESYSTEM_MAGIC)) return;
743    if (store->list_th)
744      {
745         ecore_thread_cancel(store->list_th);
746         store->list_th = NULL;
747      }
748    if (!eina_stringshare_replace(&st->dir, dir)) return;
749    store->list_th = ecore_thread_feedback_run(_store_filesystem_list_do,
750                                               _store_filesystem_list_update,
751                                               _store_filesystem_list_end,
752                                               _store_filesystem_list_cancel,
753                                               st, EINA_TRUE);
754 }
755
756 EAPI const char *
757 elm_store_filesystem_directory_get(const Elm_Store *store)
758 {
759    const Elm_Store_Filesystem *st = (const Elm_Store_Filesystem *)store;
760    if (!EINA_MAGIC_CHECK(store, ELM_STORE_MAGIC)) return NULL;
761    if (!EINA_MAGIC_CHECK(st, ELM_STORE_FILESYSTEM_MAGIC)) return NULL;
762    return st->dir;
763 }
764
765 EAPI void
766 elm_store_cache_set(Elm_Store *st, int max)
767 {
768    if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
769    if (max < 0) max = 0;
770    st->cache_max = max;
771    if(!st->type) _store_cache_trim(st);
772 }
773
774 EAPI int
775 elm_store_cache_get(const Elm_Store *st)
776 {
777    if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return 0;
778    return st->cache_max;
779 }
780
781 EAPI void
782 elm_store_list_func_set(Elm_Store *st, Elm_Store_Item_List_Cb func, const void *data)
783 {
784    if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
785    st->cb.list.func = func;
786    st->cb.list.data = (void *)data;
787 }
788
789 EAPI void
790 elm_store_fetch_func_set(Elm_Store *st, Elm_Store_Item_Fetch_Cb func, const void *data)
791 {
792    if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
793    st->cb.fetch.func = func;
794    st->cb.fetch.data = (void *)data;
795 }
796
797 EAPI void
798 elm_store_fetch_thread_set(Elm_Store *st, Eina_Bool use_thread)
799 {
800    if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
801    st->fetch_thread = !!use_thread;
802 }
803
804 EAPI Eina_Bool
805 elm_store_fetch_thread_get(const Elm_Store *st)
806 {
807    if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return EINA_FALSE;
808    return st->fetch_thread;
809 }
810
811 EAPI void
812 elm_store_unfetch_func_set(Elm_Store *st, Elm_Store_Item_Unfetch_Cb func, const void *data)
813 {
814    if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
815    st->cb.unfetch.func = func;
816    st->cb.unfetch.data = (void *)data;
817 }
818
819 EAPI void
820 elm_store_sorted_set(Elm_Store *st, Eina_Bool sorted)
821 {
822    if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
823    st->sorted = sorted;
824 }
825
826 EAPI Eina_Bool
827 elm_store_sorted_get(const Elm_Store *st)
828 {
829    if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return EINA_FALSE;
830    return st->sorted;
831 }
832
833 EAPI void
834 elm_store_item_data_set(Elm_Store_Item *sti, void *data)
835 {
836    if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return;
837    LKL(sti->lock);
838    sti->data = data;
839    LKU(sti->lock);
840 }
841
842 EAPI void *
843 elm_store_item_data_get(Elm_Store_Item *sti)
844 {
845    if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return NULL;
846    void *d;
847    LKL(sti->lock);
848    d = sti->data;
849    LKU(sti->lock);
850    return d;
851 }
852
853 EAPI const Elm_Store *
854 elm_store_item_store_get(const Elm_Store_Item *sti)
855 {
856    if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return NULL;
857    // dont need lock
858    return sti->store;
859 }
860
861 EAPI const Elm_Genlist_Item *
862 elm_store_item_genlist_item_get(const Elm_Store_Item *sti)
863 {
864    if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return NULL;
865    // dont need lock
866    return sti->item;
867 }
868
869 EAPI const char *
870 elm_store_item_filesystem_path_get(const Elm_Store_Item *item)
871 {
872    Elm_Store_Item_Filesystem *sti = (Elm_Store_Item_Filesystem *)item;
873    Elm_Store_Filesystem *st;
874    if (!EINA_MAGIC_CHECK(item, ELM_STORE_ITEM_MAGIC)) return NULL;
875    if (!EINA_MAGIC_CHECK(item->store, ELM_STORE_MAGIC)) return NULL;
876    /* ensure we're dealing with filesystem item */
877    st = (Elm_Store_Filesystem *)item->store;
878    if (!EINA_MAGIC_CHECK(st, ELM_STORE_FILESYSTEM_MAGIC)) return NULL;
879    // dont need lock
880    return sti->path;
881 }
882
883 // TODO: BEGIN -DBsystem store
884
885 static Elm_Store *
886 _store_init(size_t size)
887 {
888    Elm_Store *st = calloc(1, size);
889    if (!st) return NULL;
890
891    eina_magic_string_set(ELM_STORE_MAGIC, "Elm_Store");
892    eina_magic_string_set(ELM_STORE_FILESYSTEM_MAGIC, "Elm_Store_Filesystem");
893    eina_magic_string_set(ELM_STORE_ITEM_MAGIC, "Elm_Store_Item");
894    eina_magic_string_set(ELM_STORE_DBSYSTEM_MAGIC, "Elm_Store_DBsystem");
895
896    _store_item_class.item_style = "default";
897    _store_item_class.func.label_get = (GenlistItemLabelGetFunc)_item_label_get;
898    _store_item_class.func.icon_get = (GenlistItemIconGetFunc)_item_icon_get;
899    _store_item_class.func.state_get = NULL;
900    _store_item_class.func.del = NULL;
901
902    EINA_MAGIC_SET(st, ELM_STORE_MAGIC);
903    st->cache_max = CACHE_COUNT;
904    st->start_fetch_index = 0;
905    st->end_fetch_index = 0;
906    st->live = EINA_TRUE;
907    st->multi_load = EINA_FALSE;
908    st->total_item_count = 0;
909    st->fetch_thread = EINA_FALSE;
910    st->type = 1;
911    return st;
912 }
913
914 #define _store_new(type) (type *)_store_init(sizeof(type))
915
916 static void
917 _genlist_del(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
918 {
919    EINA_SAFETY_ON_NULL_RETURN(data);
920    Elm_Store *st = data;
921    if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
922
923    elm_store_free(st);
924 }
925
926 static void
927 _store_fetch_do(void *data, Ecore_Thread *th __UNUSED__)
928 {
929    Elm_Store_Item *sti = data;
930
931    LKL(sti->lock);
932    if (!sti->fetched)
933      {
934         LKU(sti->lock);
935         sti->store->cb.fetch.func(sti->store->cb.fetch.data, sti, sti->item_info);
936         LKL(sti->lock);
937         sti->fetched = EINA_TRUE;
938      }
939    LKU(sti->lock);
940 }
941
942 static void
943 _store_fetch_end(void *data, Ecore_Thread *th)
944 {
945    Elm_Store_Item *sti = data;
946    LKL(sti->lock);
947    if (th == sti->fetch_th) sti->fetch_th = NULL;
948    LKU(sti->lock);
949 }
950
951 static void
952 _store_fetch_cancel(void *data, Ecore_Thread *th)
953 {
954    Elm_Store_Item *sti = data;
955    LKL(sti->lock);
956    if (th == sti->fetch_th) sti->fetch_th = NULL;
957    LKU(sti->lock);
958 }
959
960 static Elm_Store_Item *
961 _item_fetch(Elm_Store *st, int index)
962 {
963    EINA_SAFETY_ON_NULL_RETURN_VAL(st,NULL);
964    Elm_Store_Item *sti;
965
966    int in_index = 0;
967    Eina_List *l;
968    Eina_List *l_next;
969    Eina_List *header_list;
970    if (st->live)
971      {
972         EINA_LIST_FOREACH_SAFE(st->header_items, l, l_next, header_list)
973           {
974              if(header_list)
975                {
976                   if ((in_index + eina_list_count(header_list)) > index)
977                     {
978                        sti = eina_list_nth(header_list, index - in_index);
979                        if(sti)
980                          {
981                             if (st->cb.fetch.func)
982                               {
983                                  LKL(sti->lock);
984                                  if (st->fetch_thread)
985                                    {
986                                       if (!sti->fetch_th)
987                                         {
988                                            sti->fetch_th = ecore_thread_run(_store_fetch_do,
989                                                                             _store_fetch_end,
990                                                                             _store_fetch_cancel,
991                                                                             sti);
992                                         }
993                                    }
994                                  else
995                                    {
996                                       LKU(sti->lock);
997                                       st->cb.fetch.func(st->cb.fetch.data, sti, sti->item_info);
998                                       LKL(sti->lock);
999                                       sti->fetched = EINA_TRUE;
1000                                    }
1001                                  LKU(sti->lock);
1002                               }
1003                             return sti;
1004                          }
1005                        else
1006                          {
1007                             return NULL;
1008                          }
1009                     }
1010                   else
1011                     {
1012                        in_index = in_index + eina_list_count(header_list);
1013                     }
1014                }
1015           }
1016      }
1017    return NULL;
1018 }
1019
1020 static Elm_Store_Item *
1021 _item_unfetch(Elm_Store *st, int index)
1022 {
1023    EINA_SAFETY_ON_NULL_RETURN_VAL(st,NULL);
1024
1025    int in_index = 0;
1026    Elm_Store_Item *sti;
1027    Eina_List *l;
1028    Eina_List *l_next;
1029    Eina_List *header_list;
1030
1031    if (st->live)
1032      {
1033         EINA_LIST_FOREACH_SAFE(st->header_items, l, l_next, header_list)
1034           {
1035              if(header_list)
1036                {
1037                   if ((in_index + eina_list_count(header_list)) > index)
1038                     {
1039                        sti = eina_list_nth(header_list, index - in_index);
1040                        if(sti)
1041                          {
1042                             if (st->cb.unfetch.func)
1043                               {
1044                                  LKL(sti->lock);
1045                                  if (sti->fetch_th)
1046                                    {
1047                                       LKU(sti->lock);
1048                                       ecore_thread_cancel(sti->fetch_th);
1049                                       sti->fetch_th = NULL;
1050                                       LKL(sti->lock);
1051                                    }
1052                                  LKU(sti->lock);
1053                                  st->cb.unfetch.func(st->cb.unfetch.data, sti, sti->item_info);
1054                                  LKL(sti->lock);
1055                                  sti->fetched = EINA_FALSE;
1056                                  LKU(sti->lock);
1057                               }
1058                             return sti;
1059                          }
1060                        else
1061                          {
1062                             return NULL;
1063                          }
1064                     }
1065                   else
1066                     {
1067                        in_index = in_index + eina_list_count(header_list);
1068                     }
1069                }
1070           }
1071      }
1072    return NULL;
1073 }
1074
1075 static const Elm_Store_Item_Mapping *
1076 _item_mapping_find(Elm_Store_Item *sti, const char *part)
1077 {
1078    if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return NULL;
1079    const Elm_Store_Item_Mapping *m;
1080
1081    if(!sti->item_info)
1082      {
1083         return NULL;
1084      }
1085
1086    for (m = sti->item_info->mapping; m; m++)
1087      {
1088         if (m->type == ELM_STORE_ITEM_MAPPING_NONE) break;
1089         if (!strcmp(part, m->part)) return m;
1090      }
1091    return NULL;
1092 }
1093
1094 static void
1095 _item_realize(Elm_Store_Item *sti)
1096 {
1097    if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return;
1098    Elm_Store *st = sti->store;
1099    if (sti->store->live)
1100      {
1101         int index = elm_store_item_index_get(sti);
1102
1103         if (index != -1)
1104           {
1105              if ((st->start_fetch_index <= index) && (index <= (st->start_fetch_index + st->cache_max)))
1106                {
1107                   if (sti->fetched)
1108                     {
1109                        _item_unfetch(st, index);
1110                     }
1111                   _item_fetch(st, index);
1112
1113                   if(st->end_fetch_index < index)
1114                     {
1115                        st->end_fetch_index = index;
1116                     }
1117                }
1118              else if (st->start_fetch_index > index)
1119                {
1120                   int diff = st->start_fetch_index - index;
1121                   int loop;
1122                   for (loop = 1; loop <= diff; loop++)
1123                     {
1124                        _item_unfetch(st, st->end_fetch_index);
1125                        st->end_fetch_index--;
1126                        _item_fetch(sti->store, (st->start_fetch_index - loop));
1127                     }
1128                   st->start_fetch_index = index;
1129                }
1130              else if (index > st->end_fetch_index)
1131                {
1132                   int diff = index - st->end_fetch_index;
1133                   int loop;
1134                   for (loop = 1; loop <= diff; loop++)
1135                     {
1136                        _item_unfetch(st, st->start_fetch_index);
1137                        st->start_fetch_index++;
1138                        _item_fetch(st, (st->end_fetch_index + loop));
1139                     }
1140                   st->end_fetch_index = index;
1141                }
1142           }
1143         else
1144           {
1145              return;
1146           }
1147      }
1148 }
1149
1150 static char *
1151 _item_label_get(void *data, Evas_Object *obj __UNUSED__, const char *part)
1152 {
1153    EINA_SAFETY_ON_NULL_RETURN_VAL(data, strdup(""));
1154    Elm_Store_Item *sti = data;
1155    EINA_SAFETY_ON_NULL_RETURN_VAL(sti,NULL);
1156
1157    if (sti->store->live)
1158      {
1159         if (sti->item)
1160           {
1161              if (!sti->data)
1162                {
1163                   _item_realize(sti);
1164                }
1165
1166              LKL(sti->lock);
1167              if (sti->data)
1168                {
1169                   const char *s = "";
1170                   const Elm_Store_Item_Mapping *m = _item_mapping_find(sti, part);
1171                   if (m)
1172                     {
1173                        switch (m->type)
1174                          {
1175                           case ELM_STORE_ITEM_MAPPING_LABEL:
1176                              s = *(char **)(((unsigned char *)sti->data) + m->offset);
1177                              break;
1178
1179                           case ELM_STORE_ITEM_MAPPING_CUSTOM:
1180                              if (m->details.custom.func)
1181                                s = m->details.custom.func(sti->data, sti, part);
1182                              break;
1183
1184                           default:
1185                              break;
1186                          }
1187                        if (s)
1188                          {
1189                             LKU(sti->lock);
1190                             return strdup(s);
1191                          }
1192                        else
1193                          {
1194                             LKU(sti->lock);
1195                             return NULL;
1196                          }
1197                     }
1198                }
1199              LKU(sti->lock);
1200           }
1201      }
1202    return NULL;
1203 }
1204
1205 static Evas_Object *
1206 _item_icon_get(void *data, Evas_Object *obj, const char *part)
1207 {
1208    EINA_SAFETY_ON_NULL_RETURN_VAL(data,NULL);
1209    Elm_Store_Item *sti = data;
1210    EINA_SAFETY_ON_NULL_RETURN_VAL(sti,NULL);
1211
1212    if (sti->store->live)
1213      {
1214         if (sti->item)
1215           {
1216              if (!sti->data)
1217                {
1218                   _item_realize(sti);
1219                }
1220
1221              LKL(sti->lock);
1222              if (sti->data)
1223                {
1224                   const Elm_Store_Item_Mapping *m = _item_mapping_find(sti, part);
1225                   if (m)
1226                     {
1227                        Evas_Object *ic = NULL;
1228                        const char *s = NULL;
1229
1230                        switch (m->type)
1231                          {
1232                           case ELM_STORE_ITEM_MAPPING_ICON:
1233                              ic = elm_icon_add(obj);
1234                              s = *(char **)(((unsigned char *)sti->data) + m->offset);
1235                              elm_icon_order_lookup_set(ic, m->details.icon.lookup_order);
1236                              evas_object_size_hint_aspect_set(ic,
1237                                                               EVAS_ASPECT_CONTROL_VERTICAL,
1238                                                               m->details.icon.w,
1239                                                               m->details.icon.h);
1240                              elm_icon_smooth_set(ic, m->details.icon.smooth);
1241                              elm_icon_no_scale_set(ic, m->details.icon.no_scale);
1242                              elm_icon_scale_set(ic,
1243                                                 m->details.icon.scale_up,
1244                                                 m->details.icon.scale_down);
1245
1246                              if (s)
1247                                {
1248                                   if (m->details.icon.standard_name)
1249                                     elm_icon_standard_set(ic, s);
1250                                   else
1251                                     elm_icon_file_set(ic, s, NULL);
1252                                }
1253                              break;
1254
1255                           case ELM_STORE_ITEM_MAPPING_PHOTO:
1256                              ic = elm_icon_add(obj);
1257                              s = *(char **)(((unsigned char *)sti->data) + m->offset);
1258                              elm_photo_size_set(ic, m->details.photo.size);
1259                              if (s)
1260                                elm_photo_file_set(ic, s);
1261                              break;
1262
1263                           case ELM_STORE_ITEM_MAPPING_CUSTOM:
1264                              if (m->details.custom.func)
1265                                ic = m->details.custom.func(sti->data, sti, part);
1266                              break;
1267
1268                           default:
1269                              break;
1270                          }
1271                        LKU(sti->lock);
1272                        return ic;
1273                     }
1274                }
1275              LKU(sti->lock);
1276           }
1277      }
1278    return NULL;
1279 }
1280
1281 static void
1282 _item_realized(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1283 {
1284    /*   EINA_SAFETY_ON_NULL_RETURN(data);
1285         EINA_SAFETY_ON_NULL_RETURN(event_info);
1286         Elm_Store *st = data;
1287         Elm_Genlist_Item *gli = event_info;
1288         Elm_Store_Item *sti = elm_genlist_item_data_get(gli);
1289
1290         EINA_SAFETY_ON_NULL_RETURN(sti);
1291
1292         int index = elm_store_item_index_get(sti);
1293
1294         if (st->fetch_thread)
1295         {
1296         if ((st->start_fetch_index <= index) && (index <= st->end_fetch_index))
1297         {
1298         int middle_index = sti->store->start_fetch_index + (sti->store->cache_max) / 2;
1299
1300         if ((middle_index < index) && (sti->store->end_fetch_index < sti->store->total_item_count))
1301         {
1302         int diff = index - middle_index;
1303         int loop;
1304         for (loop = 0; loop < diff; loop++)
1305         {
1306         _item_unfetch(st, sti->store->start_fetch_index);
1307         sti->store->start_fetch_index++;
1308         _item_fetch(st, (sti->store->end_fetch_index + 1));
1309         sti->store->end_fetch_index++;
1310         }
1311         }
1312         else if ((middle_index > index) && (sti->store->start_fetch_index > 0))
1313         {
1314         int diff = st->current_top_index - index;
1315         int loop;
1316         for (loop = 0; loop < diff; loop++)
1317         {
1318         _item_unfetch(st, sti->store->end_fetch_index);
1319         sti->store->end_fetch_index--;
1320         _item_fetch(st, (sti->store->start_fetch_index - 1));
1321         sti->store->start_fetch_index--;
1322         }
1323         }
1324         else {
1325         if ((!sti->fetched))
1326         {
1327         _item_fetch(st, index);
1328         }
1329         }
1330         }
1331         }
1332
1333         if ((st->current_top_index > index))
1334         {
1335         st->current_top_index = index;
1336         }
1337         else if ((st->current_top_index + SCREEN_ITEM_COUNT) < index)
1338         {
1339         st->current_top_index = st->current_top_index + (index - (st->current_top_index + SCREEN_ITEM_COUNT));
1340         }
1341     */
1342    // TODO:
1343 }
1344
1345 static void
1346 _item_unrealized(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1347 {
1348    /*   EINA_SAFETY_ON_NULL_RETURN(data);
1349         EINA_SAFETY_ON_NULL_RETURN(event_info);
1350         Elm_Genlist_Item *gli = event_info;
1351         Elm_Store_Item *sti = elm_genlist_item_data_get(gli);
1352         EINA_SAFETY_ON_NULL_RETURN(sti);*/
1353 }
1354
1355 static void
1356 _item_del(void *data, Evas_Object *obj __UNUSED__)
1357 {
1358    EINA_SAFETY_ON_NULL_RETURN(data);
1359    Elm_Store_Item *sti = data;
1360    EINA_SAFETY_ON_NULL_RETURN(sti);
1361    if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return;
1362    elm_store_item_del(sti);
1363 }
1364
1365 static void
1366 _list_do(void *data, Ecore_Thread *th __UNUSED__)
1367 {
1368    EINA_SAFETY_ON_NULL_RETURN(data);
1369    Elm_Store *st = data;
1370    if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
1371
1372    if (st->multi_load == EINA_TRUE)
1373      {
1374         Elm_Store_Item_Info *item_info;
1375         Eina_Bool ok = EINA_FALSE;
1376         int loop;
1377         for (loop = 0; loop < st->item_count; loop++)
1378           {
1379              item_info = calloc(1, sizeof(Elm_Store_Item_Info));
1380              if (!item_info) return;
1381              item_info->index = loop;
1382
1383              if (st->cb.list.func)
1384                {
1385                   ok = st->cb.list.func(st->cb.list.data, item_info);
1386                }
1387              if (ok) ecore_thread_feedback(th, item_info);
1388              else free(item_info);
1389              if (ecore_thread_check(th)) break;
1390           }
1391      }
1392 }
1393
1394 static void
1395 _list_update(void *data, Ecore_Thread *th __UNUSED__, void *msg)
1396 {
1397    EINA_SAFETY_ON_NULL_RETURN(data);
1398    EINA_SAFETY_ON_NULL_RETURN(msg);
1399    Elm_Store *st = data;
1400    Elm_Store_Item_Info *info = msg;
1401
1402    elm_store_item_add(st, info);
1403 }
1404
1405 static void
1406 _list_end(void *data, Ecore_Thread *th)
1407 {
1408    EINA_SAFETY_ON_NULL_RETURN(data);
1409    EINA_SAFETY_ON_NULL_RETURN(th);
1410    Elm_Store *st = data;
1411
1412    if (th == st->list_th)
1413      {
1414         ecore_thread_cancel(st->list_th);
1415         st->list_th = NULL;
1416      }
1417 }
1418
1419 static void
1420 _list_cancel(void *data, Ecore_Thread *th)
1421 {
1422    EINA_SAFETY_ON_NULL_RETURN(data);
1423    EINA_SAFETY_ON_NULL_RETURN(th);
1424    Elm_Store *st = data;
1425
1426    if (th == st->list_th)
1427      {
1428         ecore_thread_cancel(st->list_th);
1429         st->list_th = NULL;
1430      }
1431 }
1432
1433 static void
1434 _item_select_cb(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
1435 {
1436    EINA_SAFETY_ON_NULL_RETURN(event_info);
1437
1438    const Elm_Genlist_Item *it = (Elm_Genlist_Item *)event_info;
1439    Elm_Store_Item *sti = elm_genlist_item_data_get(it);
1440    if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return;
1441
1442    if (sti->store->cb.item_select.func)
1443      {
1444         sti->store->cb.item_select.func(sti->store->cb.item_select.data, sti);
1445      }
1446 }
1447
1448 static void
1449 _group_item_append(Elm_Store_Item *sti, Elm_Genlist_Item_Class *itc)
1450 {
1451    EINA_SAFETY_ON_NULL_RETURN(sti);
1452    if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return;
1453    Elm_Store *st = sti->store;
1454    if (st->live)
1455      {
1456         if (st->header_items)
1457           {
1458              Eina_Bool header_add = EINA_TRUE;
1459              Eina_List *l;
1460              Eina_List *l_next;
1461              Eina_List *header_list;
1462
1463              EINA_LIST_FOREACH_SAFE(st->header_items, l, l_next, header_list)
1464                {
1465                   if(header_list)
1466                     {
1467                        Elm_Store_Item *item = eina_list_nth(header_list, 0);
1468                        if(item && item->item_info)
1469                          {
1470                             if (item->item_info->group_index == sti->item_info->group_index)
1471                               {
1472                                  header_add = EINA_FALSE;
1473                                  break;
1474                               }
1475                          }
1476                     }
1477                }
1478              if (header_add)
1479                {
1480                   Eina_List *new_header_list = NULL;
1481                   sti->item_info->index = 0;
1482                   new_header_list = eina_list_append(new_header_list, sti);
1483                   st->total_item_count++;
1484
1485                   Eina_Bool last_header = EINA_TRUE;
1486                   Eina_List *l;
1487                   Eina_List *l_next;
1488                   Eina_List *header_list;
1489
1490                   EINA_LIST_FOREACH_SAFE(st->header_items, l, l_next, header_list)
1491                     {
1492                        if (header_list)
1493                          {
1494                             Elm_Store_Item *group_sti = eina_list_nth(header_list, 0);
1495                             if(group_sti && group_sti->item_info)
1496                               {
1497                                  if(group_sti->item_info->item_type == ELM_GENLIST_ITEM_GROUP)
1498                                    {
1499                                       int sort;
1500                                       if (st->cb.item_sort.func)
1501                                         {
1502                                            sort = st->cb.item_sort.func(st->cb.item_sort.data, sti->item_info, group_sti->item_info);
1503
1504                                            if(sort == ELM_STORE_ITEM_SORT_LOW)
1505                                              {
1506                                                 st->header_items = eina_list_prepend_relative(st->header_items, new_header_list, header_list);
1507                                                 sti->item = elm_genlist_item_insert_before(st->genlist,
1508                                                                                            itc,
1509                                                                                            sti,
1510                                                                                            NULL,
1511                                                                                            group_sti->item,
1512                                                                                            ELM_GENLIST_ITEM_GROUP,
1513                                                                                            NULL,
1514                                                                                            NULL);
1515                                                 last_header = EINA_FALSE;
1516                                                 break;
1517                                              }
1518                                         }
1519                                       else
1520                                         {
1521                                            break;
1522                                         }
1523                                    }
1524                               }
1525                          }
1526                     }
1527                   if (last_header)
1528                     {
1529                        st->header_items = eina_list_append(st->header_items, new_header_list);
1530                        sti->item = elm_genlist_item_append(st->genlist,
1531                                                            itc,
1532                                                            sti,
1533                                                            NULL,
1534                                                            ELM_GENLIST_ITEM_GROUP,
1535                                                            NULL,
1536                                                            NULL);
1537                     }
1538                   elm_store_item_update(sti);
1539                }
1540           }
1541         else
1542           {
1543              Eina_List *header_list = NULL;
1544              sti->item_info->index = 0;
1545              header_list = eina_list_append(header_list, sti);
1546              st->total_item_count++;
1547              st->header_items = eina_list_append(st->header_items, header_list);
1548              sti->item = elm_genlist_item_append(st->genlist,
1549                                                  itc,
1550                                                  sti,
1551                                                  NULL,
1552                                                  ELM_GENLIST_ITEM_GROUP,
1553                                                  NULL,
1554                                                  NULL);
1555              elm_store_item_update(sti);
1556           }
1557      }
1558 }
1559
1560 static void
1561 _normal_item_append(Elm_Store_Item *sti, Elm_Genlist_Item_Class *itc)
1562 {
1563    EINA_SAFETY_ON_NULL_RETURN(sti);
1564    if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return;
1565    Elm_Store *st = sti->store;
1566    if (st->live)
1567      {
1568         if (sti->item_info->rec_item == EINA_TRUE)
1569           {
1570              if (sti->item_info->group_index == sti->item_info->pre_group_index)
1571                {
1572                   Eina_List *l;
1573                   Eina_List *l_next;
1574                   Eina_List *header_list;
1575
1576                   EINA_LIST_FOREACH_SAFE(st->header_items, l, l_next, header_list)
1577                     {
1578                        if(header_list)
1579                          {
1580                             Elm_Store_Item *header_item = eina_list_nth(header_list, 0);
1581                             if(header_item && header_item->item_info)
1582                               {
1583                                  if (header_item->item_info->group_index == sti->item_info->group_index)
1584                                    {
1585                                       Eina_List *in_l;
1586                                       Eina_List *in_l_next;
1587                                       Elm_Store_Item *item;
1588
1589                                       EINA_LIST_FOREACH_SAFE(header_list, in_l, in_l_next, item)
1590                                         {
1591                                            if(item)
1592                                              {
1593                                                 int sort;
1594                                                 if (st->cb.item_sort.func)
1595                                                   {
1596                                                      sort = st->cb.item_sort.func(st->cb.item_sort.data, sti->item_info, item->item_info);
1597
1598                                                      if(sort == ELM_STORE_ITEM_SORT_SAME)
1599                                                        {
1600                                                           elm_store_item_update(item);
1601                                                        }
1602                                                   }
1603                                                 else
1604                                                   {
1605                                                      break;
1606                                                   }
1607
1608                                              }
1609                                         }
1610                                    }
1611                               }
1612                          }
1613                     }
1614                }
1615              else
1616                {
1617                   Eina_List *l;
1618                   Eina_List *l_next;
1619                   Eina_List *header_list;
1620
1621                   EINA_LIST_FOREACH_SAFE(st->header_items, l, l_next, header_list)
1622                     {
1623                        if(header_list)
1624                          {
1625                             Elm_Store_Item *header_item = eina_list_nth(header_list, 0);
1626                             if(header_item && header_item->item_info)
1627                               {
1628                                  if (header_item->item_info->group_index == sti->item_info->pre_group_index)
1629                                    {
1630                                       Eina_Bool removed = EINA_FALSE;
1631                                       Eina_List *in_l;
1632                                       Eina_List *in_l_next;
1633                                       Elm_Store_Item *remove_item;
1634
1635                                       EINA_LIST_FOREACH_SAFE(header_list, in_l, in_l_next, remove_item)
1636                                         {
1637                                            if(remove_item)
1638                                              {
1639                                                 if (removed == EINA_TRUE)
1640                                                   {
1641                                                      remove_item->item_info->index--;
1642                                                   }
1643                                                 else
1644                                                   {
1645                                                      int sort;
1646                                                      if (st->cb.item_sort.func)
1647                                                        {
1648                                                           sort = st->cb.item_sort.func(st->cb.item_sort.data, sti->item_info, remove_item->item_info);
1649
1650                                                           if(sort == ELM_STORE_ITEM_SORT_SAME)
1651                                                             {
1652                                                                if (st->cb.item_free.func)
1653                                                                  {
1654                                                                     st->cb.item_free.func(st->cb.item_free.data, remove_item->item_info);
1655                                                                     remove_item->item_info = NULL;
1656                                                                  }
1657                                                                if (remove_item->fetched)
1658                                                                  {
1659                                                                     int index = elm_store_item_index_get(remove_item);
1660                                                                     if (index != -1)
1661                                                                       {
1662                                                                          _item_unfetch(st, index);
1663                                                                       }
1664                                                                     else
1665                                                                       {
1666                                                                          return;
1667                                                                       }
1668                                                                  }
1669                                                                header_list = eina_list_remove(header_list, remove_item);
1670                                                                st->total_item_count--;
1671                                                                LKD(remove_item->lock);
1672                                                                elm_genlist_item_del(remove_item->item);
1673                                                                free(remove_item);
1674
1675                                                                if (eina_list_count(header_list) == 0)
1676                                                                  {
1677                                                                     st->header_items = eina_list_remove(st->header_items, header_list);
1678                                                                     header_list = eina_list_free(header_list);
1679                                                                  }
1680                                                                else if(eina_list_count(header_list) == 1)
1681                                                                  {
1682                                                                     Elm_Store_Item *temp_sti = eina_list_nth(header_list, 0);
1683                                                                     if(temp_sti && temp_sti->item_info)
1684                                                                       {
1685                                                                          if (temp_sti->item_info->item_type == ELM_GENLIST_ITEM_GROUP)
1686                                                                            {
1687                                                                               if (st->cb.item_free.func)
1688                                                                                 {
1689                                                                                    st->cb.item_free.func(st->cb.item_free.data, temp_sti->item_info);
1690                                                                                    temp_sti->item_info = NULL;
1691                                                                                 }
1692                                                                               if (temp_sti->fetched)
1693                                                                                 {
1694                                                                                    int index = elm_store_item_index_get(temp_sti);
1695                                                                                    if (index != -1)
1696                                                                                      {
1697                                                                                         _item_unfetch(st, index);
1698                                                                                      }
1699                                                                                    else
1700                                                                                      {
1701                                                                                         return;
1702                                                                                      }
1703                                                                                 }
1704                                                                               header_list = eina_list_remove(header_list, temp_sti);
1705                                                                               st->total_item_count--;
1706                                                                               LKD(temp_sti->lock);
1707                                                                               elm_genlist_item_del(temp_sti->item);
1708                                                                               free(temp_sti);
1709                                                                               st->header_items = eina_list_remove(st->header_items, header_list);
1710                                                                               header_list = eina_list_free(header_list);
1711                                                                            }
1712                                                                       }
1713                                                                  }
1714                                                                removed = EINA_TRUE;
1715                                                             }
1716                                                        }
1717                                                      else
1718                                                        {
1719                                                           break;
1720                                                        }
1721                                                   }
1722                                              }
1723                                         }
1724                                    }
1725                                  else if (header_item->item_info->group_index == sti->item_info->group_index)
1726                                    {
1727                                       Eina_Bool last_add = EINA_TRUE;
1728                                       Eina_List *in_l;
1729                                       Eina_List *in_l_next;
1730                                       Elm_Store_Item *comp_item;
1731
1732                                       EINA_LIST_FOREACH_SAFE(header_list, in_l, in_l_next, comp_item)
1733                                         {
1734                                            if(comp_item)
1735                                              {
1736                                                 if(last_add == EINA_FALSE)
1737                                                   {
1738                                                      comp_item->item_info->index++;
1739                                                   }
1740                                                 else
1741                                                   {
1742                                                      int sort;
1743                                                      if (st->cb.item_sort.func)
1744                                                        {
1745                                                           sort = st->cb.item_sort.func(st->cb.item_sort.data, sti->item_info, comp_item->item_info);
1746
1747                                                           if(sort == ELM_STORE_ITEM_SORT_LOW)
1748                                                             {
1749                                                                sti->item_info->index = comp_item->item_info->index;
1750                                                                comp_item->item_info->index++;
1751                                                                header_list = eina_list_prepend_relative(header_list, sti, comp_item);
1752                                                                st->total_item_count++;
1753                                                                sti->item = elm_genlist_item_insert_before(st->genlist,
1754                                                                                                           itc,
1755                                                                                                           sti,
1756                                                                                                           header_item->item,
1757                                                                                                           comp_item->item,
1758                                                                                                           ELM_GENLIST_ITEM_NONE,
1759                                                                                                           (Evas_Smart_Cb)sti->store->cb.item_select.func,
1760                                                                                                           (void *)sti->store->cb.item_select.data);
1761                                                                elm_store_item_update(sti);
1762                                                                last_add = EINA_FALSE;
1763                                                             }
1764                                                        }
1765                                                      else
1766                                                        {
1767                                                           Elm_Store_Item *last_sti = eina_list_nth(header_list, eina_list_count(header_list) - 1);
1768                                                           sti->item_info->index = eina_list_count(header_list);
1769                                                           header_list = eina_list_append(header_list, sti);
1770                                                           st->total_item_count++;
1771                                                           sti->item = elm_genlist_item_insert_after(st->genlist,
1772                                                                                                     itc,
1773                                                                                                     sti,
1774                                                                                                     header_item->item,
1775                                                                                                     last_sti->item,
1776                                                                                                     ELM_GENLIST_ITEM_NONE,
1777                                                                                                     (Evas_Smart_Cb)sti->store->cb.item_select.func,
1778                                                                                                     (void *)sti->store->cb.item_select.data);
1779                                                           elm_store_item_update(sti);
1780                                                           last_add = EINA_FALSE;
1781                                                           break;
1782                                                        }
1783                                                   }
1784                                              }
1785                                         }
1786                                       if(last_add)
1787                                         {
1788                                            Elm_Store_Item *last_sti = eina_list_nth(header_list, eina_list_count(header_list) - 1);
1789                                            sti->item_info->index = eina_list_count(header_list);
1790                                            header_list = eina_list_append(header_list, sti);
1791                                            st->total_item_count++;
1792                                            sti->item = elm_genlist_item_insert_after(st->genlist,
1793                                                                                      itc,
1794                                                                                      sti,
1795                                                                                      header_item->item,
1796                                                                                      last_sti->item,
1797                                                                                      ELM_GENLIST_ITEM_NONE,
1798                                                                                      (Evas_Smart_Cb)sti->store->cb.item_select.func,
1799                                                                                      (void *)sti->store->cb.item_select.data);
1800                                            elm_store_item_update(sti);
1801                                         }
1802                                    }
1803                               }
1804                          }
1805                     }
1806                }
1807           }
1808         else
1809           {
1810              if (st->header_items)
1811                {
1812                   Eina_Bool normal_add = EINA_TRUE;
1813                   Eina_List *l;
1814                   Eina_List *l_next;
1815                   Eina_List *header_list;
1816
1817                   EINA_LIST_FOREACH_SAFE(st->header_items, l, l_next, header_list)
1818                     {
1819                        if (header_list)
1820                          {
1821                             Elm_Store_Item *header_item = eina_list_nth(header_list, 0);
1822
1823                             if(header_item && header_item->item_info)
1824                               {
1825                                  if (header_item->item_info->group_index == sti->item_info->group_index)
1826                                    {
1827                                       Eina_List *in_l;
1828                                       Eina_List *in_l_next;
1829                                       Elm_Store_Item *comp_item;
1830
1831                                       EINA_LIST_FOREACH_SAFE(header_list, in_l, in_l_next, comp_item)
1832                                         {
1833                                            if (comp_item )
1834                                              {
1835                                                 if(normal_add == EINA_FALSE)
1836                                                   {
1837                                                      comp_item->item_info->index++;
1838                                                   }
1839                                                 else
1840                                                   {
1841                                                      int sort;
1842                                                      if (st->cb.item_sort.func)
1843                                                        {
1844                                                           sort = st->cb.item_sort.func(st->cb.item_sort.data, sti->item_info, comp_item->item_info);
1845
1846                                                           if(sort == ELM_STORE_ITEM_SORT_LOW)
1847                                                             {
1848                                                                sti->item_info->index = comp_item->item_info->index;
1849                                                                comp_item->item_info->index++;
1850                                                                header_list = eina_list_prepend_relative(header_list, sti, comp_item);
1851                                                                st->total_item_count++;
1852                                                                sti->item = elm_genlist_item_insert_before(st->genlist,
1853                                                                                                           itc,
1854                                                                                                           sti,
1855                                                                                                           header_item->item,
1856                                                                                                           comp_item->item,
1857                                                                                                           ELM_GENLIST_ITEM_NONE,
1858                                                                                                           (Evas_Smart_Cb)sti->store->cb.item_select.func,
1859                                                                                                           (void *)sti->store->cb.item_select.data);
1860                                                                normal_add = EINA_FALSE;
1861                                                                elm_store_item_update(sti);
1862                                                             }
1863                                                        }
1864                                                      else
1865                                                        {
1866                                                           Elm_Store_Item *last_sti = eina_list_nth(header_list, eina_list_count(header_list) - 1);
1867                                                           sti->item_info->index = eina_list_count(header_list);
1868                                                           header_list = eina_list_append(header_list, sti);
1869                                                           st->total_item_count++;
1870                                                           sti->item = elm_genlist_item_insert_after(st->genlist,
1871                                                                                                     itc,
1872                                                                                                     sti,
1873                                                                                                     header_item->item,
1874                                                                                                     last_sti->item,
1875                                                                                                     ELM_GENLIST_ITEM_NONE,
1876                                                                                                     (Evas_Smart_Cb)sti->store->cb.item_select.func,
1877                                                                                                     (void *)sti->store->cb.item_select.data);
1878                                                           normal_add = EINA_FALSE;
1879                                                           elm_store_item_update(sti);
1880                                                           break;
1881                                                        }
1882                                                   }
1883                                              }
1884                                         }
1885                                       if(normal_add)
1886                                         {
1887                                            Elm_Store_Item *last_sti = eina_list_nth(header_list, eina_list_count(header_list) - 1);
1888                                            sti->item_info->index = eina_list_count(header_list);
1889                                            header_list = eina_list_append(header_list, sti);
1890                                            st->total_item_count++;
1891                                            sti->item = elm_genlist_item_insert_after(st->genlist,
1892                                                                                      itc,
1893                                                                                      sti,
1894                                                                                      header_item->item,
1895                                                                                      last_sti->item,
1896                                                                                      ELM_GENLIST_ITEM_NONE,
1897                                                                                      (Evas_Smart_Cb)sti->store->cb.item_select.func,
1898                                                                                      (void *)sti->store->cb.item_select.data);
1899                                            normal_add = EINA_FALSE;
1900                                            elm_store_item_update(sti);
1901                                         }
1902                                       if(normal_add == EINA_FALSE)
1903                                         {
1904                                            break;
1905                                         }
1906                                    }
1907                               }
1908                          }
1909                     }
1910                   if (normal_add)
1911                     {
1912                        Eina_List *new_header_list = NULL;
1913                        sti->item_info->index = 0;
1914                        new_header_list = eina_list_append(new_header_list, sti);
1915                        st->total_item_count++;
1916                        st->header_items = eina_list_append(st->header_items, new_header_list);
1917                        sti->item = elm_genlist_item_append(st->genlist,
1918                                                            itc,
1919                                                            sti,
1920                                                            NULL,
1921                                                            ELM_GENLIST_ITEM_NONE,
1922                                                            (Evas_Smart_Cb)sti->store->cb.item_select.func,
1923                                                            (void *)sti->store->cb.item_select.data);
1924                        elm_store_item_update(sti);
1925                     }
1926                }
1927              else
1928                {
1929                   if (st->live)
1930                     {
1931                        Eina_List *new_header_list = NULL;
1932                        sti->item_info->index = 0;
1933                        new_header_list = eina_list_append(new_header_list, sti);
1934                        st->total_item_count++;
1935                        st->header_items = eina_list_append(st->header_items, new_header_list);
1936                        sti->item = elm_genlist_item_append(st->genlist,
1937                                                            itc,
1938                                                            sti,
1939                                                            NULL,
1940                                                            ELM_GENLIST_ITEM_NONE,
1941                                                            (Evas_Smart_Cb)sti->store->cb.item_select.func,
1942                                                            (void *)sti->store->cb.item_select.data);
1943                        elm_store_item_update(sti);
1944                     }
1945                }
1946           }
1947      }
1948 }
1949
1950 static void
1951 _item_free(Elm_Store_Item *sti)
1952 {
1953    if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return;
1954    elm_store_item_del(sti);
1955 }
1956
1957 static void
1958 _store_free(Elm_Store *st)
1959 {
1960    if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
1961
1962    Elm_Store_DBsystem *std = (Elm_Store_DBsystem *)st;
1963    eina_stringshare_del(std->p_db);
1964    elm_store_free(st);
1965 }
1966
1967 /**
1968  * Add a new dbsystem Store object
1969  *
1970  * @return The new object or NULL if it cannot be created
1971  *
1972  * @ingroup Store
1973  */
1974 EAPI Elm_Store *
1975 elm_store_dbsystem_new(void)
1976 {
1977    Elm_Store_DBsystem *std = _store_new(Elm_Store_DBsystem);
1978    EINA_SAFETY_ON_NULL_RETURN_VAL(std, NULL);
1979
1980    EINA_MAGIC_SET(std, ELM_STORE_DBSYSTEM_MAGIC);
1981    std->base.free = _store_free;
1982    std->base.item.free = _item_free;
1983    return &std->base;
1984 }
1985
1986 /**
1987  * Sets the item count of a store
1988  *
1989  * @param st The store object
1990  * @param count The item count of an store
1991  *
1992  * @ingroup Store
1993  */
1994 EAPI void
1995 elm_store_item_count_set(Elm_Store *st, int count)
1996 {
1997    EINA_SAFETY_ON_NULL_RETURN(st);
1998    if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
1999
2000    st->item_count = count;
2001    if (count > 0)
2002      {
2003         st->multi_load = EINA_TRUE;
2004      }
2005    else
2006      {
2007         st->multi_load = EINA_FALSE;
2008      }
2009 }
2010
2011
2012 /**
2013  * Set the select func that select the state of a list item whether true or false
2014  *
2015  * @param st The store object
2016  * @param func The select cb function of an store
2017  * @param data The new data pointer to set
2018  *
2019  * @ingroup Store
2020  */
2021 EAPI void
2022 elm_store_item_select_func_set(Elm_Store *st, Elm_Store_Item_Select_Cb func, const void *data)
2023 {
2024    EINA_SAFETY_ON_NULL_RETURN(st);
2025    if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
2026
2027    st->cb.item_select.func = func;
2028    st->cb.item_select.data = (void *)data;
2029 }
2030
2031 /**
2032  * Sets the sort func that sort the item with a next in the list
2033  *
2034  * @param st The store object
2035  * @param func The sort cb function of an store
2036  * @param data The new data pointer to set
2037  *
2038  * @ingroup Store
2039  */
2040 EAPI void
2041 elm_store_item_sort_func_set(Elm_Store *st, Elm_Store_Item_Sort_Cb func, const void *data)
2042 {
2043    EINA_SAFETY_ON_NULL_RETURN(st);
2044    if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
2045
2046    st->cb.item_sort.func = func;
2047    st->cb.item_sort.data = (void *)data;
2048 }
2049
2050 /**
2051  * Set the store item free func
2052  *
2053  * @param st The store object
2054  * @param func The free cb function of an store
2055  * @param data The new data pointer to set
2056  *
2057  * @ingroup Store
2058  */
2059 EAPI void
2060 elm_store_item_free_func_set(Elm_Store *st, Elm_Store_Item_Free_Cb func, const void *data)
2061 {
2062    EINA_SAFETY_ON_NULL_RETURN(st);
2063    if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
2064
2065    st->cb.item_free.func = func;
2066    st->cb.item_free.data = (void *)data;
2067 }
2068
2069 /**
2070  * Get the item index that included header items
2071  *
2072  * @param sti The store item object
2073  * @return The item index in genlist
2074  *
2075  * @ingroup Store
2076  */
2077 EAPI int
2078 elm_store_item_index_get(const Elm_Store_Item *sti)
2079 {
2080    EINA_SAFETY_ON_NULL_RETURN_VAL(sti, -1);
2081    if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return -1;
2082    Elm_Store *st = sti->store;
2083
2084    if (st->live)
2085      {
2086         int index = 0;
2087         Eina_List *l;
2088         Eina_List *l_next;
2089         Eina_List *header_list;
2090
2091         EINA_LIST_FOREACH_SAFE(st->header_items, l, l_next, header_list)
2092           {
2093              if (header_list)
2094                {
2095                   Elm_Store_Item *temp_sti = eina_list_nth(header_list, 0);
2096                   if(temp_sti && temp_sti->item_info && sti->item_info)
2097                     {
2098                        if (sti->item_info->group_index == temp_sti->item_info->group_index)
2099                          {
2100                             Eina_List *in_l;
2101                             Eina_List *in_l_next;
2102                             Elm_Store_Item *comp_item;
2103
2104                             EINA_LIST_FOREACH_SAFE(header_list, in_l, in_l_next, comp_item)
2105                               {
2106                                  if(comp_item)
2107                                    {
2108                                       if (comp_item->item_info->index == sti->item_info->index)
2109                                         {
2110                                            return index;
2111                                         }
2112                                       else
2113                                         {
2114                                            index++;
2115                                         }
2116                                    }
2117                               }
2118                          }
2119                        else
2120                          {
2121                             index = index + eina_list_count(header_list);
2122                          }
2123                     }
2124                }
2125           }
2126         return -1;
2127      }
2128    else
2129      {
2130         return -1;
2131      }
2132 }
2133
2134 /**
2135  * Get the item index of real data that don't included header items
2136  *
2137  * @param sti The store item object
2138  * @return The real item index
2139  *
2140  * @ingroup Store
2141  */
2142 EAPI int
2143 elm_store_item_data_index_get(const Elm_Store_Item *sti)
2144 {
2145    EINA_SAFETY_ON_NULL_RETURN_VAL(sti, -1);
2146    if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return -1;
2147    Elm_Store *st = sti->store;
2148
2149    if (st->live)
2150      {
2151         if (sti->item_info->item_type == ELM_GENLIST_ITEM_NONE)
2152           {
2153              int index = 0;
2154              int group_item_count = 0;
2155              Eina_List *l;
2156              Eina_List *l_next;
2157              Eina_List *header_list;
2158
2159              EINA_LIST_FOREACH_SAFE(st->header_items, l, l_next, header_list)
2160                {
2161                   if (header_list)
2162                     {
2163                        Elm_Store_Item *temp_sti = eina_list_nth(header_list, 0);
2164                        if(temp_sti && temp_sti->item_info && sti->item_info)
2165                          {
2166
2167                             if(temp_sti->item_info->item_type == ELM_GENLIST_ITEM_GROUP)
2168                               {
2169                                  group_item_count++;
2170                               }
2171
2172                             if (temp_sti->item_info->group_index == sti->item_info->group_index)
2173                               {
2174                                  Eina_List *in_l;
2175                                  Eina_List *in_l_next;
2176                                  Elm_Store_Item *comp_item;
2177
2178                                  EINA_LIST_FOREACH_SAFE(header_list, in_l, in_l_next, comp_item)
2179                                    {
2180                                       if(comp_item)
2181                                         {
2182                                            if (comp_item->item_info->index == sti->item_info->index)
2183                                              {
2184                                                 return (index - group_item_count);
2185                                              }
2186                                            else
2187                                              {
2188                                                 index++;
2189                                              }
2190                                         }
2191                                    }
2192                               }
2193                          }
2194                        else
2195                          {
2196                             index = index + eina_list_count(header_list);
2197                          }
2198                     }
2199                }
2200           }
2201         return -1;
2202      }
2203    else
2204      {
2205         return -1;
2206      }
2207 }
2208
2209 /**
2210  * Get the DB pointer of an item
2211  *
2212  * @param sti The store item object
2213  * @return The DB pointer of item
2214  *
2215  * @ingroup Store
2216  */
2217 EAPI void *
2218 elm_store_dbsystem_db_get(const Elm_Store_Item *sti)
2219 {
2220    if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return NULL;
2221
2222    const Elm_Store_DBsystem *std = (const Elm_Store_DBsystem *)sti->store;
2223    if (!EINA_MAGIC_CHECK(sti->store, ELM_STORE_MAGIC)) return NULL;
2224    if (!EINA_MAGIC_CHECK(std, ELM_STORE_DBSYSTEM_MAGIC)) return NULL;
2225    return std->p_db;
2226 }
2227
2228 /**
2229  * Set the DB pointer of an item
2230  *
2231  * @param sti The store item object
2232  * @parm p_db The DB pointer of item
2233  *
2234  * @ingroup Store
2235  */
2236 EAPI void
2237 elm_store_dbsystem_db_set(Elm_Store *store, void *p_db)
2238 {
2239    Elm_Store_DBsystem *std = (Elm_Store_DBsystem *)store;
2240    if (!EINA_MAGIC_CHECK(store, ELM_STORE_MAGIC)) return;
2241    if (!EINA_MAGIC_CHECK(std, ELM_STORE_DBSYSTEM_MAGIC)) return;
2242
2243    std->p_db = p_db;
2244
2245    if (store->list_th)
2246      {
2247         ecore_thread_cancel(store->list_th);
2248         store->list_th = NULL;
2249      }
2250    store->list_th = ecore_thread_feedback_run(_list_do, _list_update, _list_end, _list_cancel, store, EINA_TRUE);
2251 }
2252
2253 /**
2254  * Append the item to the genlist
2255  *
2256  * @param st The store object
2257  * @param info The store item info dbsystem object
2258  * @return The item of store
2259  *
2260  * @ingroup Store
2261  */
2262 EAPI Elm_Store_Item *
2263 elm_store_item_add(Elm_Store *st, Elm_Store_Item_Info *info)
2264 {
2265    EINA_SAFETY_ON_NULL_RETURN_VAL(st, NULL);
2266    if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return NULL;
2267    EINA_SAFETY_ON_NULL_RETURN_VAL(info, NULL);
2268    Elm_Store_Item *sti;
2269    Elm_Genlist_Item_Class *itc;
2270
2271    sti = calloc(1, sizeof(Elm_Store_Item));
2272    if (!sti) return NULL;
2273
2274    LKI(sti->lock);
2275    EINA_MAGIC_SET(sti, ELM_STORE_ITEM_MAGIC);
2276
2277    sti->store = st;
2278    sti->item_info = info;
2279    sti->fetched = EINA_FALSE;
2280
2281    itc = info->item_class;
2282    if (!itc) itc = &_store_item_class;
2283    else
2284      {
2285         itc->func.label_get = (GenlistItemLabelGetFunc)_item_label_get;
2286         itc->func.icon_get = (GenlistItemIconGetFunc)_item_icon_get;
2287         itc->func.state_get = NULL;
2288         itc->func.del = NULL;
2289      }
2290
2291    if (st->live)
2292      {
2293         if (sti->item_info->item_type == ELM_GENLIST_ITEM_GROUP)
2294           {
2295              _group_item_append(sti, itc);
2296           }
2297         else
2298           {
2299              _normal_item_append(sti, itc);
2300           }
2301         return sti;
2302      }
2303    else
2304      {
2305         return NULL;
2306      }
2307 }
2308
2309 /**
2310  * Realize the visible items to the screen
2311  *
2312  * @param st The store object
2313  *
2314  * @ingroup Store
2315  */
2316 EAPI void
2317 elm_store_visible_items_update(Elm_Store *st)
2318 {
2319    EINA_SAFETY_ON_NULL_RETURN(st);
2320    if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
2321
2322    Eina_List *realized_list = elm_genlist_realized_items_get(st->genlist);
2323    if(realized_list)
2324      {
2325         Eina_List *l;
2326         Elm_Genlist_Item *it;
2327         EINA_LIST_FOREACH(realized_list, l, it)
2328           {
2329              if(it)
2330                {
2331                   Elm_Store_Item *realized_sti = elm_genlist_item_data_get(it);
2332                   int index = elm_store_item_index_get(realized_sti);
2333                   if (index != -1)
2334                     {
2335                        if(realized_sti->fetched)
2336                          {
2337                             _item_unfetch(st, index);
2338                          }
2339                        _item_fetch(st, index);
2340                        if (realized_sti->data) elm_genlist_item_update(realized_sti->item);
2341                     }
2342                   else
2343                     {
2344                        return;
2345                     }
2346                }
2347           }
2348      }
2349 }
2350
2351 /**
2352  * Realize the item to the screen
2353  *
2354  * @param sti The store item object
2355  *
2356  * @ingroup Store
2357  */
2358 EAPI void
2359 elm_store_item_update(Elm_Store_Item *sti)
2360 {
2361    EINA_SAFETY_ON_NULL_RETURN(sti);
2362    if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return;
2363    Elm_Store *st = sti->store;
2364
2365    int index = elm_store_item_index_get(sti);
2366    if (index != -1)
2367      {
2368         if ((st->start_fetch_index <= index) && (index <= (st->start_fetch_index + st->cache_max)))
2369           {
2370              if (sti->fetched)
2371                {
2372                   _item_unfetch(st, index);
2373                }
2374              _item_fetch(st, index);
2375
2376              if(st->end_fetch_index < (st->total_item_count-1))
2377                {
2378                   if( (st->end_fetch_index - st->cache_max) == st->start_fetch_index)
2379                     {
2380                        _item_unfetch(st, (st->total_item_count-1));
2381                     }
2382                   else
2383                     {
2384                        st->end_fetch_index = (st->total_item_count-1);
2385                     }
2386                }
2387              if(sti->data) elm_genlist_item_update(sti->item);
2388           }
2389      }
2390    else
2391      {
2392         return;
2393      }
2394 }
2395
2396 /**
2397  * Delete the item of genlist
2398  *
2399  * @param sti The store item object
2400  *
2401  * @ingroup Store
2402  */
2403 EAPI void
2404 elm_store_item_del(Elm_Store_Item *sti)
2405 {
2406    EINA_SAFETY_ON_NULL_RETURN(sti);
2407    if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return;
2408    Elm_Store *st = sti->store;
2409
2410    Eina_List *l;
2411    Eina_List*l_next;
2412    Eina_List *header_list;
2413
2414    if (st->live)
2415      {
2416         EINA_LIST_FOREACH_SAFE(st->header_items, l, l_next, header_list)
2417           {
2418              if (header_list)
2419                {
2420                   Elm_Store_Item *header_item = eina_list_nth(header_list, 0);
2421                   if(header_item && header_item->item_info && sti->item_info)
2422                     {
2423
2424                        if (header_item->item_info->group_index == sti->item_info->group_index)
2425                          {
2426                             Eina_Bool removed = EINA_FALSE;
2427                             Eina_List *in_l;
2428                             Eina_List *in_l_next;
2429                             Elm_Store_Item *remove_sti;
2430                             EINA_LIST_FOREACH_SAFE(header_list, in_l, in_l_next, remove_sti)
2431                               {
2432                                  if(remove_sti)
2433                                    {
2434                                       if (removed == EINA_TRUE)
2435                                         {
2436                                            remove_sti->item_info->index--;
2437                                         }
2438                                       else
2439                                         {
2440                                            if (remove_sti->item_info->index == sti->item_info->index)
2441                                              {
2442                                                 if (st->cb.item_free.func)
2443                                                   {
2444                                                      st->cb.item_free.func(st->cb.item_free.data, remove_sti->item_info);
2445                                                      remove_sti->item_info = NULL;
2446                                                   }
2447                                                 if (remove_sti->fetched)
2448                                                   {
2449                                                      int index = elm_store_item_index_get(remove_sti);
2450                                                      if (index != -1)
2451                                                        {
2452                                                           _item_unfetch(st, index);
2453                                                        }
2454                                                      else
2455                                                        {
2456                                                           return;
2457                                                        }
2458                                                   }
2459                                                 header_list = eina_list_remove(header_list, remove_sti);
2460                                                 st->total_item_count--;
2461                                                 LKD(remove_sti->lock);
2462                                                 elm_genlist_item_del(remove_sti->item);
2463                                                 free(remove_sti);
2464
2465                                                 if (eina_list_count(header_list) == 0)
2466                                                   {
2467                                                      st->header_items = eina_list_remove(st->header_items, header_list);
2468                                                      header_list = eina_list_free(header_list);
2469                                                   }
2470                                                 else if (eina_list_count(header_list) == 1)
2471                                                   {
2472                                                      Elm_Store_Item *temp_sti = eina_list_nth(header_list, 0);
2473                                                      if(temp_sti && temp_sti->item_info)
2474                                                        {
2475                                                           if (temp_sti->item_info->item_type == ELM_GENLIST_ITEM_GROUP)
2476                                                             {
2477                                                                if (st->cb.item_free.func)
2478                                                                  {
2479                                                                     st->cb.item_free.func(st->cb.item_free.data, temp_sti->item_info);
2480                                                                     temp_sti->item_info = NULL;
2481                                                                  }
2482                                                                if (temp_sti->fetched)
2483                                                                  {
2484                                                                     int index = elm_store_item_index_get(temp_sti);
2485                                                                     if (index != -1)
2486                                                                       {
2487                                                                          _item_unfetch(st, index);
2488                                                                       }
2489                                                                     else
2490                                                                       {
2491                                                                          return;
2492                                                                       }
2493                                                                  }
2494                                                                header_list = eina_list_remove(header_list, temp_sti);
2495                                                                st->total_item_count--;
2496                                                                LKD(temp_sti->lock);
2497                                                                elm_genlist_item_del(temp_sti->item);
2498                                                                free(temp_sti);
2499                                                                st->header_items = eina_list_remove(st->header_items, header_list);
2500                                                                header_list = eina_list_free(header_list);
2501                                                             }
2502                                                        }
2503                                                   }
2504                                                 removed = EINA_TRUE;
2505                                              }
2506                                         }
2507                                    }
2508                               }
2509                          }
2510                     }
2511                }
2512           }
2513      }
2514 }
2515
2516 // TODO: END -DBsystem store
2517