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;
674 if (st->cb.item_free.func)
676 st->cb.item_free.func(st->cb.item_free.data, sti->item_info);
677 sti->item_info = NULL;
681 int index = elm_store_item_index_get(sti);
682 if (index != -1) _item_unfetch(st, index);
684 header_list = eina_list_remove(header_list, sti);
689 st->header_items = eina_list_remove(st->header_items, header_list);
690 header_list = eina_list_free(header_list);
693 st->header_items = eina_list_free(st->header_items);
699 elm_store_target_genlist_set(Elm_Store *st, Evas_Object *obj)
701 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
702 if (st->genlist == obj) return;
707 evas_object_event_callback_del_full(st->genlist, EVAS_CALLBACK_DEL, _store_genlist_del, st);
708 evas_object_smart_callback_del(st->genlist, "realized", _store_genlist_item_realized);
709 evas_object_smart_callback_del(st->genlist, "unrealized", _store_genlist_item_unrealized);
713 evas_object_event_callback_del_full(st->genlist, EVAS_CALLBACK_DEL, _genlist_del, st);
714 evas_object_smart_callback_del(st->genlist, "realized", _item_realized);
715 evas_object_smart_callback_del(st->genlist, "unrealized", _item_unrealized);
717 elm_genlist_clear(st->genlist);
720 if (!st->genlist) return;
723 evas_object_smart_callback_add(st->genlist, "realized", _store_genlist_item_realized, st);
724 evas_object_smart_callback_add(st->genlist, "unrealized", _store_genlist_item_unrealized, st);
725 evas_object_event_callback_add(st->genlist, EVAS_CALLBACK_DEL, _store_genlist_del, st);
729 evas_object_smart_callback_add(st->genlist, "realized", _item_realized, st);
730 evas_object_smart_callback_add(st->genlist, "unrealized", _item_unrealized, st);
731 evas_object_event_callback_add(st->genlist, EVAS_CALLBACK_DEL, _genlist_del, st);
732 st->block_count = elm_genlist_block_count_get(st->genlist);
734 elm_genlist_clear(st->genlist);
738 elm_store_filesystem_directory_set(Elm_Store *store, const char *dir)
740 Elm_Store_Filesystem *st = (Elm_Store_Filesystem *)store;
741 if (!EINA_MAGIC_CHECK(store, ELM_STORE_MAGIC)) return;
742 if (!EINA_MAGIC_CHECK(st, ELM_STORE_FILESYSTEM_MAGIC)) return;
745 ecore_thread_cancel(store->list_th);
746 store->list_th = NULL;
748 if (!eina_stringshare_replace(&st->dir, dir)) return;
749 store->list_th = ecore_thread_feedback_run(_store_filesystem_list_do,
750 _store_filesystem_list_update,
751 _store_filesystem_list_end,
752 _store_filesystem_list_cancel,
757 elm_store_filesystem_directory_get(const Elm_Store *store)
759 const Elm_Store_Filesystem *st = (const Elm_Store_Filesystem *)store;
760 if (!EINA_MAGIC_CHECK(store, ELM_STORE_MAGIC)) return NULL;
761 if (!EINA_MAGIC_CHECK(st, ELM_STORE_FILESYSTEM_MAGIC)) return NULL;
766 elm_store_cache_set(Elm_Store *st, int max)
768 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
769 if (max < 0) max = 0;
771 if(!st->type) _store_cache_trim(st);
775 elm_store_cache_get(const Elm_Store *st)
777 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return 0;
778 return st->cache_max;
782 elm_store_list_func_set(Elm_Store *st, Elm_Store_Item_List_Cb func, const void *data)
784 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
785 st->cb.list.func = func;
786 st->cb.list.data = (void *)data;
790 elm_store_fetch_func_set(Elm_Store *st, Elm_Store_Item_Fetch_Cb func, const void *data)
792 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
793 st->cb.fetch.func = func;
794 st->cb.fetch.data = (void *)data;
798 elm_store_fetch_thread_set(Elm_Store *st, Eina_Bool use_thread)
800 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
801 st->fetch_thread = !!use_thread;
805 elm_store_fetch_thread_get(const Elm_Store *st)
807 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return EINA_FALSE;
808 return st->fetch_thread;
812 elm_store_unfetch_func_set(Elm_Store *st, Elm_Store_Item_Unfetch_Cb func, const void *data)
814 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
815 st->cb.unfetch.func = func;
816 st->cb.unfetch.data = (void *)data;
820 elm_store_sorted_set(Elm_Store *st, Eina_Bool sorted)
822 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
827 elm_store_sorted_get(const Elm_Store *st)
829 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return EINA_FALSE;
834 elm_store_item_data_set(Elm_Store_Item *sti, void *data)
836 if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return;
843 elm_store_item_data_get(Elm_Store_Item *sti)
845 if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return NULL;
853 EAPI const Elm_Store *
854 elm_store_item_store_get(const Elm_Store_Item *sti)
856 if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return NULL;
861 EAPI const Elm_Genlist_Item *
862 elm_store_item_genlist_item_get(const Elm_Store_Item *sti)
864 if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return NULL;
870 elm_store_item_filesystem_path_get(const Elm_Store_Item *item)
872 Elm_Store_Item_Filesystem *sti = (Elm_Store_Item_Filesystem *)item;
873 Elm_Store_Filesystem *st;
874 if (!EINA_MAGIC_CHECK(item, ELM_STORE_ITEM_MAGIC)) return NULL;
875 if (!EINA_MAGIC_CHECK(item->store, ELM_STORE_MAGIC)) return NULL;
876 /* ensure we're dealing with filesystem item */
877 st = (Elm_Store_Filesystem *)item->store;
878 if (!EINA_MAGIC_CHECK(st, ELM_STORE_FILESYSTEM_MAGIC)) return NULL;
883 // TODO: BEGIN -DBsystem store
886 _store_init(size_t size)
888 Elm_Store *st = calloc(1, size);
889 if (!st) return NULL;
891 eina_magic_string_set(ELM_STORE_MAGIC, "Elm_Store");
892 eina_magic_string_set(ELM_STORE_FILESYSTEM_MAGIC, "Elm_Store_Filesystem");
893 eina_magic_string_set(ELM_STORE_ITEM_MAGIC, "Elm_Store_Item");
894 eina_magic_string_set(ELM_STORE_DBSYSTEM_MAGIC, "Elm_Store_DBsystem");
896 _store_item_class.item_style = "default";
897 _store_item_class.func.label_get = (GenlistItemLabelGetFunc)_item_label_get;
898 _store_item_class.func.icon_get = (GenlistItemIconGetFunc)_item_icon_get;
899 _store_item_class.func.state_get = NULL;
900 _store_item_class.func.del = NULL;
902 EINA_MAGIC_SET(st, ELM_STORE_MAGIC);
903 st->cache_max = CACHE_COUNT;
904 st->start_fetch_index = 0;
905 st->end_fetch_index = 0;
906 st->live = EINA_TRUE;
907 st->multi_load = EINA_FALSE;
908 st->total_item_count = 0;
909 st->fetch_thread = EINA_FALSE;
914 #define _store_new(type) (type *)_store_init(sizeof(type))
917 _genlist_del(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
919 EINA_SAFETY_ON_NULL_RETURN(data);
920 Elm_Store *st = data;
921 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
927 _store_fetch_do(void *data, Ecore_Thread *th __UNUSED__)
929 Elm_Store_Item *sti = data;
935 sti->store->cb.fetch.func(sti->store->cb.fetch.data, sti, sti->item_info);
937 sti->fetched = EINA_TRUE;
943 _store_fetch_end(void *data, Ecore_Thread *th)
945 Elm_Store_Item *sti = data;
947 if (th == sti->fetch_th) sti->fetch_th = NULL;
952 _store_fetch_cancel(void *data, Ecore_Thread *th)
954 Elm_Store_Item *sti = data;
956 if (th == sti->fetch_th) sti->fetch_th = NULL;
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 (st->cb.item_free.func)
1654 st->cb.item_free.func(st->cb.item_free.data, remove_item->item_info);
1655 remove_item->item_info = NULL;
1657 if (remove_item->fetched)
1659 int index = elm_store_item_index_get(remove_item);
1662 _item_unfetch(st, index);
1669 header_list = eina_list_remove(header_list, remove_item);
1670 st->total_item_count--;
1671 LKD(remove_item->lock);
1672 elm_genlist_item_del(remove_item->item);
1675 if (eina_list_count(header_list) == 0)
1677 st->header_items = eina_list_remove(st->header_items, header_list);
1678 header_list = eina_list_free(header_list);
1680 else if(eina_list_count(header_list) == 1)
1682 Elm_Store_Item *temp_sti = eina_list_nth(header_list, 0);
1683 if(temp_sti && temp_sti->item_info)
1685 if (temp_sti->item_info->item_type == ELM_GENLIST_ITEM_GROUP)
1687 if (st->cb.item_free.func)
1689 st->cb.item_free.func(st->cb.item_free.data, temp_sti->item_info);
1690 temp_sti->item_info = NULL;
1692 if (temp_sti->fetched)
1694 int index = elm_store_item_index_get(temp_sti);
1697 _item_unfetch(st, index);
1704 header_list = eina_list_remove(header_list, temp_sti);
1705 st->total_item_count--;
1706 LKD(temp_sti->lock);
1707 elm_genlist_item_del(temp_sti->item);
1709 st->header_items = eina_list_remove(st->header_items, header_list);
1710 header_list = eina_list_free(header_list);
1714 removed = EINA_TRUE;
1725 else if (header_item->item_info->group_index == sti->item_info->group_index)
1727 Eina_Bool last_add = EINA_TRUE;
1729 Eina_List *in_l_next;
1730 Elm_Store_Item *comp_item;
1732 EINA_LIST_FOREACH_SAFE(header_list, in_l, in_l_next, comp_item)
1736 if(last_add == EINA_FALSE)
1738 comp_item->item_info->index++;
1743 if (st->cb.item_sort.func)
1745 sort = st->cb.item_sort.func(st->cb.item_sort.data, sti->item_info, comp_item->item_info);
1747 if(sort == ELM_STORE_ITEM_SORT_LOW)
1749 sti->item_info->index = comp_item->item_info->index;
1750 comp_item->item_info->index++;
1751 header_list = eina_list_prepend_relative(header_list, sti, comp_item);
1752 st->total_item_count++;
1753 sti->item = elm_genlist_item_insert_before(st->genlist,
1758 ELM_GENLIST_ITEM_NONE,
1759 (Evas_Smart_Cb)sti->store->cb.item_select.func,
1760 (void *)sti->store->cb.item_select.data);
1761 elm_store_item_update(sti);
1762 last_add = EINA_FALSE;
1767 Elm_Store_Item *last_sti = eina_list_nth(header_list, eina_list_count(header_list) - 1);
1768 sti->item_info->index = eina_list_count(header_list);
1769 header_list = eina_list_append(header_list, sti);
1770 st->total_item_count++;
1771 sti->item = elm_genlist_item_insert_after(st->genlist,
1776 ELM_GENLIST_ITEM_NONE,
1777 (Evas_Smart_Cb)sti->store->cb.item_select.func,
1778 (void *)sti->store->cb.item_select.data);
1779 elm_store_item_update(sti);
1780 last_add = EINA_FALSE;
1788 Elm_Store_Item *last_sti = eina_list_nth(header_list, eina_list_count(header_list) - 1);
1789 sti->item_info->index = eina_list_count(header_list);
1790 header_list = eina_list_append(header_list, sti);
1791 st->total_item_count++;
1792 sti->item = elm_genlist_item_insert_after(st->genlist,
1797 ELM_GENLIST_ITEM_NONE,
1798 (Evas_Smart_Cb)sti->store->cb.item_select.func,
1799 (void *)sti->store->cb.item_select.data);
1800 elm_store_item_update(sti);
1810 if (st->header_items)
1812 Eina_Bool normal_add = EINA_TRUE;
1815 Eina_List *header_list;
1817 EINA_LIST_FOREACH_SAFE(st->header_items, l, l_next, header_list)
1821 Elm_Store_Item *header_item = eina_list_nth(header_list, 0);
1823 if(header_item && header_item->item_info)
1825 if (header_item->item_info->group_index == sti->item_info->group_index)
1828 Eina_List *in_l_next;
1829 Elm_Store_Item *comp_item;
1831 EINA_LIST_FOREACH_SAFE(header_list, in_l, in_l_next, comp_item)
1835 if(normal_add == EINA_FALSE)
1837 comp_item->item_info->index++;
1842 if (st->cb.item_sort.func)
1844 sort = st->cb.item_sort.func(st->cb.item_sort.data, sti->item_info, comp_item->item_info);
1846 if(sort == ELM_STORE_ITEM_SORT_LOW)
1848 sti->item_info->index = comp_item->item_info->index;
1849 comp_item->item_info->index++;
1850 header_list = eina_list_prepend_relative(header_list, sti, comp_item);
1851 st->total_item_count++;
1852 sti->item = elm_genlist_item_insert_before(st->genlist,
1857 ELM_GENLIST_ITEM_NONE,
1858 (Evas_Smart_Cb)sti->store->cb.item_select.func,
1859 (void *)sti->store->cb.item_select.data);
1860 normal_add = EINA_FALSE;
1861 elm_store_item_update(sti);
1866 Elm_Store_Item *last_sti = eina_list_nth(header_list, eina_list_count(header_list) - 1);
1867 sti->item_info->index = eina_list_count(header_list);
1868 header_list = eina_list_append(header_list, sti);
1869 st->total_item_count++;
1870 sti->item = elm_genlist_item_insert_after(st->genlist,
1875 ELM_GENLIST_ITEM_NONE,
1876 (Evas_Smart_Cb)sti->store->cb.item_select.func,
1877 (void *)sti->store->cb.item_select.data);
1878 normal_add = EINA_FALSE;
1879 elm_store_item_update(sti);
1887 Elm_Store_Item *last_sti = eina_list_nth(header_list, eina_list_count(header_list) - 1);
1888 sti->item_info->index = eina_list_count(header_list);
1889 header_list = eina_list_append(header_list, sti);
1890 st->total_item_count++;
1891 sti->item = elm_genlist_item_insert_after(st->genlist,
1896 ELM_GENLIST_ITEM_NONE,
1897 (Evas_Smart_Cb)sti->store->cb.item_select.func,
1898 (void *)sti->store->cb.item_select.data);
1899 normal_add = EINA_FALSE;
1900 elm_store_item_update(sti);
1902 if(normal_add == EINA_FALSE)
1912 Eina_List *new_header_list = NULL;
1913 sti->item_info->index = 0;
1914 new_header_list = eina_list_append(new_header_list, sti);
1915 st->total_item_count++;
1916 st->header_items = eina_list_append(st->header_items, new_header_list);
1917 sti->item = elm_genlist_item_append(st->genlist,
1921 ELM_GENLIST_ITEM_NONE,
1922 (Evas_Smart_Cb)sti->store->cb.item_select.func,
1923 (void *)sti->store->cb.item_select.data);
1924 elm_store_item_update(sti);
1931 Eina_List *new_header_list = NULL;
1932 sti->item_info->index = 0;
1933 new_header_list = eina_list_append(new_header_list, sti);
1934 st->total_item_count++;
1935 st->header_items = eina_list_append(st->header_items, new_header_list);
1936 sti->item = elm_genlist_item_append(st->genlist,
1940 ELM_GENLIST_ITEM_NONE,
1941 (Evas_Smart_Cb)sti->store->cb.item_select.func,
1942 (void *)sti->store->cb.item_select.data);
1943 elm_store_item_update(sti);
1951 _item_free(Elm_Store_Item *sti)
1953 if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return;
1954 elm_store_item_del(sti);
1958 _store_free(Elm_Store *st)
1960 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
1962 Elm_Store_DBsystem *std = (Elm_Store_DBsystem *)st;
1963 eina_stringshare_del(std->p_db);
1968 * Add a new dbsystem Store object
1970 * @return The new object or NULL if it cannot be created
1975 elm_store_dbsystem_new(void)
1977 Elm_Store_DBsystem *std = _store_new(Elm_Store_DBsystem);
1978 EINA_SAFETY_ON_NULL_RETURN_VAL(std, NULL);
1980 EINA_MAGIC_SET(std, ELM_STORE_DBSYSTEM_MAGIC);
1981 std->base.free = _store_free;
1982 std->base.item.free = _item_free;
1987 * Sets the item count of a store
1989 * @param st The store object
1990 * @param count The item count of an store
1995 elm_store_item_count_set(Elm_Store *st, int count)
1997 EINA_SAFETY_ON_NULL_RETURN(st);
1998 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
2000 st->item_count = count;
2003 st->multi_load = EINA_TRUE;
2007 st->multi_load = EINA_FALSE;
2013 * Set the select func that select the state of a list item whether true or false
2015 * @param st The store object
2016 * @param func The select cb function of an store
2017 * @param data The new data pointer to set
2022 elm_store_item_select_func_set(Elm_Store *st, Elm_Store_Item_Select_Cb func, const void *data)
2024 EINA_SAFETY_ON_NULL_RETURN(st);
2025 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
2027 st->cb.item_select.func = func;
2028 st->cb.item_select.data = (void *)data;
2032 * Sets the sort func that sort the item with a next in the list
2034 * @param st The store object
2035 * @param func The sort cb function of an store
2036 * @param data The new data pointer to set
2041 elm_store_item_sort_func_set(Elm_Store *st, Elm_Store_Item_Sort_Cb func, const void *data)
2043 EINA_SAFETY_ON_NULL_RETURN(st);
2044 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
2046 st->cb.item_sort.func = func;
2047 st->cb.item_sort.data = (void *)data;
2051 * Set the store item free func
2053 * @param st The store object
2054 * @param func The free cb function of an store
2055 * @param data The new data pointer to set
2060 elm_store_item_free_func_set(Elm_Store *st, Elm_Store_Item_Free_Cb func, const void *data)
2062 EINA_SAFETY_ON_NULL_RETURN(st);
2063 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
2065 st->cb.item_free.func = func;
2066 st->cb.item_free.data = (void *)data;
2070 * Get the item index that included header items
2072 * @param sti The store item object
2073 * @return The item index in genlist
2078 elm_store_item_index_get(const Elm_Store_Item *sti)
2080 EINA_SAFETY_ON_NULL_RETURN_VAL(sti, -1);
2081 if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return -1;
2082 Elm_Store *st = sti->store;
2089 Eina_List *header_list;
2091 EINA_LIST_FOREACH_SAFE(st->header_items, l, l_next, header_list)
2095 Elm_Store_Item *temp_sti = eina_list_nth(header_list, 0);
2096 if(temp_sti && temp_sti->item_info && sti->item_info)
2098 if (sti->item_info->group_index == temp_sti->item_info->group_index)
2101 Eina_List *in_l_next;
2102 Elm_Store_Item *comp_item;
2104 EINA_LIST_FOREACH_SAFE(header_list, in_l, in_l_next, comp_item)
2108 if (comp_item->item_info->index == sti->item_info->index)
2121 index = index + eina_list_count(header_list);
2135 * Get the item index of real data that don't included header items
2137 * @param sti The store item object
2138 * @return The real item index
2143 elm_store_item_data_index_get(const Elm_Store_Item *sti)
2145 EINA_SAFETY_ON_NULL_RETURN_VAL(sti, -1);
2146 if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return -1;
2147 Elm_Store *st = sti->store;
2151 if (sti->item_info->item_type == ELM_GENLIST_ITEM_NONE)
2154 int group_item_count = 0;
2157 Eina_List *header_list;
2159 EINA_LIST_FOREACH_SAFE(st->header_items, l, l_next, header_list)
2163 Elm_Store_Item *temp_sti = eina_list_nth(header_list, 0);
2164 if(temp_sti && temp_sti->item_info && sti->item_info)
2167 if(temp_sti->item_info->item_type == ELM_GENLIST_ITEM_GROUP)
2172 if (temp_sti->item_info->group_index == sti->item_info->group_index)
2175 Eina_List *in_l_next;
2176 Elm_Store_Item *comp_item;
2178 EINA_LIST_FOREACH_SAFE(header_list, in_l, in_l_next, comp_item)
2182 if (comp_item->item_info->index == sti->item_info->index)
2184 return (index - group_item_count);
2196 index = index + eina_list_count(header_list);
2210 * Get the DB pointer of an item
2212 * @param sti The store item object
2213 * @return The DB pointer of item
2218 elm_store_dbsystem_db_get(const Elm_Store_Item *sti)
2220 if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return NULL;
2222 const Elm_Store_DBsystem *std = (const Elm_Store_DBsystem *)sti->store;
2223 if (!EINA_MAGIC_CHECK(sti->store, ELM_STORE_MAGIC)) return NULL;
2224 if (!EINA_MAGIC_CHECK(std, ELM_STORE_DBSYSTEM_MAGIC)) return NULL;
2229 * Set the DB pointer of an item
2231 * @param sti The store item object
2232 * @parm p_db The DB pointer of item
2237 elm_store_dbsystem_db_set(Elm_Store *store, void *p_db)
2239 Elm_Store_DBsystem *std = (Elm_Store_DBsystem *)store;
2240 if (!EINA_MAGIC_CHECK(store, ELM_STORE_MAGIC)) return;
2241 if (!EINA_MAGIC_CHECK(std, ELM_STORE_DBSYSTEM_MAGIC)) return;
2247 ecore_thread_cancel(store->list_th);
2248 store->list_th = NULL;
2250 store->list_th = ecore_thread_feedback_run(_list_do, _list_update, _list_end, _list_cancel, store, EINA_TRUE);
2254 * Append the item to the genlist
2256 * @param st The store object
2257 * @param info The store item info dbsystem object
2258 * @return The item of store
2262 EAPI Elm_Store_Item *
2263 elm_store_item_add(Elm_Store *st, Elm_Store_Item_Info *info)
2265 EINA_SAFETY_ON_NULL_RETURN_VAL(st, NULL);
2266 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return NULL;
2267 EINA_SAFETY_ON_NULL_RETURN_VAL(info, NULL);
2268 Elm_Store_Item *sti;
2269 Elm_Genlist_Item_Class *itc;
2271 sti = calloc(1, sizeof(Elm_Store_Item));
2272 if (!sti) return NULL;
2275 EINA_MAGIC_SET(sti, ELM_STORE_ITEM_MAGIC);
2278 sti->item_info = info;
2279 sti->fetched = EINA_FALSE;
2281 itc = info->item_class;
2282 if (!itc) itc = &_store_item_class;
2285 itc->func.label_get = (GenlistItemLabelGetFunc)_item_label_get;
2286 itc->func.icon_get = (GenlistItemIconGetFunc)_item_icon_get;
2287 itc->func.state_get = NULL;
2288 itc->func.del = NULL;
2293 if (sti->item_info->item_type == ELM_GENLIST_ITEM_GROUP)
2295 _group_item_append(sti, itc);
2299 _normal_item_append(sti, itc);
2310 * Realize the visible items to the screen
2312 * @param st The store object
2317 elm_store_visible_items_update(Elm_Store *st)
2319 EINA_SAFETY_ON_NULL_RETURN(st);
2320 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
2322 Eina_List *realized_list = elm_genlist_realized_items_get(st->genlist);
2326 Elm_Genlist_Item *it;
2327 EINA_LIST_FOREACH(realized_list, l, it)
2331 Elm_Store_Item *realized_sti = elm_genlist_item_data_get(it);
2332 int index = elm_store_item_index_get(realized_sti);
2335 if(realized_sti->fetched)
2337 _item_unfetch(st, index);
2339 _item_fetch(st, index);
2340 if (realized_sti->data) elm_genlist_item_update(realized_sti->item);
2352 * Realize the item to the screen
2354 * @param sti The store item object
2359 elm_store_item_update(Elm_Store_Item *sti)
2361 EINA_SAFETY_ON_NULL_RETURN(sti);
2362 if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return;
2363 Elm_Store *st = sti->store;
2365 int index = elm_store_item_index_get(sti);
2368 if ((st->start_fetch_index <= index) && (index <= (st->start_fetch_index + st->cache_max)))
2372 _item_unfetch(st, index);
2374 _item_fetch(st, index);
2376 if(st->end_fetch_index < (st->total_item_count-1))
2378 if( (st->end_fetch_index - st->cache_max) == st->start_fetch_index)
2380 _item_unfetch(st, (st->total_item_count-1));
2384 st->end_fetch_index = (st->total_item_count-1);
2387 if(sti->data) elm_genlist_item_update(sti->item);
2397 * Delete the item of genlist
2399 * @param sti The store item object
2404 elm_store_item_del(Elm_Store_Item *sti)
2406 EINA_SAFETY_ON_NULL_RETURN(sti);
2407 if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return;
2408 Elm_Store *st = sti->store;
2412 Eina_List *header_list;
2416 EINA_LIST_FOREACH_SAFE(st->header_items, l, l_next, header_list)
2420 Elm_Store_Item *header_item = eina_list_nth(header_list, 0);
2421 if(header_item && header_item->item_info && sti->item_info)
2424 if (header_item->item_info->group_index == sti->item_info->group_index)
2426 Eina_Bool removed = EINA_FALSE;
2428 Eina_List *in_l_next;
2429 Elm_Store_Item *remove_sti;
2430 EINA_LIST_FOREACH_SAFE(header_list, in_l, in_l_next, remove_sti)
2434 if (removed == EINA_TRUE)
2436 remove_sti->item_info->index--;
2440 if (remove_sti->item_info->index == sti->item_info->index)
2442 if (st->cb.item_free.func)
2444 st->cb.item_free.func(st->cb.item_free.data, remove_sti->item_info);
2445 remove_sti->item_info = NULL;
2447 if (remove_sti->fetched)
2449 int index = elm_store_item_index_get(remove_sti);
2452 _item_unfetch(st, index);
2459 header_list = eina_list_remove(header_list, remove_sti);
2460 st->total_item_count--;
2461 LKD(remove_sti->lock);
2462 elm_genlist_item_del(remove_sti->item);
2465 if (eina_list_count(header_list) == 0)
2467 st->header_items = eina_list_remove(st->header_items, header_list);
2468 header_list = eina_list_free(header_list);
2470 else if (eina_list_count(header_list) == 1)
2472 Elm_Store_Item *temp_sti = eina_list_nth(header_list, 0);
2473 if(temp_sti && temp_sti->item_info)
2475 if (temp_sti->item_info->item_type == ELM_GENLIST_ITEM_GROUP)
2477 if (st->cb.item_free.func)
2479 st->cb.item_free.func(st->cb.item_free.data, temp_sti->item_info);
2480 temp_sti->item_info = NULL;
2482 if (temp_sti->fetched)
2484 int index = elm_store_item_index_get(temp_sti);
2487 _item_unfetch(st, index);
2494 header_list = eina_list_remove(header_list, temp_sti);
2495 st->total_item_count--;
2496 LKD(temp_sti->lock);
2497 elm_genlist_item_del(temp_sti->item);
2499 st->header_items = eina_list_remove(st->header_items, header_list);
2500 header_list = eina_list_free(header_list);
2504 removed = EINA_TRUE;
2516 // TODO: END -DBsystem store