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)
671 ecore_thread_cancel(sti->fetch_th);
672 sti->fetch_th = NULL;
674 if (st->cb.item_free.func)
676 st->cb.item_free.func(st->cb.item_free.data, sti->item_info);
680 int index = elm_store_item_index_get(sti);
681 if (index != -1) _item_unfetch(st, index);
683 header_list = eina_list_remove(header_list, sti);
688 st->header_items = eina_list_remove(st->header_items, header_list);
689 header_list = eina_list_free(header_list);
692 st->header_items = eina_list_free(st->header_items);
698 elm_store_target_genlist_set(Elm_Store *st, Evas_Object *obj)
700 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
701 if (st->genlist == obj) return;
706 evas_object_event_callback_del_full(st->genlist, EVAS_CALLBACK_DEL, _store_genlist_del, st);
707 evas_object_smart_callback_del(st->genlist, "realized", _store_genlist_item_realized);
708 evas_object_smart_callback_del(st->genlist, "unrealized", _store_genlist_item_unrealized);
712 evas_object_event_callback_del_full(st->genlist, EVAS_CALLBACK_DEL, _genlist_del, st);
713 evas_object_smart_callback_del(st->genlist, "realized", _item_realized);
714 evas_object_smart_callback_del(st->genlist, "unrealized", _item_unrealized);
716 elm_genlist_clear(st->genlist);
719 if (!st->genlist) return;
722 evas_object_smart_callback_add(st->genlist, "realized", _store_genlist_item_realized, st);
723 evas_object_smart_callback_add(st->genlist, "unrealized", _store_genlist_item_unrealized, st);
724 evas_object_event_callback_add(st->genlist, EVAS_CALLBACK_DEL, _store_genlist_del, st);
728 evas_object_smart_callback_add(st->genlist, "realized", _item_realized, st);
729 evas_object_smart_callback_add(st->genlist, "unrealized", _item_unrealized, st);
730 evas_object_event_callback_add(st->genlist, EVAS_CALLBACK_DEL, _genlist_del, st);
731 st->block_count = elm_genlist_block_count_get(st->genlist);
733 elm_genlist_clear(st->genlist);
737 elm_store_filesystem_directory_set(Elm_Store *store, const char *dir)
739 Elm_Store_Filesystem *st = (Elm_Store_Filesystem *)store;
740 if (!EINA_MAGIC_CHECK(store, ELM_STORE_MAGIC)) return;
741 if (!EINA_MAGIC_CHECK(st, ELM_STORE_FILESYSTEM_MAGIC)) return;
744 ecore_thread_cancel(store->list_th);
745 store->list_th = NULL;
747 if (!eina_stringshare_replace(&st->dir, dir)) return;
748 store->list_th = ecore_thread_feedback_run(_store_filesystem_list_do,
749 _store_filesystem_list_update,
750 _store_filesystem_list_end,
751 _store_filesystem_list_cancel,
756 elm_store_filesystem_directory_get(const Elm_Store *store)
758 const Elm_Store_Filesystem *st = (const Elm_Store_Filesystem *)store;
759 if (!EINA_MAGIC_CHECK(store, ELM_STORE_MAGIC)) return NULL;
760 if (!EINA_MAGIC_CHECK(st, ELM_STORE_FILESYSTEM_MAGIC)) return NULL;
765 elm_store_cache_set(Elm_Store *st, int max)
767 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
768 if (max < 0) max = 0;
770 if(!st->type) _store_cache_trim(st);
774 elm_store_cache_get(const Elm_Store *st)
776 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return 0;
777 return st->cache_max;
781 elm_store_list_func_set(Elm_Store *st, Elm_Store_Item_List_Cb func, const void *data)
783 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
784 st->cb.list.func = func;
785 st->cb.list.data = (void *)data;
789 elm_store_fetch_func_set(Elm_Store *st, Elm_Store_Item_Fetch_Cb func, const void *data)
791 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
792 st->cb.fetch.func = func;
793 st->cb.fetch.data = (void *)data;
797 elm_store_fetch_thread_set(Elm_Store *st, Eina_Bool use_thread)
799 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
800 st->fetch_thread = !!use_thread;
804 elm_store_fetch_thread_get(const Elm_Store *st)
806 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return EINA_FALSE;
807 return st->fetch_thread;
811 elm_store_unfetch_func_set(Elm_Store *st, Elm_Store_Item_Unfetch_Cb func, const void *data)
813 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
814 st->cb.unfetch.func = func;
815 st->cb.unfetch.data = (void *)data;
819 elm_store_sorted_set(Elm_Store *st, Eina_Bool sorted)
821 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
826 elm_store_sorted_get(const Elm_Store *st)
828 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return EINA_FALSE;
833 elm_store_item_data_set(Elm_Store_Item *sti, void *data)
835 if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return;
842 elm_store_item_data_get(Elm_Store_Item *sti)
844 if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return NULL;
852 EAPI const Elm_Store *
853 elm_store_item_store_get(const Elm_Store_Item *sti)
855 if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return NULL;
860 EAPI const Elm_Genlist_Item *
861 elm_store_item_genlist_item_get(const Elm_Store_Item *sti)
863 if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return NULL;
869 elm_store_item_filesystem_path_get(const Elm_Store_Item *item)
871 Elm_Store_Item_Filesystem *sti = (Elm_Store_Item_Filesystem *)item;
872 Elm_Store_Filesystem *st;
873 if (!EINA_MAGIC_CHECK(item, ELM_STORE_ITEM_MAGIC)) return NULL;
874 if (!EINA_MAGIC_CHECK(item->store, ELM_STORE_MAGIC)) return NULL;
875 /* ensure we're dealing with filesystem item */
876 st = (Elm_Store_Filesystem *)item->store;
877 if (!EINA_MAGIC_CHECK(st, ELM_STORE_FILESYSTEM_MAGIC)) return NULL;
882 // TODO: BEGIN -DBsystem store
885 _store_init(size_t size)
887 Elm_Store *st = calloc(1, size);
888 if (!st) return NULL;
890 eina_magic_string_set(ELM_STORE_MAGIC, "Elm_Store");
891 eina_magic_string_set(ELM_STORE_FILESYSTEM_MAGIC, "Elm_Store_Filesystem");
892 eina_magic_string_set(ELM_STORE_ITEM_MAGIC, "Elm_Store_Item");
893 eina_magic_string_set(ELM_STORE_DBSYSTEM_MAGIC, "Elm_Store_DBsystem");
895 _store_item_class.item_style = "default";
896 _store_item_class.func.label_get = (GenlistItemLabelGetFunc)_item_label_get;
897 _store_item_class.func.icon_get = (GenlistItemIconGetFunc)_item_icon_get;
898 _store_item_class.func.state_get = NULL;
899 _store_item_class.func.del = NULL;
901 EINA_MAGIC_SET(st, ELM_STORE_MAGIC);
902 st->cache_max = CACHE_COUNT;
903 st->start_fetch_index = 0;
904 st->end_fetch_index = 0;
905 st->live = EINA_TRUE;
906 st->multi_load = EINA_FALSE;
907 st->total_item_count = 0;
908 st->fetch_thread = EINA_FALSE;
913 #define _store_new(type) (type *)_store_init(sizeof(type))
916 _genlist_del(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
918 EINA_SAFETY_ON_NULL_RETURN(data);
919 Elm_Store *st = data;
920 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
926 _store_fetch_do(void *data, Ecore_Thread *th __UNUSED__)
928 Elm_Store_Item *sti = data;
934 sti->store->cb.fetch.func(sti->store->cb.fetch.data, sti, sti->item_info);
936 sti->fetched = EINA_TRUE;
942 _store_fetch_end(void *data, Ecore_Thread *th)
944 Elm_Store_Item *sti = data;
946 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;
959 static Elm_Store_Item *
960 _item_fetch(Elm_Store *st, int index)
962 EINA_SAFETY_ON_NULL_RETURN_VAL(st,NULL);
968 Eina_List *header_list;
971 EINA_LIST_FOREACH_SAFE(st->header_items, l, l_next, header_list)
975 if ((in_index + eina_list_count(header_list)) > index)
977 sti = eina_list_nth(header_list, index - in_index);
980 if (st->cb.fetch.func)
983 if (st->fetch_thread)
987 sti->fetch_th = ecore_thread_run(_store_fetch_do,
996 st->cb.fetch.func(st->cb.fetch.data, sti, sti->item_info);
998 sti->fetched = EINA_TRUE;
1011 in_index = in_index + eina_list_count(header_list);
1019 static Elm_Store_Item *
1020 _item_unfetch(Elm_Store *st, int index)
1022 EINA_SAFETY_ON_NULL_RETURN_VAL(st,NULL);
1025 Elm_Store_Item *sti;
1028 Eina_List *header_list;
1032 EINA_LIST_FOREACH_SAFE(st->header_items, l, l_next, header_list)
1036 if ((in_index + eina_list_count(header_list)) > index)
1038 sti = eina_list_nth(header_list, index - in_index);
1041 if (st->cb.unfetch.func)
1047 ecore_thread_cancel(sti->fetch_th);
1048 sti->fetch_th = NULL;
1052 st->cb.unfetch.func(st->cb.unfetch.data, sti, sti->item_info);
1054 sti->fetched = EINA_FALSE;
1066 in_index = in_index + eina_list_count(header_list);
1074 static const Elm_Store_Item_Mapping *
1075 _item_mapping_find(Elm_Store_Item *sti, const char *part)
1077 if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return NULL;
1078 const Elm_Store_Item_Mapping *m;
1080 for (m = sti->item_info->mapping; m; m++)
1082 if (m->type == ELM_STORE_ITEM_MAPPING_NONE) break;
1083 if (!strcmp(part, m->part)) return m;
1089 _item_realize(Elm_Store_Item *sti)
1091 if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return;
1092 Elm_Store *st = sti->store;
1093 if (sti->store->live)
1095 int index = elm_store_item_index_get(sti);
1099 if ((st->start_fetch_index <= index) && (index <= (st->start_fetch_index + st->cache_max)))
1103 _item_unfetch(st, index);
1105 _item_fetch(st, index);
1107 if(st->end_fetch_index < index)
1109 st->end_fetch_index = index;
1112 else if (st->start_fetch_index > index)
1114 int diff = st->start_fetch_index - index;
1116 for (loop = 1; loop <= diff; loop++)
1118 _item_unfetch(st, st->end_fetch_index);
1119 st->end_fetch_index--;
1120 _item_fetch(sti->store, (st->start_fetch_index - loop));
1122 st->start_fetch_index = index;
1124 else if (index > st->end_fetch_index)
1126 int diff = index - st->end_fetch_index;
1128 for (loop = 1; loop <= diff; loop++)
1130 _item_unfetch(st, st->start_fetch_index);
1131 st->start_fetch_index++;
1132 _item_fetch(st, (st->end_fetch_index + loop));
1134 st->end_fetch_index = index;
1145 _item_label_get(void *data, Evas_Object *obj __UNUSED__, const char *part)
1147 EINA_SAFETY_ON_NULL_RETURN_VAL(data, strdup(""));
1148 Elm_Store_Item *sti = data;
1149 EINA_SAFETY_ON_NULL_RETURN_VAL(sti,NULL);
1151 if (sti->store->live)
1164 const Elm_Store_Item_Mapping *m = _item_mapping_find(sti, part);
1169 case ELM_STORE_ITEM_MAPPING_LABEL:
1170 s = *(char **)(((unsigned char *)sti->data) + m->offset);
1173 case ELM_STORE_ITEM_MAPPING_CUSTOM:
1174 if (m->details.custom.func)
1175 s = m->details.custom.func(sti->data, sti, part);
1199 static Evas_Object *
1200 _item_icon_get(void *data, Evas_Object *obj, const char *part)
1202 EINA_SAFETY_ON_NULL_RETURN_VAL(data,NULL);
1203 Elm_Store_Item *sti = data;
1204 EINA_SAFETY_ON_NULL_RETURN_VAL(sti,NULL);
1206 if (sti->store->live)
1218 const Elm_Store_Item_Mapping *m = _item_mapping_find(sti, part);
1221 Evas_Object *ic = NULL;
1222 const char *s = NULL;
1226 case ELM_STORE_ITEM_MAPPING_ICON:
1227 ic = elm_icon_add(obj);
1228 s = *(char **)(((unsigned char *)sti->data) + m->offset);
1229 elm_icon_order_lookup_set(ic, m->details.icon.lookup_order);
1230 evas_object_size_hint_aspect_set(ic,
1231 EVAS_ASPECT_CONTROL_VERTICAL,
1234 elm_icon_smooth_set(ic, m->details.icon.smooth);
1235 elm_icon_no_scale_set(ic, m->details.icon.no_scale);
1236 elm_icon_scale_set(ic,
1237 m->details.icon.scale_up,
1238 m->details.icon.scale_down);
1242 if (m->details.icon.standard_name)
1243 elm_icon_standard_set(ic, s);
1245 elm_icon_file_set(ic, s, NULL);
1249 case ELM_STORE_ITEM_MAPPING_PHOTO:
1250 ic = elm_icon_add(obj);
1251 s = *(char **)(((unsigned char *)sti->data) + m->offset);
1252 elm_photo_size_set(ic, m->details.photo.size);
1254 elm_photo_file_set(ic, s);
1257 case ELM_STORE_ITEM_MAPPING_CUSTOM:
1258 if (m->details.custom.func)
1259 ic = m->details.custom.func(sti->data, sti, part);
1276 _item_realized(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1278 /* EINA_SAFETY_ON_NULL_RETURN(data);
1279 EINA_SAFETY_ON_NULL_RETURN(event_info);
1280 Elm_Store *st = data;
1281 Elm_Genlist_Item *gli = event_info;
1282 Elm_Store_Item *sti = elm_genlist_item_data_get(gli);
1284 EINA_SAFETY_ON_NULL_RETURN(sti);
1286 int index = elm_store_item_index_get(sti);
1288 if (st->fetch_thread)
1290 if ((st->start_fetch_index <= index) && (index <= st->end_fetch_index))
1292 int middle_index = sti->store->start_fetch_index + (sti->store->cache_max) / 2;
1294 if ((middle_index < index) && (sti->store->end_fetch_index < sti->store->total_item_count))
1296 int diff = index - middle_index;
1298 for (loop = 0; loop < diff; loop++)
1300 _item_unfetch(st, sti->store->start_fetch_index);
1301 sti->store->start_fetch_index++;
1302 _item_fetch(st, (sti->store->end_fetch_index + 1));
1303 sti->store->end_fetch_index++;
1306 else if ((middle_index > index) && (sti->store->start_fetch_index > 0))
1308 int diff = st->current_top_index - index;
1310 for (loop = 0; loop < diff; loop++)
1312 _item_unfetch(st, sti->store->end_fetch_index);
1313 sti->store->end_fetch_index--;
1314 _item_fetch(st, (sti->store->start_fetch_index - 1));
1315 sti->store->start_fetch_index--;
1319 if ((!sti->fetched))
1321 _item_fetch(st, index);
1327 if ((st->current_top_index > index))
1329 st->current_top_index = index;
1331 else if ((st->current_top_index + SCREEN_ITEM_COUNT) < index)
1333 st->current_top_index = st->current_top_index + (index - (st->current_top_index + SCREEN_ITEM_COUNT));
1340 _item_unrealized(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1342 /* EINA_SAFETY_ON_NULL_RETURN(data);
1343 EINA_SAFETY_ON_NULL_RETURN(event_info);
1344 Elm_Genlist_Item *gli = event_info;
1345 Elm_Store_Item *sti = elm_genlist_item_data_get(gli);
1346 EINA_SAFETY_ON_NULL_RETURN(sti);*/
1350 _item_del(void *data, Evas_Object *obj __UNUSED__)
1352 EINA_SAFETY_ON_NULL_RETURN(data);
1353 Elm_Store_Item *sti = data;
1354 EINA_SAFETY_ON_NULL_RETURN(sti);
1355 if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return;
1356 elm_store_item_del(sti);
1360 _list_do(void *data, Ecore_Thread *th __UNUSED__)
1362 EINA_SAFETY_ON_NULL_RETURN(data);
1363 Elm_Store *st = data;
1364 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
1366 if (st->multi_load == EINA_TRUE)
1368 Elm_Store_Item_Info *item_info;
1369 Eina_Bool ok = EINA_FALSE;
1371 for (loop = 0; loop < st->item_count; loop++)
1373 item_info = calloc(1, sizeof(Elm_Store_Item_Info));
1374 if (!item_info) return;
1375 item_info->index = loop;
1377 if (st->cb.list.func)
1379 ok = st->cb.list.func(st->cb.list.data, item_info);
1381 if (ok) ecore_thread_feedback(th, item_info);
1382 else free(item_info);
1383 if (ecore_thread_check(th)) break;
1389 _list_update(void *data, Ecore_Thread *th __UNUSED__, void *msg)
1391 EINA_SAFETY_ON_NULL_RETURN(data);
1392 EINA_SAFETY_ON_NULL_RETURN(msg);
1393 Elm_Store *st = data;
1394 Elm_Store_Item_Info *info = msg;
1396 elm_store_item_add(st, info);
1400 _list_end(void *data, Ecore_Thread *th)
1402 EINA_SAFETY_ON_NULL_RETURN(data);
1403 EINA_SAFETY_ON_NULL_RETURN(th);
1404 Elm_Store *st = data;
1406 if (th == st->list_th)
1408 ecore_thread_cancel(st->list_th);
1414 _list_cancel(void *data, Ecore_Thread *th)
1416 EINA_SAFETY_ON_NULL_RETURN(data);
1417 EINA_SAFETY_ON_NULL_RETURN(th);
1418 Elm_Store *st = data;
1420 if (th == st->list_th)
1422 ecore_thread_cancel(st->list_th);
1428 _item_select_cb(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
1430 EINA_SAFETY_ON_NULL_RETURN(event_info);
1432 const Elm_Genlist_Item *it = (Elm_Genlist_Item *)event_info;
1433 Elm_Store_Item *sti = elm_genlist_item_data_get(it);
1434 if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return;
1436 if (sti->store->cb.item_select.func)
1438 sti->store->cb.item_select.func(sti->store->cb.item_select.data, sti);
1443 _group_item_append(Elm_Store_Item *sti, Elm_Genlist_Item_Class *itc)
1445 EINA_SAFETY_ON_NULL_RETURN(sti);
1446 if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return;
1447 Elm_Store *st = sti->store;
1450 if (st->header_items)
1452 Eina_Bool header_add = EINA_TRUE;
1455 Eina_List *header_list;
1457 EINA_LIST_FOREACH_SAFE(st->header_items, l, l_next, header_list)
1461 Elm_Store_Item *item = eina_list_nth(header_list, 0);
1462 if (item->item_info->group_index == sti->item_info->group_index)
1464 header_add = EINA_FALSE;
1471 Eina_List *new_header_list = NULL;
1472 sti->item_info->index = 0;
1473 new_header_list = eina_list_append(new_header_list, sti);
1474 st->total_item_count++;
1476 Eina_Bool last_header = EINA_TRUE;
1479 Eina_List *header_list;
1481 EINA_LIST_FOREACH_SAFE(st->header_items, l, l_next, header_list)
1485 Elm_Store_Item *group_sti = eina_list_nth(header_list, 0);
1486 if(group_sti->item_info->item_type == ELM_GENLIST_ITEM_GROUP)
1489 if (st->cb.item_sort.func)
1491 sort = st->cb.item_sort.func(st->cb.item_sort.data, sti->item_info, group_sti->item_info);
1493 if(sort == ELM_STORE_ITEM_SORT_LOW)
1495 st->header_items = eina_list_prepend_relative(st->header_items, new_header_list, header_list);
1496 sti->item = elm_genlist_item_insert_before(st->genlist,
1501 ELM_GENLIST_ITEM_GROUP,
1504 last_header = EINA_FALSE;
1517 st->header_items = eina_list_append(st->header_items, new_header_list);
1518 sti->item = elm_genlist_item_append(st->genlist,
1522 ELM_GENLIST_ITEM_GROUP,
1526 elm_store_item_update(sti);
1531 Eina_List *header_list = NULL;
1532 sti->item_info->index = 0;
1533 header_list = eina_list_append(header_list, sti);
1534 st->total_item_count++;
1535 st->header_items = eina_list_append(st->header_items, header_list);
1536 sti->item = elm_genlist_item_append(st->genlist,
1540 ELM_GENLIST_ITEM_GROUP,
1543 elm_store_item_update(sti);
1549 _normal_item_append(Elm_Store_Item *sti, Elm_Genlist_Item_Class *itc)
1551 EINA_SAFETY_ON_NULL_RETURN(sti);
1552 if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return;
1553 Elm_Store *st = sti->store;
1556 if (sti->item_info->rec_item == EINA_TRUE)
1558 if (sti->item_info->group_index == sti->item_info->pre_group_index)
1562 Eina_List *header_list;
1564 EINA_LIST_FOREACH_SAFE(st->header_items, l, l_next, header_list)
1568 Elm_Store_Item *header_item = eina_list_nth(header_list, 0);
1569 if (header_item->item_info->group_index == sti->item_info->group_index)
1572 Eina_List *in_l_next;
1573 Elm_Store_Item *item;
1575 EINA_LIST_FOREACH_SAFE(header_list, in_l, in_l_next, item)
1580 if (st->cb.item_sort.func)
1582 sort = st->cb.item_sort.func(st->cb.item_sort.data, sti->item_info, item->item_info);
1584 if(sort == ELM_STORE_ITEM_SORT_SAME)
1586 elm_store_item_update(item);
1604 Eina_List *header_list;
1606 EINA_LIST_FOREACH_SAFE(st->header_items, l, l_next, header_list)
1610 Elm_Store_Item *header_item = eina_list_nth(header_list, 0);
1611 if (header_item->item_info->group_index == sti->item_info->pre_group_index)
1613 Eina_Bool removed = EINA_FALSE;
1615 Eina_List *in_l_next;
1616 Elm_Store_Item *remove_item;
1618 EINA_LIST_FOREACH_SAFE(header_list, in_l, in_l_next, remove_item)
1622 if (removed == EINA_TRUE)
1624 remove_item->item_info->index--;
1629 if (st->cb.item_sort.func)
1631 sort = st->cb.item_sort.func(st->cb.item_sort.data, sti->item_info, remove_item->item_info);
1633 if(sort == ELM_STORE_ITEM_SORT_SAME)
1635 if (st->cb.item_free.func)
1637 st->cb.item_free.func(st->cb.item_free.data, remove_item->item_info);
1639 if (remove_item->fetched)
1641 int index = elm_store_item_index_get(remove_item);
1644 _item_unfetch(st, index);
1651 header_list = eina_list_remove(header_list, remove_item);
1652 st->total_item_count--;
1653 LKD(remove_item->lock);
1654 elm_genlist_item_del(remove_item->item);
1657 if (eina_list_count(header_list) == 0)
1659 st->header_items = eina_list_remove(st->header_items, header_list);
1660 header_list = eina_list_free(header_list);
1662 else if(eina_list_count(header_list) == 1)
1664 Elm_Store_Item *temp_sti = eina_list_nth(header_list, 0);
1665 if (temp_sti->item_info->item_type == ELM_GENLIST_ITEM_GROUP)
1667 if (st->cb.item_free.func)
1669 st->cb.item_free.func(st->cb.item_free.data, temp_sti->item_info);
1671 if (temp_sti->fetched)
1673 int index = elm_store_item_index_get(temp_sti);
1676 _item_unfetch(st, index);
1683 header_list = eina_list_remove(header_list, temp_sti);
1684 st->total_item_count--;
1685 LKD(temp_sti->lock);
1686 elm_genlist_item_del(temp_sti->item);
1688 st->header_items = eina_list_remove(st->header_items, header_list);
1689 header_list = eina_list_free(header_list);
1692 removed = EINA_TRUE;
1703 else if (header_item->item_info->group_index == sti->item_info->group_index)
1705 Eina_Bool last_add = EINA_TRUE;
1707 Eina_List *in_l_next;
1708 Elm_Store_Item *comp_item;
1710 EINA_LIST_FOREACH_SAFE(header_list, in_l, in_l_next, comp_item)
1714 if(last_add == EINA_FALSE)
1716 comp_item->item_info->index++;
1721 if (st->cb.item_sort.func)
1723 sort = st->cb.item_sort.func(st->cb.item_sort.data, sti->item_info, comp_item->item_info);
1725 if(sort == ELM_STORE_ITEM_SORT_LOW)
1727 sti->item_info->index = comp_item->item_info->index;
1728 comp_item->item_info->index++;
1729 header_list = eina_list_prepend_relative(header_list, sti, comp_item);
1730 st->total_item_count++;
1731 sti->item = elm_genlist_item_insert_before(st->genlist,
1736 ELM_GENLIST_ITEM_NONE,
1737 (Evas_Smart_Cb)sti->store->cb.item_select.func,
1738 (void *)sti->store->cb.item_select.data);
1739 elm_store_item_update(sti);
1740 last_add = EINA_FALSE;
1745 Elm_Store_Item *last_sti = eina_list_nth(header_list, eina_list_count(header_list) - 1);
1746 sti->item_info->index = eina_list_count(header_list);
1747 header_list = eina_list_append(header_list, sti);
1748 st->total_item_count++;
1749 sti->item = elm_genlist_item_insert_after(st->genlist,
1754 ELM_GENLIST_ITEM_NONE,
1755 (Evas_Smart_Cb)sti->store->cb.item_select.func,
1756 (void *)sti->store->cb.item_select.data);
1757 elm_store_item_update(sti);
1758 last_add = EINA_FALSE;
1766 Elm_Store_Item *last_sti = eina_list_nth(header_list, eina_list_count(header_list) - 1);
1767 sti->item_info->index = eina_list_count(header_list);
1768 header_list = eina_list_append(header_list, sti);
1769 st->total_item_count++;
1770 sti->item = elm_genlist_item_insert_after(st->genlist,
1775 ELM_GENLIST_ITEM_NONE,
1776 (Evas_Smart_Cb)sti->store->cb.item_select.func,
1777 (void *)sti->store->cb.item_select.data);
1778 elm_store_item_update(sti);
1788 if (st->header_items)
1790 Eina_Bool normal_add = EINA_TRUE;
1793 Eina_List *header_list;
1795 EINA_LIST_FOREACH_SAFE(st->header_items, l, l_next, header_list)
1799 Elm_Store_Item *header_item = eina_list_nth(header_list, 0);
1803 if (header_item->item_info->group_index == sti->item_info->group_index)
1806 Eina_List *in_l_next;
1807 Elm_Store_Item *comp_item;
1809 EINA_LIST_FOREACH_SAFE(header_list, in_l, in_l_next, comp_item)
1813 if(normal_add == EINA_FALSE)
1815 comp_item->item_info->index++;
1820 if (st->cb.item_sort.func)
1822 sort = st->cb.item_sort.func(st->cb.item_sort.data, sti->item_info, comp_item->item_info);
1824 if(sort == ELM_STORE_ITEM_SORT_LOW)
1826 sti->item_info->index = comp_item->item_info->index;
1827 comp_item->item_info->index++;
1828 header_list = eina_list_prepend_relative(header_list, sti, comp_item);
1829 st->total_item_count++;
1830 sti->item = elm_genlist_item_insert_before(st->genlist,
1835 ELM_GENLIST_ITEM_NONE,
1836 (Evas_Smart_Cb)sti->store->cb.item_select.func,
1837 (void *)sti->store->cb.item_select.data);
1838 normal_add = EINA_FALSE;
1839 elm_store_item_update(sti);
1844 Elm_Store_Item *last_sti = eina_list_nth(header_list, eina_list_count(header_list) - 1);
1845 sti->item_info->index = eina_list_count(header_list);
1846 header_list = eina_list_append(header_list, sti);
1847 st->total_item_count++;
1848 sti->item = elm_genlist_item_insert_after(st->genlist,
1853 ELM_GENLIST_ITEM_NONE,
1854 (Evas_Smart_Cb)sti->store->cb.item_select.func,
1855 (void *)sti->store->cb.item_select.data);
1856 normal_add = EINA_FALSE;
1857 elm_store_item_update(sti);
1865 Elm_Store_Item *last_sti = eina_list_nth(header_list, eina_list_count(header_list) - 1);
1866 sti->item_info->index = eina_list_count(header_list);
1867 header_list = eina_list_append(header_list, sti);
1868 st->total_item_count++;
1869 sti->item = elm_genlist_item_insert_after(st->genlist,
1874 ELM_GENLIST_ITEM_NONE,
1875 (Evas_Smart_Cb)sti->store->cb.item_select.func,
1876 (void *)sti->store->cb.item_select.data);
1877 normal_add = EINA_FALSE;
1878 elm_store_item_update(sti);
1880 if(normal_add == EINA_FALSE)
1890 Eina_List *new_header_list = NULL;
1891 sti->item_info->index = 0;
1892 new_header_list = eina_list_append(new_header_list, sti);
1893 st->total_item_count++;
1894 st->header_items = eina_list_append(st->header_items, new_header_list);
1895 sti->item = elm_genlist_item_append(st->genlist,
1899 ELM_GENLIST_ITEM_NONE,
1900 (Evas_Smart_Cb)sti->store->cb.item_select.func,
1901 (void *)sti->store->cb.item_select.data);
1902 elm_store_item_update(sti);
1909 Eina_List *new_header_list = NULL;
1910 sti->item_info->index = 0;
1911 new_header_list = eina_list_append(new_header_list, sti);
1912 st->total_item_count++;
1913 st->header_items = eina_list_append(st->header_items, new_header_list);
1914 sti->item = elm_genlist_item_append(st->genlist,
1918 ELM_GENLIST_ITEM_NONE,
1919 (Evas_Smart_Cb)sti->store->cb.item_select.func,
1920 (void *)sti->store->cb.item_select.data);
1921 elm_store_item_update(sti);
1929 _item_free(Elm_Store_Item *sti)
1931 if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return;
1932 elm_store_item_del(sti);
1936 _store_free(Elm_Store *st)
1938 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
1940 Elm_Store_DBsystem *std = (Elm_Store_DBsystem *)st;
1941 eina_stringshare_del(std->p_db);
1946 * Add a new dbsystem Store object
1948 * @return The new object or NULL if it cannot be created
1953 elm_store_dbsystem_new(void)
1955 Elm_Store_DBsystem *std = _store_new(Elm_Store_DBsystem);
1956 EINA_SAFETY_ON_NULL_RETURN_VAL(std, NULL);
1958 EINA_MAGIC_SET(std, ELM_STORE_DBSYSTEM_MAGIC);
1959 std->base.free = _store_free;
1960 std->base.item.free = _item_free;
1965 * Sets the item count of a store
1967 * @param st The store object
1968 * @param count The item count of an store
1973 elm_store_item_count_set(Elm_Store *st, int count)
1975 EINA_SAFETY_ON_NULL_RETURN(st);
1976 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
1978 st->item_count = count;
1981 st->multi_load = EINA_TRUE;
1985 st->multi_load = EINA_FALSE;
1991 * Set the select func that select the state of a list item whether true or false
1993 * @param st The store object
1994 * @param func The select cb function of an store
1995 * @param data The new data pointer to set
2000 elm_store_item_select_func_set(Elm_Store *st, Elm_Store_Item_Select_Cb func, const void *data)
2002 EINA_SAFETY_ON_NULL_RETURN(st);
2003 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
2005 st->cb.item_select.func = func;
2006 st->cb.item_select.data = (void *)data;
2010 * Sets the sort func that sort the item with a next in the list
2012 * @param st The store object
2013 * @param func The sort cb function of an store
2014 * @param data The new data pointer to set
2019 elm_store_item_sort_func_set(Elm_Store *st, Elm_Store_Item_Sort_Cb func, const void *data)
2021 EINA_SAFETY_ON_NULL_RETURN(st);
2022 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
2024 st->cb.item_sort.func = func;
2025 st->cb.item_sort.data = (void *)data;
2029 * Set the store item free func
2031 * @param st The store object
2032 * @param func The free cb function of an store
2033 * @param data The new data pointer to set
2038 elm_store_item_free_func_set(Elm_Store *st, Elm_Store_Item_Free_Cb func, const void *data)
2040 EINA_SAFETY_ON_NULL_RETURN(st);
2041 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
2043 st->cb.item_free.func = func;
2044 st->cb.item_free.data = (void *)data;
2048 * Get the item index that included header items
2050 * @param sti The store item object
2051 * @return The item index in genlist
2056 elm_store_item_index_get(const Elm_Store_Item *sti)
2058 EINA_SAFETY_ON_NULL_RETURN_VAL(sti, -1);
2059 if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return -1;
2060 Elm_Store *st = sti->store;
2067 Eina_List *header_list;
2069 EINA_LIST_FOREACH_SAFE(st->header_items, l, l_next, header_list)
2073 Elm_Store_Item *temp_sti = eina_list_nth(header_list, 0);
2076 if (sti->item_info->group_index == temp_sti->item_info->group_index)
2079 Eina_List *in_l_next;
2080 Elm_Store_Item *comp_item;
2082 EINA_LIST_FOREACH_SAFE(header_list, in_l, in_l_next, comp_item)
2086 if (comp_item->item_info->index == sti->item_info->index)
2099 index = index + eina_list_count(header_list);
2113 * Get the item index of real data that don't included header items
2115 * @param sti The store item object
2116 * @return The real item index
2121 elm_store_item_data_index_get(const Elm_Store_Item *sti)
2123 EINA_SAFETY_ON_NULL_RETURN_VAL(sti, -1);
2124 if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return -1;
2125 Elm_Store *st = sti->store;
2129 if (sti->item_info->item_type == ELM_GENLIST_ITEM_NONE)
2132 int group_item_count = 0;
2135 Eina_List *header_list;
2137 EINA_LIST_FOREACH_SAFE(st->header_items, l, l_next, header_list)
2141 Elm_Store_Item *temp_sti = eina_list_nth(header_list, 0);
2143 if(temp_sti->item_info->item_type == ELM_GENLIST_ITEM_GROUP)
2148 if (temp_sti->item_info->group_index == sti->item_info->group_index)
2151 Eina_List *in_l_next;
2152 Elm_Store_Item *comp_item;
2154 EINA_LIST_FOREACH_SAFE(header_list, in_l, in_l_next, comp_item)
2158 if (comp_item->item_info->index == sti->item_info->index)
2160 return (index - group_item_count);
2171 index = index + eina_list_count(header_list);
2185 * Get the DB pointer of an item
2187 * @param sti The store item object
2188 * @return The DB pointer of item
2193 elm_store_dbsystem_db_get(const Elm_Store_Item *sti)
2195 if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return NULL;
2197 const Elm_Store_DBsystem *std = (const Elm_Store_DBsystem *)sti->store;
2198 if (!EINA_MAGIC_CHECK(sti->store, ELM_STORE_MAGIC)) return NULL;
2199 if (!EINA_MAGIC_CHECK(std, ELM_STORE_DBSYSTEM_MAGIC)) return NULL;
2204 * Set the DB pointer of an item
2206 * @param sti The store item object
2207 * @parm p_db The DB pointer of item
2212 elm_store_dbsystem_db_set(Elm_Store *store, void *p_db)
2214 Elm_Store_DBsystem *std = (Elm_Store_DBsystem *)store;
2215 if (!EINA_MAGIC_CHECK(store, ELM_STORE_MAGIC)) return;
2216 if (!EINA_MAGIC_CHECK(std, ELM_STORE_DBSYSTEM_MAGIC)) return;
2222 ecore_thread_cancel(store->list_th);
2223 store->list_th = NULL;
2225 store->list_th = ecore_thread_feedback_run(_list_do, _list_update, _list_end, _list_cancel, store, EINA_TRUE);
2229 * Append the item to the genlist
2231 * @param st The store object
2232 * @param info The store item info dbsystem object
2233 * @return The item of store
2237 EAPI Elm_Store_Item *
2238 elm_store_item_add(Elm_Store *st, Elm_Store_Item_Info *info)
2240 EINA_SAFETY_ON_NULL_RETURN_VAL(st, NULL);
2241 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return NULL;
2242 EINA_SAFETY_ON_NULL_RETURN_VAL(info, NULL);
2243 Elm_Store_Item *sti;
2244 Elm_Genlist_Item_Class *itc;
2246 sti = calloc(1, sizeof(Elm_Store_Item));
2247 if (!sti) return NULL;
2250 EINA_MAGIC_SET(sti, ELM_STORE_ITEM_MAGIC);
2253 sti->item_info = info;
2254 sti->fetched = EINA_FALSE;
2256 itc = info->item_class;
2257 if (!itc) itc = &_store_item_class;
2260 itc->func.label_get = (GenlistItemLabelGetFunc)_item_label_get;
2261 itc->func.icon_get = (GenlistItemIconGetFunc)_item_icon_get;
2262 itc->func.state_get = NULL;
2263 itc->func.del = NULL;
2268 if (sti->item_info->item_type == ELM_GENLIST_ITEM_GROUP)
2270 _group_item_append(sti, itc);
2274 _normal_item_append(sti, itc);
2285 * Realize the visible items to the screen
2287 * @param st The store object
2292 elm_store_visible_items_update(Elm_Store *st)
2294 EINA_SAFETY_ON_NULL_RETURN(st);
2295 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
2297 Eina_List *realized_list = elm_genlist_realized_items_get(st->genlist);
2301 Elm_Genlist_Item *it;
2302 EINA_LIST_FOREACH(realized_list, l, it)
2306 Elm_Store_Item *realized_sti = elm_genlist_item_data_get(it);
2307 int index = elm_store_item_index_get(realized_sti);
2310 if(realized_sti->fetched)
2312 _item_unfetch(st, index);
2314 _item_fetch(st, index);
2315 if (realized_sti->data) elm_genlist_item_update(realized_sti->item);
2327 * Realize the item to the screen
2329 * @param sti The store item object
2334 elm_store_item_update(Elm_Store_Item *sti)
2336 EINA_SAFETY_ON_NULL_RETURN(sti);
2337 if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return;
2338 Elm_Store *st = sti->store;
2340 int index = elm_store_item_index_get(sti);
2343 if ((st->start_fetch_index <= index) && (index <= (st->start_fetch_index + st->cache_max)))
2347 _item_unfetch(st, index);
2349 _item_fetch(st, index);
2351 if(st->end_fetch_index < (st->total_item_count-1))
2353 if( (st->end_fetch_index - st->cache_max) == st->start_fetch_index)
2355 _item_unfetch(st, (st->total_item_count-1));
2359 st->end_fetch_index = (st->total_item_count-1);
2362 if(sti->data) elm_genlist_item_update(sti->item);
2372 * Delete the item of genlist
2374 * @param sti The store item object
2379 elm_store_item_del(Elm_Store_Item *sti)
2381 EINA_SAFETY_ON_NULL_RETURN(sti);
2382 if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return;
2383 Elm_Store *st = sti->store;
2387 Eina_List *header_list;
2391 EINA_LIST_FOREACH_SAFE(st->header_items, l, l_next, header_list)
2395 Elm_Store_Item *header_item = eina_list_nth(header_list, 0);
2397 if (header_item->item_info->group_index == sti->item_info->group_index)
2399 Eina_Bool removed = EINA_FALSE;
2401 Eina_List *in_l_next;
2402 Elm_Store_Item *remove_sti;
2403 EINA_LIST_FOREACH_SAFE(header_list, in_l, in_l_next, remove_sti)
2407 if (removed == EINA_TRUE)
2409 remove_sti->item_info->index--;
2413 if (remove_sti->item_info->index == sti->item_info->index)
2415 if (st->cb.item_free.func)
2417 st->cb.item_free.func(st->cb.item_free.data, remove_sti->item_info);
2419 if (remove_sti->fetched)
2421 int index = elm_store_item_index_get(remove_sti);
2424 _item_unfetch(st, index);
2431 header_list = eina_list_remove(header_list, remove_sti);
2432 st->total_item_count--;
2433 LKD(remove_sti->lock);
2434 elm_genlist_item_del(remove_sti->item);
2437 if (eina_list_count(header_list) == 0)
2439 st->header_items = eina_list_remove(st->header_items, header_list);
2440 header_list = eina_list_free(header_list);
2442 else if (eina_list_count(header_list) == 1)
2444 Elm_Store_Item *temp_sti = eina_list_nth(header_list, 0);
2445 if (temp_sti->item_info->item_type == ELM_GENLIST_ITEM_GROUP)
2447 if (st->cb.item_free.func)
2449 st->cb.item_free.func(st->cb.item_free.data, temp_sti->item_info);
2451 if (temp_sti->fetched)
2453 int index = elm_store_item_index_get(temp_sti);
2456 _item_unfetch(st, index);
2463 header_list = eina_list_remove(header_list, temp_sti);
2464 st->total_item_count--;
2465 LKD(temp_sti->lock);
2466 elm_genlist_item_del(temp_sti->item);
2468 st->header_items = eina_list_remove(st->header_items, header_list);
2469 header_list = eina_list_free(header_list);
2472 removed = EINA_TRUE;
2483 // TODO: END -DBsystem store