1 #include <Elementary.h>
2 #include <Elementary_Cursor.h>
5 #ifndef EFL_HAVE_THREADS
6 # error "No thread support. Required."
9 #ifdef EFL_HAVE_POSIX_THREADS
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
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)
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
37 void (*free)(Elm_Store *store);
39 void (*free)(Elm_Store_Item *item);
42 Ecore_Thread *list_th;
47 int start_fetch_index;
53 Eina_List *header_items;
56 Elm_Store_Item_List_Cb func;
60 Elm_Store_Item_Fetch_Cb func;
64 Elm_Store_Item_Unfetch_Cb func;
68 Elm_Store_Item_Select_Cb func;
72 Elm_Store_Item_Sort_Cb func;
76 Elm_Store_Item_Free_Cb func;
81 Eina_Bool fetch_thread : 1;
82 Eina_Bool multi_load : 1;
86 struct _Elm_Store_Item
91 Elm_Genlist_Item *item;
92 Ecore_Thread *fetch_th;
94 const Elm_Store_Item_Mapping *mapping;
96 Elm_Store_Item_Info *item_info;
99 Eina_Bool was_live : 1;
100 Eina_Bool realized : 1;
101 Eina_Bool fetched : 1;
104 struct _Elm_Store_Filesystem
111 struct _Elm_Store_Item_Filesystem
117 struct _Elm_Store_DBsystem
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;
133 static Elm_Genlist_Item_Class _store_item_class;
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);
146 _store_cache_trim(Elm_Store *st)
148 while ((st->realized ) &&
149 (((int)eina_list_count(st->realized) - st->realized_count)
152 Elm_Store_Item *sti = st->realized->data;
155 st->realized = eina_list_remove_list(st->realized, st->realized);
156 sti->realized = EINA_FALSE;
164 ecore_thread_cancel(sti->fetch_th);
165 sti->fetch_th = NULL;
169 sti->fetched = EINA_FALSE;
171 if (st->cb.unfetch.func)
172 st->cb.unfetch.func(st->cb.unfetch.data, sti, NULL);
180 _store_genlist_del(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
182 Elm_Store *st = data;
186 ecore_thread_cancel(st->list_th);
189 eina_list_free(st->realized);
192 Elm_Store_Item *sti = (Elm_Store_Item *)st->items;
193 if (sti->eval_job) ecore_job_del(sti->eval_job);
196 ecore_thread_cancel(sti->fetch_th);
197 sti->fetch_th = NULL;
199 if (sti->store->item.free) sti->store->item.free(sti);
202 if (st->cb.unfetch.func)
203 st->cb.unfetch.func(st->cb.unfetch.data, sti, NULL);
209 // FIXME: kill threads and more
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 */
217 _store_filesystem_fetch_do(void *data, Ecore_Thread *th __UNUSED__)
219 Elm_Store_Item *sti = data;
229 if (sti->store->cb.fetch.func)
230 sti->store->cb.fetch.func(sti->store->cb.fetch.data, sti, NULL);
232 sti->fetched = EINA_TRUE;
236 // ************************************************************************
237 //// * End of separate thread function. *
238 ////// ************************************************************************
239 /* TODO: refactor lock part into core? this does not depend on filesystm part */
241 _store_filesystem_fetch_end(void *data, Ecore_Thread *th)
243 Elm_Store_Item *sti = data;
245 if (sti->data) elm_genlist_item_update(sti->item);
247 if (th == sti->fetch_th) sti->fetch_th = NULL;
250 /* TODO: refactor lock part into core? this does not depend on filesystm part */
252 _store_filesystem_fetch_cancel(void *data, Ecore_Thread *th)
254 Elm_Store_Item *sti = data;
256 if (th == sti->fetch_th) sti->fetch_th = NULL;
257 if (sti->data) elm_genlist_item_update(sti->item);
262 _store_item_eval(void *data)
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;
270 _store_cache_trim(sti->store);
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,
280 else if ((!sti->store->fetch_thread))
282 _store_filesystem_fetch_do(sti, NULL);
283 _store_filesystem_fetch_end(sti, NULL);
290 ecore_thread_cancel(sti->fetch_th);
291 sti->fetch_th = NULL;
293 _store_cache_trim(sti->store);
298 _store_genlist_item_realized(void *data, Evas_Object *obj __UNUSED__, void *event_info)
300 Elm_Store *st = data;
301 Elm_Genlist_Item *gli = event_info;
302 Elm_Store_Item *sti = elm_genlist_item_data_get(gli);
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);
311 _store_genlist_item_unrealized(void *data, Evas_Object *obj __UNUSED__, void *event_info)
313 Elm_Store *st = data;
314 Elm_Genlist_Item *gli = event_info;
315 Elm_Store_Item *sti = elm_genlist_item_data_get(gli);
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);
323 static const Elm_Store_Item_Mapping *
324 _store_item_mapping_find(Elm_Store_Item *sti, const char *part)
326 const Elm_Store_Item_Mapping *m;
328 for (m = sti->mapping; m; m ++)
330 if (m->type == ELM_STORE_ITEM_MAPPING_NONE) break;
331 if (!strcmp(part, m->part)) return m;
337 _store_item_label_get(void *data, Evas_Object *obj __UNUSED__, const char *part)
339 Elm_Store_Item *sti = data;
344 const Elm_Store_Item_Mapping *m = _store_item_mapping_find(sti, part);
349 case ELM_STORE_ITEM_MAPPING_LABEL:
350 s = *(char **)(((unsigned char *)sti->data) + m->offset);
352 case ELM_STORE_ITEM_MAPPING_CUSTOM:
353 if (m->details.custom.func)
354 s = m->details.custom.func(sti->data, sti, part);
366 _store_item_icon_get(void *data, Evas_Object *obj, const char *part)
368 Elm_Store_Item *sti = data;
372 const Elm_Store_Item_Mapping *m = _store_item_mapping_find(sti, part);
375 Evas_Object *ic = NULL;
376 const char *s = NULL;
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,
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);
395 if (m->details.icon.standard_name)
396 elm_icon_standard_set(ic, s);
398 elm_icon_file_set(ic, s, NULL);
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);
406 elm_photo_file_set(ic, s);
408 case ELM_STORE_ITEM_MAPPING_CUSTOM:
409 if (m->details.custom.func)
410 ic = m->details.custom.func(sti->data, sti, part);
424 _store_item_del(void *data __UNUSED__, Evas_Object *obj __UNUSED__)
428 ////// **** WARNING ***********************************************************
429 //// * This function runs inside a thread outside efl mainloop. Be careful! *
430 // ************************************************************************
432 _store_filesystem_sort_cb(void *d1, void *d2)
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);
440 _store_filesystem_list_do(void *data, Ecore_Thread *th __UNUSED__)
442 Elm_Store_Filesystem *st = data;
444 const Eina_File_Direct_Info *finf;
445 Eina_List *sorted = NULL;
446 Elm_Store_Item_Info_Filesystem *info;
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);
452 EINA_ITERATOR_FOREACH(it, finf)
455 size_t pathsz = finf->path_length + 1;
457 info = calloc(1, sizeof(Elm_Store_Item_Info_Filesystem) + pathsz);
459 info->path = ((char *)info) + sizeof(Elm_Store_Item_Info_Filesystem);
460 memcpy(info->path, finf->path, pathsz);
462 if (st->base.cb.list.func)
463 ok = st->base.cb.list.func(st->base.cb.list.data, &info->base);
466 if (!st->base.sorted) ecore_thread_feedback(th, info);
467 else sorted = eina_list_append(sorted, info);
471 if (info->base.sort_id) free(info->base.sort_id);
474 if (ecore_thread_check(th)) break;
476 eina_iterator_free(it);
479 sorted = eina_list_sort(sorted, 0,
480 EINA_COMPARE_CB(_store_filesystem_sort_cb));
481 EINA_LIST_FREE(sorted, info)
483 if (!ecore_thread_check(th)) ecore_thread_feedback(th, info);
487 // ************************************************************************
488 //// * End of separate thread function. *
489 ////// ************************************************************************
492 _store_filesystem_list_end(void *data, Ecore_Thread *th)
494 Elm_Store *st = data;
495 if (th == st->list_th) st->list_th = NULL;
499 _store_filesystem_list_cancel(void *data, Ecore_Thread *th)
501 Elm_Store *st = data;
502 if (th == st->list_th) st->list_th = NULL;
506 _store_filesystem_list_update(void *data, Ecore_Thread *th __UNUSED__, void *msg)
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;
513 sti = calloc(1, sizeof(Elm_Store_Item_Filesystem));
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);
522 itc = info->base.item_class;
523 if (!itc) itc = &_store_item_class;
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;
532 // FIXME: handle being a parent (tree)
533 sti->base.item = elm_genlist_item_append(st->genlist, itc,
536 ELM_GENLIST_ITEM_NONE,
538 NULL/* func data */);
539 st->items = eina_inlist_append(st->items, (Eina_Inlist *)sti);
541 if (info->base.sort_id) free(info->base.sort_id);
547 _elm_store_new(size_t size)
549 Elm_Store *st = calloc(1, size);
550 EINA_SAFETY_ON_NULL_RETURN_VAL(st, NULL);
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()
564 EINA_MAGIC_SET(st, ELM_STORE_MAGIC);
566 st->fetch_thread = EINA_TRUE;
570 #define elm_store_new(type) (type*)_elm_store_new(sizeof(type))
573 _elm_store_filesystem_free(Elm_Store *store)
575 Elm_Store_Filesystem *st = (Elm_Store_Filesystem *)store;
576 eina_stringshare_del(st->dir);
580 _elm_store_filesystem_item_free(Elm_Store_Item *item)
582 Elm_Store_Item_Filesystem *sti = (Elm_Store_Item_Filesystem *)item;
583 eina_stringshare_del(sti->path);
587 elm_store_filesystem_new(void)
589 Elm_Store_Filesystem *st = elm_store_new(Elm_Store_Filesystem);
590 EINA_SAFETY_ON_NULL_RETURN_VAL(st, NULL);
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;
600 elm_store_free(Elm_Store *st)
602 void (*item_free)(Elm_Store_Item *);
603 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
606 ecore_thread_cancel(st->list_th);
612 eina_list_free(st->realized);
613 item_free = st->item.free;
616 Elm_Store_Item *sti = (Elm_Store_Item *)st->items;
617 if (sti->eval_job) ecore_job_del(sti->eval_job);
620 ecore_thread_cancel(sti->fetch_th);
621 sti->fetch_th = NULL;
623 if (item_free) item_free(sti);
626 if (st->cb.unfetch.func)
627 st->cb.unfetch.func(st->cb.unfetch.data, sti, NULL);
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);
641 if (st->free) st->free(st);
645 st->live = EINA_FALSE;
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);
656 Eina_List *header_list;
658 EINA_LIST_FOREACH_SAFE(st->header_items, l, l_next, header_list)
663 Eina_List *in_l_next;
665 EINA_LIST_FOREACH_SAFE(header_list, in_l, in_l_next, sti)
669 if (st->fetch_thread && sti->fetch_th)
671 ecore_thread_cancel(sti->fetch_th);
672 sti->fetch_th = NULL;
676 int index = elm_store_item_index_get(sti);
677 if (index != -1) _item_unfetch(st, index);
679 if (st->cb.item_free.func)
681 st->cb.item_free.func(st->cb.item_free.data, sti->item_info);
682 sti->item_info = NULL;
687 st->header_items = eina_list_remove(st->header_items, header_list);
688 header_list = eina_list_free(header_list);
691 st->header_items = eina_list_free(st->header_items);
697 elm_store_target_genlist_set(Elm_Store *st, Evas_Object *obj)
699 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
700 if (st->genlist == obj) return;
705 evas_object_event_callback_del_full(st->genlist, EVAS_CALLBACK_DEL, _store_genlist_del, st);
706 evas_object_smart_callback_del(st->genlist, "realized", _store_genlist_item_realized);
707 evas_object_smart_callback_del(st->genlist, "unrealized", _store_genlist_item_unrealized);
711 evas_object_event_callback_del_full(st->genlist, EVAS_CALLBACK_DEL, _genlist_del, st);
712 evas_object_smart_callback_del(st->genlist, "realized", _item_realized);
713 evas_object_smart_callback_del(st->genlist, "unrealized", _item_unrealized);
715 elm_genlist_clear(st->genlist);
718 if (!st->genlist) return;
721 evas_object_smart_callback_add(st->genlist, "realized", _store_genlist_item_realized, st);
722 evas_object_smart_callback_add(st->genlist, "unrealized", _store_genlist_item_unrealized, st);
723 evas_object_event_callback_add(st->genlist, EVAS_CALLBACK_DEL, _store_genlist_del, st);
727 evas_object_smart_callback_add(st->genlist, "realized", _item_realized, st);
728 evas_object_smart_callback_add(st->genlist, "unrealized", _item_unrealized, st);
729 evas_object_event_callback_add(st->genlist, EVAS_CALLBACK_DEL, _genlist_del, st);
730 st->block_count = elm_genlist_block_count_get(st->genlist);
732 elm_genlist_clear(st->genlist);
736 elm_store_filesystem_directory_set(Elm_Store *store, const char *dir)
738 Elm_Store_Filesystem *st = (Elm_Store_Filesystem *)store;
739 if (!EINA_MAGIC_CHECK(store, ELM_STORE_MAGIC)) return;
740 if (!EINA_MAGIC_CHECK(st, ELM_STORE_FILESYSTEM_MAGIC)) return;
743 ecore_thread_cancel(store->list_th);
744 store->list_th = NULL;
746 if (!eina_stringshare_replace(&st->dir, dir)) return;
747 store->list_th = ecore_thread_feedback_run(_store_filesystem_list_do,
748 _store_filesystem_list_update,
749 _store_filesystem_list_end,
750 _store_filesystem_list_cancel,
755 elm_store_filesystem_directory_get(const Elm_Store *store)
757 const Elm_Store_Filesystem *st = (const Elm_Store_Filesystem *)store;
758 if (!EINA_MAGIC_CHECK(store, ELM_STORE_MAGIC)) return NULL;
759 if (!EINA_MAGIC_CHECK(st, ELM_STORE_FILESYSTEM_MAGIC)) return NULL;
764 elm_store_cache_set(Elm_Store *st, int max)
766 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
767 if (max < 0) max = 0;
769 if(!st->type) _store_cache_trim(st);
773 elm_store_cache_get(const Elm_Store *st)
775 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return 0;
776 return st->cache_max;
780 elm_store_list_func_set(Elm_Store *st, Elm_Store_Item_List_Cb func, const void *data)
782 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
783 st->cb.list.func = func;
784 st->cb.list.data = (void *)data;
788 elm_store_fetch_func_set(Elm_Store *st, Elm_Store_Item_Fetch_Cb func, const void *data)
790 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
791 st->cb.fetch.func = func;
792 st->cb.fetch.data = (void *)data;
796 elm_store_fetch_thread_set(Elm_Store *st, Eina_Bool use_thread)
798 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
799 st->fetch_thread = !!use_thread;
803 elm_store_fetch_thread_get(const Elm_Store *st)
805 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return EINA_FALSE;
806 return st->fetch_thread;
810 elm_store_unfetch_func_set(Elm_Store *st, Elm_Store_Item_Unfetch_Cb func, const void *data)
812 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
813 st->cb.unfetch.func = func;
814 st->cb.unfetch.data = (void *)data;
818 elm_store_sorted_set(Elm_Store *st, Eina_Bool sorted)
820 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
825 elm_store_sorted_get(const Elm_Store *st)
827 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return EINA_FALSE;
832 elm_store_item_data_set(Elm_Store_Item *sti, void *data)
834 if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return;
841 elm_store_item_data_get(Elm_Store_Item *sti)
843 if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return NULL;
851 EAPI const Elm_Store *
852 elm_store_item_store_get(const Elm_Store_Item *sti)
854 if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return NULL;
859 EAPI const Elm_Genlist_Item *
860 elm_store_item_genlist_item_get(const Elm_Store_Item *sti)
862 if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return NULL;
868 elm_store_item_filesystem_path_get(const Elm_Store_Item *item)
870 Elm_Store_Item_Filesystem *sti = (Elm_Store_Item_Filesystem *)item;
871 Elm_Store_Filesystem *st;
872 if (!EINA_MAGIC_CHECK(item, ELM_STORE_ITEM_MAGIC)) return NULL;
873 if (!EINA_MAGIC_CHECK(item->store, ELM_STORE_MAGIC)) return NULL;
874 /* ensure we're dealing with filesystem item */
875 st = (Elm_Store_Filesystem *)item->store;
876 if (!EINA_MAGIC_CHECK(st, ELM_STORE_FILESYSTEM_MAGIC)) return NULL;
881 // TODO: BEGIN -DBsystem store
884 _store_init(size_t size)
886 Elm_Store *st = calloc(1, size);
887 if (!st) return NULL;
889 eina_magic_string_set(ELM_STORE_MAGIC, "Elm_Store");
890 eina_magic_string_set(ELM_STORE_FILESYSTEM_MAGIC, "Elm_Store_Filesystem");
891 eina_magic_string_set(ELM_STORE_ITEM_MAGIC, "Elm_Store_Item");
892 eina_magic_string_set(ELM_STORE_DBSYSTEM_MAGIC, "Elm_Store_DBsystem");
894 _store_item_class.item_style = "default";
895 _store_item_class.func.label_get = (GenlistItemLabelGetFunc)_item_label_get;
896 _store_item_class.func.icon_get = (GenlistItemIconGetFunc)_item_icon_get;
897 _store_item_class.func.state_get = NULL;
898 _store_item_class.func.del = NULL;
900 EINA_MAGIC_SET(st, ELM_STORE_MAGIC);
901 st->cache_max = CACHE_COUNT;
902 st->start_fetch_index = 0;
903 st->end_fetch_index = 0;
904 st->live = EINA_TRUE;
905 st->multi_load = EINA_FALSE;
906 st->total_item_count = 0;
907 st->fetch_thread = EINA_FALSE;
912 #define _store_new(type) (type *)_store_init(sizeof(type))
915 _genlist_del(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
917 EINA_SAFETY_ON_NULL_RETURN(data);
918 Elm_Store *st = data;
919 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
925 _store_fetch_do(void *data, Ecore_Thread *th __UNUSED__)
927 Elm_Store_Item *sti = data;
933 sti->store->cb.fetch.func(sti->store->cb.fetch.data, sti, sti->item_info);
935 sti->fetched = EINA_TRUE;
941 _store_fetch_end(void *data, Ecore_Thread *th)
943 Elm_Store_Item *sti = data;
945 if(sti->data) elm_genlist_item_update(sti->item);
947 if (th == sti->fetch_th) sti->fetch_th = NULL;
951 _store_fetch_cancel(void *data, Ecore_Thread *th)
953 Elm_Store_Item *sti = data;
955 if (th == sti->fetch_th) sti->fetch_th = NULL;
956 if(sti->data) elm_genlist_item_update(sti->item);
960 static Elm_Store_Item *
961 _item_fetch(Elm_Store *st, int index)
963 EINA_SAFETY_ON_NULL_RETURN_VAL(st,NULL);
969 Eina_List *header_list;
972 EINA_LIST_FOREACH_SAFE(st->header_items, l, l_next, header_list)
976 if ((in_index + eina_list_count(header_list)) > index)
978 sti = eina_list_nth(header_list, index - in_index);
981 if (st->cb.fetch.func)
984 if (st->fetch_thread)
988 sti->fetch_th = ecore_thread_run(_store_fetch_do,
997 st->cb.fetch.func(st->cb.fetch.data, sti, sti->item_info);
999 sti->fetched = EINA_TRUE;
1012 in_index = in_index + eina_list_count(header_list);
1020 static Elm_Store_Item *
1021 _item_unfetch(Elm_Store *st, int index)
1023 EINA_SAFETY_ON_NULL_RETURN_VAL(st,NULL);
1026 Elm_Store_Item *sti;
1029 Eina_List *header_list;
1033 EINA_LIST_FOREACH_SAFE(st->header_items, l, l_next, header_list)
1037 if ((in_index + eina_list_count(header_list)) > index)
1039 sti = eina_list_nth(header_list, index - in_index);
1042 if (st->cb.unfetch.func)
1048 ecore_thread_cancel(sti->fetch_th);
1049 sti->fetch_th = NULL;
1053 st->cb.unfetch.func(st->cb.unfetch.data, sti, sti->item_info);
1055 sti->fetched = EINA_FALSE;
1067 in_index = in_index + eina_list_count(header_list);
1075 static const Elm_Store_Item_Mapping *
1076 _item_mapping_find(Elm_Store_Item *sti, const char *part)
1078 if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return NULL;
1079 const Elm_Store_Item_Mapping *m;
1086 for (m = sti->item_info->mapping; m; m++)
1088 if (m->type == ELM_STORE_ITEM_MAPPING_NONE) break;
1089 if (!strcmp(part, m->part)) return m;
1095 _item_realize(Elm_Store_Item *sti)
1097 if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return;
1098 Elm_Store *st = sti->store;
1099 if (sti->store->live)
1101 int index = elm_store_item_index_get(sti);
1105 if ((st->start_fetch_index <= index) && (index <= (st->start_fetch_index + st->cache_max)))
1109 _item_unfetch(st, index);
1111 _item_fetch(st, index);
1113 if(st->end_fetch_index < index)
1115 st->end_fetch_index = index;
1118 else if (st->start_fetch_index > index)
1120 int diff = st->start_fetch_index - index;
1122 for (loop = 1; loop <= diff; loop++)
1124 _item_unfetch(st, st->end_fetch_index);
1125 st->end_fetch_index--;
1126 _item_fetch(sti->store, (st->start_fetch_index - loop));
1128 st->start_fetch_index = index;
1130 else if (index > st->end_fetch_index)
1132 int diff = index - st->end_fetch_index;
1134 for (loop = 1; loop <= diff; loop++)
1136 _item_unfetch(st, st->start_fetch_index);
1137 st->start_fetch_index++;
1138 _item_fetch(st, (st->end_fetch_index + loop));
1140 st->end_fetch_index = index;
1151 _item_label_get(void *data, Evas_Object *obj __UNUSED__, const char *part)
1153 EINA_SAFETY_ON_NULL_RETURN_VAL(data, strdup(""));
1154 Elm_Store_Item *sti = data;
1155 EINA_SAFETY_ON_NULL_RETURN_VAL(sti,NULL);
1157 if (sti->store->live)
1170 const Elm_Store_Item_Mapping *m = _item_mapping_find(sti, part);
1175 case ELM_STORE_ITEM_MAPPING_LABEL:
1176 s = *(char **)(((unsigned char *)sti->data) + m->offset);
1179 case ELM_STORE_ITEM_MAPPING_CUSTOM:
1180 if (m->details.custom.func)
1181 s = m->details.custom.func(sti->data, sti, part);
1205 static Evas_Object *
1206 _item_icon_get(void *data, Evas_Object *obj, const char *part)
1208 EINA_SAFETY_ON_NULL_RETURN_VAL(data,NULL);
1209 Elm_Store_Item *sti = data;
1210 EINA_SAFETY_ON_NULL_RETURN_VAL(sti,NULL);
1212 if (sti->store->live)
1224 const Elm_Store_Item_Mapping *m = _item_mapping_find(sti, part);
1227 Evas_Object *ic = NULL;
1228 const char *s = NULL;
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,
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);
1248 if (m->details.icon.standard_name)
1249 elm_icon_standard_set(ic, s);
1251 elm_icon_file_set(ic, s, NULL);
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);
1260 elm_photo_file_set(ic, s);
1263 case ELM_STORE_ITEM_MAPPING_CUSTOM:
1264 if (m->details.custom.func)
1265 ic = m->details.custom.func(sti->data, sti, part);
1282 _item_realized(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
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);
1290 EINA_SAFETY_ON_NULL_RETURN(sti);
1292 int index = elm_store_item_index_get(sti);
1294 if (st->fetch_thread)
1296 if ((st->start_fetch_index <= index) && (index <= st->end_fetch_index))
1298 int middle_index = sti->store->start_fetch_index + (sti->store->cache_max) / 2;
1300 if ((middle_index < index) && (sti->store->end_fetch_index < sti->store->total_item_count))
1302 int diff = index - middle_index;
1304 for (loop = 0; loop < diff; loop++)
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++;
1312 else if ((middle_index > index) && (sti->store->start_fetch_index > 0))
1314 int diff = st->current_top_index - index;
1316 for (loop = 0; loop < diff; loop++)
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--;
1325 if ((!sti->fetched))
1327 _item_fetch(st, index);
1333 if ((st->current_top_index > index))
1335 st->current_top_index = index;
1337 else if ((st->current_top_index + SCREEN_ITEM_COUNT) < index)
1339 st->current_top_index = st->current_top_index + (index - (st->current_top_index + SCREEN_ITEM_COUNT));
1346 _item_unrealized(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
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);*/
1356 _item_del(void *data, Evas_Object *obj __UNUSED__)
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);
1366 _list_do(void *data, Ecore_Thread *th __UNUSED__)
1368 EINA_SAFETY_ON_NULL_RETURN(data);
1369 Elm_Store *st = data;
1370 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
1372 if (st->multi_load == EINA_TRUE)
1374 Elm_Store_Item_Info *item_info;
1375 Eina_Bool ok = EINA_FALSE;
1377 for (loop = 0; loop < st->item_count; loop++)
1379 item_info = calloc(1, sizeof(Elm_Store_Item_Info));
1380 if (!item_info) return;
1381 item_info->index = loop;
1383 if (st->cb.list.func)
1385 ok = st->cb.list.func(st->cb.list.data, item_info);
1387 if (ok) ecore_thread_feedback(th, item_info);
1388 else free(item_info);
1389 if (ecore_thread_check(th)) break;
1395 _list_update(void *data, Ecore_Thread *th __UNUSED__, void *msg)
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;
1402 elm_store_item_add(st, info);
1406 _list_end(void *data, Ecore_Thread *th)
1408 EINA_SAFETY_ON_NULL_RETURN(data);
1409 EINA_SAFETY_ON_NULL_RETURN(th);
1410 Elm_Store *st = data;
1412 if (th == st->list_th)
1414 ecore_thread_cancel(st->list_th);
1420 _list_cancel(void *data, Ecore_Thread *th)
1422 EINA_SAFETY_ON_NULL_RETURN(data);
1423 EINA_SAFETY_ON_NULL_RETURN(th);
1424 Elm_Store *st = data;
1426 if (th == st->list_th)
1428 ecore_thread_cancel(st->list_th);
1434 _item_select_cb(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
1436 EINA_SAFETY_ON_NULL_RETURN(event_info);
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;
1442 if (sti->store->cb.item_select.func)
1444 sti->store->cb.item_select.func(sti->store->cb.item_select.data, sti);
1449 _group_item_append(Elm_Store_Item *sti, Elm_Genlist_Item_Class *itc)
1451 EINA_SAFETY_ON_NULL_RETURN(sti);
1452 if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return;
1453 Elm_Store *st = sti->store;
1456 if (st->header_items)
1458 Eina_Bool header_add = EINA_TRUE;
1461 Eina_List *header_list;
1463 EINA_LIST_FOREACH_SAFE(st->header_items, l, l_next, header_list)
1467 Elm_Store_Item *item = eina_list_nth(header_list, 0);
1468 if(item && item->item_info)
1470 if (item->item_info->group_index == sti->item_info->group_index)
1472 header_add = EINA_FALSE;
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++;
1485 Eina_Bool last_header = EINA_TRUE;
1488 Eina_List *header_list;
1490 EINA_LIST_FOREACH_SAFE(st->header_items, l, l_next, header_list)
1494 Elm_Store_Item *group_sti = eina_list_nth(header_list, 0);
1495 if(group_sti && group_sti->item_info)
1497 if(group_sti->item_info->item_type == ELM_GENLIST_ITEM_GROUP)
1500 if (st->cb.item_sort.func)
1502 sort = st->cb.item_sort.func(st->cb.item_sort.data, sti->item_info, group_sti->item_info);
1504 if(sort == ELM_STORE_ITEM_SORT_LOW)
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,
1512 ELM_GENLIST_ITEM_GROUP,
1515 last_header = EINA_FALSE;
1529 st->header_items = eina_list_append(st->header_items, new_header_list);
1530 sti->item = elm_genlist_item_append(st->genlist,
1534 ELM_GENLIST_ITEM_GROUP,
1538 elm_store_item_update(sti);
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,
1552 ELM_GENLIST_ITEM_GROUP,
1555 elm_store_item_update(sti);
1561 _normal_item_append(Elm_Store_Item *sti, Elm_Genlist_Item_Class *itc)
1563 EINA_SAFETY_ON_NULL_RETURN(sti);
1564 if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return;
1565 Elm_Store *st = sti->store;
1568 if (sti->item_info->rec_item == EINA_TRUE)
1570 if (sti->item_info->group_index == sti->item_info->pre_group_index)
1574 Eina_List *header_list;
1576 EINA_LIST_FOREACH_SAFE(st->header_items, l, l_next, header_list)
1580 Elm_Store_Item *header_item = eina_list_nth(header_list, 0);
1581 if(header_item && header_item->item_info)
1583 if (header_item->item_info->group_index == sti->item_info->group_index)
1586 Eina_List *in_l_next;
1587 Elm_Store_Item *item;
1589 EINA_LIST_FOREACH_SAFE(header_list, in_l, in_l_next, item)
1594 if (st->cb.item_sort.func)
1596 sort = st->cb.item_sort.func(st->cb.item_sort.data, sti->item_info, item->item_info);
1598 if(sort == ELM_STORE_ITEM_SORT_SAME)
1600 elm_store_item_update(item);
1619 Eina_List *header_list;
1621 EINA_LIST_FOREACH_SAFE(st->header_items, l, l_next, header_list)
1625 Elm_Store_Item *header_item = eina_list_nth(header_list, 0);
1626 if(header_item && header_item->item_info)
1628 if (header_item->item_info->group_index == sti->item_info->pre_group_index)
1630 Eina_Bool removed = EINA_FALSE;
1632 Eina_List *in_l_next;
1633 Elm_Store_Item *remove_item;
1635 EINA_LIST_FOREACH_SAFE(header_list, in_l, in_l_next, remove_item)
1639 if (removed == EINA_TRUE)
1641 remove_item->item_info->index--;
1646 if (st->cb.item_sort.func)
1648 sort = st->cb.item_sort.func(st->cb.item_sort.data, sti->item_info, remove_item->item_info);
1650 if(sort == ELM_STORE_ITEM_SORT_SAME)
1652 if (remove_item->fetched)
1654 int index = elm_store_item_index_get(remove_item);
1657 _item_unfetch(st, index);
1664 if (st->cb.item_free.func)
1666 st->cb.item_free.func(st->cb.item_free.data, remove_item->item_info);
1667 remove_item->item_info = NULL;
1670 Eina_List *temp_header_list = header_list;
1671 header_list = eina_list_remove(header_list, remove_item);
1672 st->total_item_count--;
1673 LKD(remove_item->lock);
1674 elm_genlist_item_del(remove_item->item);
1677 if (eina_list_count(header_list) == 0)
1679 st->header_items = eina_list_remove(st->header_items, temp_header_list);
1680 header_list = eina_list_free(header_list);
1682 else if(eina_list_count(header_list) == 1)
1684 Elm_Store_Item *temp_sti = eina_list_nth(header_list, 0);
1685 if(temp_sti && temp_sti->item_info)
1687 if (temp_sti->item_info->item_type == ELM_GENLIST_ITEM_GROUP)
1689 if (temp_sti->fetched)
1691 int index = elm_store_item_index_get(temp_sti);
1694 _item_unfetch(st, index);
1702 if (st->cb.item_free.func)
1704 st->cb.item_free.func(st->cb.item_free.data, temp_sti->item_info);
1705 temp_sti->item_info = NULL;
1708 header_list = eina_list_remove(header_list, temp_sti);
1709 st->total_item_count--;
1710 LKD(temp_sti->lock);
1711 elm_genlist_item_del(temp_sti->item);
1713 st->header_items = eina_list_remove(st->header_items, temp_header_list);
1714 header_list = eina_list_free(header_list);
1718 temp_header_list = eina_list_free(temp_header_list);
1719 removed = EINA_TRUE;
1730 else if (header_item->item_info->group_index == sti->item_info->group_index)
1732 Eina_Bool last_add = EINA_TRUE;
1734 Eina_List *in_l_next;
1735 Elm_Store_Item *comp_item;
1737 EINA_LIST_FOREACH_SAFE(header_list, in_l, in_l_next, comp_item)
1741 if(last_add == EINA_FALSE)
1743 comp_item->item_info->index++;
1748 if (st->cb.item_sort.func)
1750 sort = st->cb.item_sort.func(st->cb.item_sort.data, sti->item_info, comp_item->item_info);
1752 if(sort == ELM_STORE_ITEM_SORT_LOW)
1754 sti->item_info->index = comp_item->item_info->index;
1755 comp_item->item_info->index++;
1756 header_list = eina_list_prepend_relative(header_list, sti, comp_item);
1757 st->total_item_count++;
1758 sti->item = elm_genlist_item_insert_before(st->genlist,
1763 ELM_GENLIST_ITEM_NONE,
1764 (Evas_Smart_Cb)sti->store->cb.item_select.func,
1765 (void *)sti->store->cb.item_select.data);
1766 elm_store_item_update(sti);
1767 last_add = EINA_FALSE;
1772 Elm_Store_Item *last_sti = eina_list_nth(header_list, eina_list_count(header_list) - 1);
1773 sti->item_info->index = eina_list_count(header_list);
1774 header_list = eina_list_append(header_list, sti);
1775 st->total_item_count++;
1776 sti->item = elm_genlist_item_insert_after(st->genlist,
1781 ELM_GENLIST_ITEM_NONE,
1782 (Evas_Smart_Cb)sti->store->cb.item_select.func,
1783 (void *)sti->store->cb.item_select.data);
1784 elm_store_item_update(sti);
1785 last_add = EINA_FALSE;
1793 Elm_Store_Item *last_sti = eina_list_nth(header_list, eina_list_count(header_list) - 1);
1794 sti->item_info->index = eina_list_count(header_list);
1795 header_list = eina_list_append(header_list, sti);
1796 st->total_item_count++;
1797 sti->item = elm_genlist_item_insert_after(st->genlist,
1802 ELM_GENLIST_ITEM_NONE,
1803 (Evas_Smart_Cb)sti->store->cb.item_select.func,
1804 (void *)sti->store->cb.item_select.data);
1805 elm_store_item_update(sti);
1815 if (st->header_items)
1817 Eina_Bool normal_add = EINA_TRUE;
1820 Eina_List *header_list;
1822 EINA_LIST_FOREACH_SAFE(st->header_items, l, l_next, header_list)
1826 Elm_Store_Item *header_item = eina_list_nth(header_list, 0);
1828 if(header_item && header_item->item_info)
1830 if (header_item->item_info->group_index == sti->item_info->group_index)
1833 Eina_List *in_l_next;
1834 Elm_Store_Item *comp_item;
1836 EINA_LIST_FOREACH_SAFE(header_list, in_l, in_l_next, comp_item)
1840 if(normal_add == EINA_FALSE)
1842 comp_item->item_info->index++;
1847 if (st->cb.item_sort.func)
1849 sort = st->cb.item_sort.func(st->cb.item_sort.data, sti->item_info, comp_item->item_info);
1851 if(sort == ELM_STORE_ITEM_SORT_LOW)
1853 sti->item_info->index = comp_item->item_info->index;
1854 comp_item->item_info->index++;
1855 header_list = eina_list_prepend_relative(header_list, sti, comp_item);
1856 st->total_item_count++;
1857 sti->item = elm_genlist_item_insert_before(st->genlist,
1862 ELM_GENLIST_ITEM_NONE,
1863 (Evas_Smart_Cb)sti->store->cb.item_select.func,
1864 (void *)sti->store->cb.item_select.data);
1865 normal_add = EINA_FALSE;
1866 elm_store_item_update(sti);
1871 Elm_Store_Item *last_sti = eina_list_nth(header_list, eina_list_count(header_list) - 1);
1872 sti->item_info->index = eina_list_count(header_list);
1873 header_list = eina_list_append(header_list, sti);
1874 st->total_item_count++;
1875 sti->item = elm_genlist_item_insert_after(st->genlist,
1880 ELM_GENLIST_ITEM_NONE,
1881 (Evas_Smart_Cb)sti->store->cb.item_select.func,
1882 (void *)sti->store->cb.item_select.data);
1883 normal_add = EINA_FALSE;
1884 elm_store_item_update(sti);
1892 Elm_Store_Item *last_sti = eina_list_nth(header_list, eina_list_count(header_list) - 1);
1893 sti->item_info->index = eina_list_count(header_list);
1894 header_list = eina_list_append(header_list, sti);
1895 st->total_item_count++;
1896 sti->item = elm_genlist_item_insert_after(st->genlist,
1901 ELM_GENLIST_ITEM_NONE,
1902 (Evas_Smart_Cb)sti->store->cb.item_select.func,
1903 (void *)sti->store->cb.item_select.data);
1904 normal_add = EINA_FALSE;
1905 elm_store_item_update(sti);
1907 if(normal_add == EINA_FALSE)
1917 Eina_List *new_header_list = NULL;
1918 sti->item_info->index = 0;
1919 new_header_list = eina_list_append(new_header_list, sti);
1920 st->total_item_count++;
1921 st->header_items = eina_list_append(st->header_items, new_header_list);
1922 sti->item = elm_genlist_item_append(st->genlist,
1926 ELM_GENLIST_ITEM_NONE,
1927 (Evas_Smart_Cb)sti->store->cb.item_select.func,
1928 (void *)sti->store->cb.item_select.data);
1929 elm_store_item_update(sti);
1936 Eina_List *new_header_list = NULL;
1937 sti->item_info->index = 0;
1938 new_header_list = eina_list_append(new_header_list, sti);
1939 st->total_item_count++;
1940 st->header_items = eina_list_append(st->header_items, new_header_list);
1941 sti->item = elm_genlist_item_append(st->genlist,
1945 ELM_GENLIST_ITEM_NONE,
1946 (Evas_Smart_Cb)sti->store->cb.item_select.func,
1947 (void *)sti->store->cb.item_select.data);
1948 elm_store_item_update(sti);
1956 _item_free(Elm_Store_Item *sti)
1958 if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return;
1959 elm_store_item_del(sti);
1963 _store_free(Elm_Store *st)
1965 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
1967 Elm_Store_DBsystem *std = (Elm_Store_DBsystem *)st;
1968 eina_stringshare_del(std->p_db);
1973 * Add a new dbsystem Store object
1975 * @return The new object or NULL if it cannot be created
1980 elm_store_dbsystem_new(void)
1982 Elm_Store_DBsystem *std = _store_new(Elm_Store_DBsystem);
1983 EINA_SAFETY_ON_NULL_RETURN_VAL(std, NULL);
1985 EINA_MAGIC_SET(std, ELM_STORE_DBSYSTEM_MAGIC);
1986 std->base.free = _store_free;
1987 std->base.item.free = _item_free;
1992 * Sets the item count of a store
1994 * @param st The store object
1995 * @param count The item count of an store
2000 elm_store_item_count_set(Elm_Store *st, int count)
2002 EINA_SAFETY_ON_NULL_RETURN(st);
2003 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
2005 st->item_count = count;
2008 st->multi_load = EINA_TRUE;
2012 st->multi_load = EINA_FALSE;
2018 * Set the select func that select the state of a list item whether true or false
2020 * @param st The store object
2021 * @param func The select cb function of an store
2022 * @param data The new data pointer to set
2027 elm_store_item_select_func_set(Elm_Store *st, Elm_Store_Item_Select_Cb func, const void *data)
2029 EINA_SAFETY_ON_NULL_RETURN(st);
2030 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
2032 st->cb.item_select.func = func;
2033 st->cb.item_select.data = (void *)data;
2037 * Sets the sort func that sort the item with a next in the list
2039 * @param st The store object
2040 * @param func The sort cb function of an store
2041 * @param data The new data pointer to set
2046 elm_store_item_sort_func_set(Elm_Store *st, Elm_Store_Item_Sort_Cb func, const void *data)
2048 EINA_SAFETY_ON_NULL_RETURN(st);
2049 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
2051 st->cb.item_sort.func = func;
2052 st->cb.item_sort.data = (void *)data;
2056 * Set the store item free func
2058 * @param st The store object
2059 * @param func The free cb function of an store
2060 * @param data The new data pointer to set
2065 elm_store_item_free_func_set(Elm_Store *st, Elm_Store_Item_Free_Cb func, const void *data)
2067 EINA_SAFETY_ON_NULL_RETURN(st);
2068 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
2070 st->cb.item_free.func = func;
2071 st->cb.item_free.data = (void *)data;
2075 * Get the item index that included header items
2077 * @param sti The store item object
2078 * @return The item index in genlist
2083 elm_store_item_index_get(const Elm_Store_Item *sti)
2085 EINA_SAFETY_ON_NULL_RETURN_VAL(sti, -1);
2086 if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return -1;
2087 Elm_Store *st = sti->store;
2094 Eina_List *header_list;
2096 EINA_LIST_FOREACH_SAFE(st->header_items, l, l_next, header_list)
2100 Elm_Store_Item *temp_sti = eina_list_nth(header_list, 0);
2101 if(temp_sti && temp_sti->item_info && sti->item_info)
2103 if (sti->item_info->group_index == temp_sti->item_info->group_index)
2106 Eina_List *in_l_next;
2107 Elm_Store_Item *comp_item;
2109 EINA_LIST_FOREACH_SAFE(header_list, in_l, in_l_next, comp_item)
2113 if (comp_item->item_info->index == sti->item_info->index)
2126 index = index + eina_list_count(header_list);
2140 * Get the item index of real data that don't included header items
2142 * @param sti The store item object
2143 * @return The real item index
2148 elm_store_item_data_index_get(const Elm_Store_Item *sti)
2150 EINA_SAFETY_ON_NULL_RETURN_VAL(sti, -1);
2151 if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return -1;
2152 Elm_Store *st = sti->store;
2156 if (sti->item_info->item_type == ELM_GENLIST_ITEM_NONE)
2159 int group_item_count = 0;
2162 Eina_List *header_list;
2164 EINA_LIST_FOREACH_SAFE(st->header_items, l, l_next, header_list)
2168 Elm_Store_Item *temp_sti = eina_list_nth(header_list, 0);
2169 if(temp_sti && temp_sti->item_info && sti->item_info)
2172 if(temp_sti->item_info->item_type == ELM_GENLIST_ITEM_GROUP)
2177 if (temp_sti->item_info->group_index == sti->item_info->group_index)
2180 Eina_List *in_l_next;
2181 Elm_Store_Item *comp_item;
2183 EINA_LIST_FOREACH_SAFE(header_list, in_l, in_l_next, comp_item)
2187 if (comp_item->item_info->index == sti->item_info->index)
2189 return (index - group_item_count);
2201 index = index + eina_list_count(header_list);
2215 * Get the DB pointer of an item
2217 * @param sti The store item object
2218 * @return The DB pointer of item
2223 elm_store_dbsystem_db_get(const Elm_Store_Item *sti)
2225 if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return NULL;
2227 const Elm_Store_DBsystem *std = (const Elm_Store_DBsystem *)sti->store;
2228 if (!EINA_MAGIC_CHECK(sti->store, ELM_STORE_MAGIC)) return NULL;
2229 if (!EINA_MAGIC_CHECK(std, ELM_STORE_DBSYSTEM_MAGIC)) return NULL;
2234 * Set the DB pointer of an item
2236 * @param sti The store item object
2237 * @parm p_db The DB pointer of item
2242 elm_store_dbsystem_db_set(Elm_Store *store, void *p_db)
2244 Elm_Store_DBsystem *std = (Elm_Store_DBsystem *)store;
2245 if (!EINA_MAGIC_CHECK(store, ELM_STORE_MAGIC)) return;
2246 if (!EINA_MAGIC_CHECK(std, ELM_STORE_DBSYSTEM_MAGIC)) return;
2252 ecore_thread_cancel(store->list_th);
2253 store->list_th = NULL;
2255 store->list_th = ecore_thread_feedback_run(_list_do, _list_update, _list_end, _list_cancel, store, EINA_TRUE);
2259 * Append the item to the genlist
2261 * @param st The store object
2262 * @param info The store item info dbsystem object
2263 * @return The item of store
2267 EAPI Elm_Store_Item *
2268 elm_store_item_add(Elm_Store *st, Elm_Store_Item_Info *info)
2270 EINA_SAFETY_ON_NULL_RETURN_VAL(st, NULL);
2271 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return NULL;
2272 EINA_SAFETY_ON_NULL_RETURN_VAL(info, NULL);
2273 Elm_Store_Item *sti;
2274 Elm_Genlist_Item_Class *itc;
2276 sti = calloc(1, sizeof(Elm_Store_Item));
2277 if (!sti) return NULL;
2280 EINA_MAGIC_SET(sti, ELM_STORE_ITEM_MAGIC);
2283 sti->item_info = info;
2284 sti->fetched = EINA_FALSE;
2286 itc = info->item_class;
2287 if (!itc) itc = &_store_item_class;
2290 itc->func.label_get = (GenlistItemLabelGetFunc)_item_label_get;
2291 itc->func.icon_get = (GenlistItemIconGetFunc)_item_icon_get;
2292 itc->func.state_get = NULL;
2293 itc->func.del = NULL;
2298 if (sti->item_info->item_type == ELM_GENLIST_ITEM_GROUP)
2300 _group_item_append(sti, itc);
2304 _normal_item_append(sti, itc);
2315 * Realize the visible items to the screen
2317 * @param st The store object
2322 elm_store_visible_items_update(Elm_Store *st)
2324 EINA_SAFETY_ON_NULL_RETURN(st);
2325 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
2327 Eina_List *realized_list = elm_genlist_realized_items_get(st->genlist);
2331 Elm_Genlist_Item *it;
2332 EINA_LIST_FOREACH(realized_list, l, it)
2336 Elm_Store_Item *realized_sti = elm_genlist_item_data_get(it);
2337 int index = elm_store_item_index_get(realized_sti);
2340 if(realized_sti->fetched)
2342 _item_unfetch(st, index);
2344 _item_fetch(st, index);
2345 if (realized_sti->data) elm_genlist_item_update(realized_sti->item);
2357 * Realize the item to the screen
2359 * @param sti The store item object
2364 elm_store_item_update(Elm_Store_Item *sti)
2366 EINA_SAFETY_ON_NULL_RETURN(sti);
2367 if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return;
2368 Elm_Store *st = sti->store;
2370 int index = elm_store_item_index_get(sti);
2373 if ((st->start_fetch_index <= index) && (index <= (st->start_fetch_index + st->cache_max)))
2377 _item_unfetch(st, index);
2379 _item_fetch(st, index);
2381 if(st->end_fetch_index < (st->total_item_count-1))
2383 if( (st->end_fetch_index - st->cache_max) == st->start_fetch_index)
2385 _item_unfetch(st, (st->total_item_count-1));
2389 st->end_fetch_index = (st->total_item_count-1);
2392 if(sti->data) elm_genlist_item_update(sti->item);
2402 * Delete the item of genlist
2404 * @param sti The store item object
2409 elm_store_item_del(Elm_Store_Item *sti)
2411 EINA_SAFETY_ON_NULL_RETURN(sti);
2412 if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return;
2413 Elm_Store *st = sti->store;
2417 Eina_List *header_list;
2421 EINA_LIST_FOREACH_SAFE(st->header_items, l, l_next, header_list)
2425 Elm_Store_Item *header_item = eina_list_nth(header_list, 0);
2426 if(header_item && header_item->item_info && sti->item_info)
2429 if (header_item->item_info->group_index == sti->item_info->group_index)
2431 Eina_Bool removed = EINA_FALSE;
2433 Eina_List *in_l_next;
2434 Elm_Store_Item *remove_sti;
2435 EINA_LIST_FOREACH_SAFE(header_list, in_l, in_l_next, remove_sti)
2439 if (removed == EINA_TRUE)
2441 remove_sti->item_info->index--;
2445 if (remove_sti->item_info->index == sti->item_info->index)
2447 if (remove_sti->fetched)
2449 int index = elm_store_item_index_get(remove_sti);
2452 _item_unfetch(st, index);
2459 if (st->cb.item_free.func)
2461 st->cb.item_free.func(st->cb.item_free.data, remove_sti->item_info);
2462 remove_sti->item_info = NULL;
2465 Eina_List *temp_header_list = header_list;
2466 header_list = eina_list_remove(header_list, remove_sti);
2467 st->total_item_count--;
2468 LKD(remove_sti->lock);
2469 elm_genlist_item_del(remove_sti->item);
2472 if (eina_list_count(header_list) == 0)
2474 st->header_items = eina_list_remove(st->header_items, temp_header_list);
2475 header_list = eina_list_free(header_list);
2477 else if (eina_list_count(header_list) == 1)
2479 Elm_Store_Item *temp_sti = eina_list_nth(header_list, 0);
2480 if(temp_sti && temp_sti->item_info)
2482 if (temp_sti->item_info->item_type == ELM_GENLIST_ITEM_GROUP)
2484 if (temp_sti->fetched)
2486 int index = elm_store_item_index_get(temp_sti);
2489 _item_unfetch(st, index);
2496 if (st->cb.item_free.func)
2498 st->cb.item_free.func(st->cb.item_free.data, temp_sti->item_info);
2499 temp_sti->item_info = NULL;
2502 header_list = eina_list_remove(header_list, temp_sti);
2503 st->total_item_count--;
2504 LKD(temp_sti->lock);
2505 elm_genlist_item_del(temp_sti->item);
2507 st->header_items = eina_list_remove(st->header_items, temp_header_list);
2508 header_list = eina_list_free(header_list);
2512 temp_header_list = eina_list_free(temp_header_list);
2513 removed = EINA_TRUE;
2525 // TODO: END -DBsystem store