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