1 #include <Elementary.h>
2 #include <Elementary_Cursor.h>
5 #ifndef EFL_HAVE_THREADS
6 # error "No thread support. Required."
9 #ifdef EFL_HAVE_POSIX_THREADS
11 # define LK(x) pthread_mutex_t x
12 # define LKI(x) pthread_mutex_init(&(x), NULL);
13 # define LKD(x) pthread_mutex_destroy(&(x));
14 # define LKL(x) pthread_mutex_lock(&(x));
15 # define LKU(x) pthread_mutex_unlock(&(x));
16 #else /* EFL_HAVE_WIN32_THREADS */
17 # define WIN32_LEAN_AND_MEAN
19 # undef WIN32_LEAN_AND_MEAN
20 # define LK(x) HANDLE x
21 # define LKI(x) x = CreateMutex(NULL, FALSE, NULL)
22 # define LKD(x) CloseHandle(x)
23 # define LKL(x) WaitForSingleObject(x, INFINITE)
24 # define LKU(x) ReleaseMutex(x)
27 #define ELM_STORE_MAGIC 0x3f89ea56
28 #define ELM_STORE_FILESYSTEM_MAGIC 0x3f89ea57
29 #define ELM_STORE_DBSYSTEM_MAGIC 0x3f89ea58
30 #define ELM_STORE_ITEM_MAGIC 0x5afe8c1d
31 #define CACHE_COUNT 127
32 #define SCREEN_ITEM_COUNT 10
37 void (*free)(Elm_Store *store);
39 void (*free)(Elm_Store_Item *item);
42 Ecore_Thread *list_th;
47 int start_fetch_index;
53 Eina_List *header_items;
56 Elm_Store_Item_List_Cb func;
60 Elm_Store_Item_Fetch_Cb func;
64 Elm_Store_Item_Unfetch_Cb func;
68 Elm_Store_Item_Select_Cb func;
72 Elm_Store_Item_Sort_Cb func;
76 Elm_Store_Item_Free_Cb func;
81 Eina_Bool fetch_thread : 1;
82 Eina_Bool multi_load : 1;
86 struct _Elm_Store_Item
91 Elm_Genlist_Item *item;
92 Ecore_Thread *fetch_th;
94 const Elm_Store_Item_Mapping *mapping;
96 Elm_Store_Item_Info *item_info;
99 Eina_Bool was_live : 1;
100 Eina_Bool realized : 1;
101 Eina_Bool fetched : 1;
104 struct _Elm_Store_Filesystem
111 struct _Elm_Store_Item_Filesystem
117 struct _Elm_Store_DBsystem
126 ELM_STORE_ITEM_SORT_LOW = -1,
127 ELM_STORE_ITEM_SORT_SAME = 0,
128 ELM_STORE_ITEM_SORT_HIGH = 1,
129 ELM_STORE_ITEM_SORT_UNKNOWN = 2,
130 ELM_STORE_ITEM_SORT_LAST
131 } Elm_Store_Item_Sort_Type;
133 static Elm_Genlist_Item_Class _store_item_class;
135 static char *_item_label_get(void *data, Evas_Object *obj __UNUSED__, const char *part);
136 static Evas_Object *_item_icon_get(void *data, Evas_Object *obj, const char *part);
137 static void _item_del(void *data __UNUSED__, Evas_Object *obj __UNUSED__);
138 static void _store_free(Elm_Store *st);
139 static void _item_free(Elm_Store_Item *sti);
140 static void _item_realized(void *data, Evas_Object *obj __UNUSED__, void *event_info);
141 static void _item_unrealized(void *data, Evas_Object *obj __UNUSED__, void *event_info);
142 static void _genlist_del(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__);
143 static Elm_Store_Item *_item_unfetch(Elm_Store *st, int index);
146 _store_cache_trim(Elm_Store *st)
148 while ((st->realized ) &&
149 (((int)eina_list_count(st->realized) - st->realized_count)
152 Elm_Store_Item *sti = st->realized->data;
155 st->realized = eina_list_remove_list(st->realized, st->realized);
156 sti->realized = EINA_FALSE;
164 ecore_thread_cancel(sti->fetch_th);
165 sti->fetch_th = NULL;
169 sti->fetched = EINA_FALSE;
171 if (st->cb.unfetch.func)
172 st->cb.unfetch.func(st->cb.unfetch.data, sti, NULL);
180 _store_genlist_del(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
182 Elm_Store *st = data;
186 ecore_thread_cancel(st->list_th);
189 eina_list_free(st->realized);
192 Elm_Store_Item *sti = (Elm_Store_Item *)st->items;
193 if (sti->eval_job) ecore_job_del(sti->eval_job);
196 ecore_thread_cancel(sti->fetch_th);
197 sti->fetch_th = NULL;
199 if (sti->store->item.free) sti->store->item.free(sti);
202 if (st->cb.unfetch.func)
203 st->cb.unfetch.func(st->cb.unfetch.data, sti, NULL);
209 // FIXME: kill threads and more
212 ////// **** WARNING ***********************************************************
213 //// * This function runs inside a thread outside efl mainloop. Be careful! *
214 // ************************************************************************
215 /* TODO: refactor lock part into core? this does not depend on filesystm part */
217 _store_filesystem_fetch_do(void *data, Ecore_Thread *th __UNUSED__)
219 Elm_Store_Item *sti = data;
229 if (sti->store->cb.fetch.func)
230 sti->store->cb.fetch.func(sti->store->cb.fetch.data, sti, NULL);
232 sti->fetched = EINA_TRUE;
236 // ************************************************************************
237 //// * End of separate thread function. *
238 ////// ************************************************************************
239 /* TODO: refactor lock part into core? this does not depend on filesystm part */
241 _store_filesystem_fetch_end(void *data, Ecore_Thread *th)
243 Elm_Store_Item *sti = data;
245 if (sti->data) elm_genlist_item_update(sti->item);
247 if (th == sti->fetch_th) sti->fetch_th = NULL;
250 /* TODO: refactor lock part into core? this does not depend on filesystm part */
252 _store_filesystem_fetch_cancel(void *data, Ecore_Thread *th)
254 Elm_Store_Item *sti = data;
256 if (th == sti->fetch_th) sti->fetch_th = NULL;
257 if (sti->data) elm_genlist_item_update(sti->item);
262 _store_item_eval(void *data)
264 Elm_Store_Item *sti = data;
265 sti->eval_job = NULL;
266 if (sti->live == sti->was_live) return;
267 sti->was_live = sti->live;
270 _store_cache_trim(sti->store);
272 sti->store->realized = eina_list_remove(sti->store->realized, sti);
273 sti->store->realized = eina_list_append(sti->store->realized, sti);
274 sti->realized = EINA_TRUE;
275 if ((sti->store->fetch_thread) && (!sti->fetch_th))
276 sti->fetch_th = ecore_thread_run(_store_filesystem_fetch_do,
277 _store_filesystem_fetch_end,
278 _store_filesystem_fetch_cancel,
280 else if ((!sti->store->fetch_thread))
282 _store_filesystem_fetch_do(sti, NULL);
283 _store_filesystem_fetch_end(sti, NULL);
290 ecore_thread_cancel(sti->fetch_th);
291 sti->fetch_th = NULL;
293 _store_cache_trim(sti->store);
298 _store_genlist_item_realized(void *data, Evas_Object *obj __UNUSED__, void *event_info)
300 Elm_Store *st = data;
301 Elm_Genlist_Item *gli = event_info;
302 Elm_Store_Item *sti = elm_genlist_item_data_get(gli);
304 st->realized_count++;
305 sti->live = EINA_TRUE;
306 if (sti->eval_job) ecore_job_del(sti->eval_job);
307 sti->eval_job = ecore_job_add(_store_item_eval, sti);
311 _store_genlist_item_unrealized(void *data, Evas_Object *obj __UNUSED__, void *event_info)
313 Elm_Store *st = data;
314 Elm_Genlist_Item *gli = event_info;
315 Elm_Store_Item *sti = elm_genlist_item_data_get(gli);
317 st->realized_count--;
318 sti->live = EINA_FALSE;
319 if (sti->eval_job) ecore_job_del(sti->eval_job);
320 sti->eval_job = ecore_job_add(_store_item_eval, sti);
323 static const Elm_Store_Item_Mapping *
324 _store_item_mapping_find(Elm_Store_Item *sti, const char *part)
326 const Elm_Store_Item_Mapping *m;
328 for (m = sti->mapping; m; m ++)
330 if (m->type == ELM_STORE_ITEM_MAPPING_NONE) break;
331 if (!strcmp(part, m->part)) return m;
337 _store_item_label_get(void *data, Evas_Object *obj __UNUSED__, const char *part)
339 Elm_Store_Item *sti = data;
344 const Elm_Store_Item_Mapping *m = _store_item_mapping_find(sti, part);
349 case ELM_STORE_ITEM_MAPPING_LABEL:
350 s = *(char **)(((unsigned char *)sti->data) + m->offset);
352 case ELM_STORE_ITEM_MAPPING_CUSTOM:
353 if (m->details.custom.func)
354 s = m->details.custom.func(sti->data, sti, part);
366 _store_item_icon_get(void *data, Evas_Object *obj, const char *part)
368 Elm_Store_Item *sti = data;
372 const Elm_Store_Item_Mapping *m = _store_item_mapping_find(sti, part);
375 Evas_Object *ic = NULL;
376 const char *s = NULL;
380 case ELM_STORE_ITEM_MAPPING_ICON:
381 ic = elm_icon_add(obj);
382 s = *(char **)(((unsigned char *)sti->data) + m->offset);
383 elm_icon_order_lookup_set(ic, m->details.icon.lookup_order);
384 evas_object_size_hint_aspect_set(ic,
385 EVAS_ASPECT_CONTROL_VERTICAL,
388 elm_icon_smooth_set(ic, m->details.icon.smooth);
389 elm_icon_no_scale_set(ic, m->details.icon.no_scale);
390 elm_icon_scale_set(ic,
391 m->details.icon.scale_up,
392 m->details.icon.scale_down);
395 if (m->details.icon.standard_name)
396 elm_icon_standard_set(ic, s);
398 elm_icon_file_set(ic, s, NULL);
401 case ELM_STORE_ITEM_MAPPING_PHOTO:
402 ic = elm_icon_add(obj);
403 s = *(char **)(((unsigned char *)sti->data) + m->offset);
404 elm_photo_size_set(ic, m->details.photo.size);
406 elm_photo_file_set(ic, s);
408 case ELM_STORE_ITEM_MAPPING_CUSTOM:
409 if (m->details.custom.func)
410 ic = m->details.custom.func(sti->data, sti, part);
424 _store_item_del(void *data __UNUSED__, Evas_Object *obj __UNUSED__)
428 ////// **** WARNING ***********************************************************
429 //// * This function runs inside a thread outside efl mainloop. Be careful! *
430 // ************************************************************************
432 _store_filesystem_sort_cb(void *d1, void *d2)
434 Elm_Store_Item_Info *info1 = d1, *info2 = d2;
435 if ((!info1->sort_id) || (!info2->sort_id)) return 0;
436 return strcoll(info1->sort_id, info2->sort_id);
440 _store_filesystem_list_do(void *data, Ecore_Thread *th __UNUSED__)
442 Elm_Store_Filesystem *st = data;
444 const Eina_File_Direct_Info *finf;
445 Eina_List *sorted = NULL;
446 Elm_Store_Item_Info_Filesystem *info;
448 // FIXME: need a way to abstract the open, list, feed items from list
449 // and maybe get initial sortable key vals etc.
450 it = eina_file_stat_ls(st->dir);
452 EINA_ITERATOR_FOREACH(it, finf)
455 size_t pathsz = finf->path_length + 1;
457 info = calloc(1, sizeof(Elm_Store_Item_Info_Filesystem) + pathsz);
459 info->path = ((char *)info) + sizeof(Elm_Store_Item_Info_Filesystem);
460 memcpy(info->path, finf->path, pathsz);
462 if (st->base.cb.list.func)
463 ok = st->base.cb.list.func(st->base.cb.list.data, &info->base);
466 if (!st->base.sorted) ecore_thread_feedback(th, info);
467 else sorted = eina_list_append(sorted, info);
471 if (info->base.sort_id) free(info->base.sort_id);
474 if (ecore_thread_check(th)) break;
476 eina_iterator_free(it);
479 sorted = eina_list_sort(sorted, 0,
480 EINA_COMPARE_CB(_store_filesystem_sort_cb));
481 EINA_LIST_FREE(sorted, info)
483 if (!ecore_thread_check(th)) ecore_thread_feedback(th, info);
487 // ************************************************************************
488 //// * End of separate thread function. *
489 ////// ************************************************************************
492 _store_filesystem_list_end(void *data, Ecore_Thread *th)
494 Elm_Store *st = data;
495 if (th == st->list_th) st->list_th = NULL;
499 _store_filesystem_list_cancel(void *data, Ecore_Thread *th)
501 Elm_Store *st = data;
502 if (th == st->list_th) st->list_th = NULL;
506 _store_filesystem_list_update(void *data, Ecore_Thread *th __UNUSED__, void *msg)
508 Elm_Store *st = data;
509 Elm_Store_Item_Filesystem *sti;
510 Elm_Genlist_Item_Class *itc;
511 Elm_Store_Item_Info_Filesystem *info = msg;
513 sti = calloc(1, sizeof(Elm_Store_Item_Filesystem));
516 EINA_MAGIC_SET(&(sti->base), ELM_STORE_ITEM_MAGIC);
517 sti->base.store = st;
518 sti->base.data = info->base.data;
519 sti->base.mapping = info->base.mapping;
520 sti->path = eina_stringshare_add(info->path);
522 itc = info->base.item_class;
523 if (!itc) itc = &_store_item_class;
526 itc->func.label_get = (GenlistItemLabelGetFunc)_store_item_label_get;
527 itc->func.icon_get = (GenlistItemIconGetFunc)_store_item_icon_get;
528 itc->func.state_get = NULL; // FIXME: support state gets later
529 itc->func.del = (GenlistItemDelFunc)_store_item_del;
532 // FIXME: handle being a parent (tree)
533 sti->base.item = elm_genlist_item_append(st->genlist, itc,
536 ELM_GENLIST_ITEM_NONE,
538 NULL/* func data */);
539 st->items = eina_inlist_append(st->items, (Eina_Inlist *)sti);
541 if (info->base.sort_id) free(info->base.sort_id);
547 _elm_store_new(size_t size)
549 Elm_Store *st = calloc(1, size);
550 EINA_SAFETY_ON_NULL_RETURN_VAL(st, NULL);
552 // TODO: BEGIN - move to elm_store_init()
553 eina_magic_string_set(ELM_STORE_MAGIC, "Elm_Store");
554 eina_magic_string_set(ELM_STORE_FILESYSTEM_MAGIC, "Elm_Store_Filesystem");
555 eina_magic_string_set(ELM_STORE_ITEM_MAGIC, "Elm_Store_Item");
556 // setup default item class (always the same) if list cb doesnt provide one
557 _store_item_class.item_style = "default";
558 _store_item_class.func.label_get = (GenlistItemLabelGetFunc)_store_item_label_get;
559 _store_item_class.func.icon_get = (GenlistItemIconGetFunc)_store_item_icon_get;
560 _store_item_class.func.state_get = NULL; // FIXME: support state gets later
561 _store_item_class.func.del = (GenlistItemDelFunc)_store_item_del;
562 // TODO: END - move to elm_store_init()
564 EINA_MAGIC_SET(st, ELM_STORE_MAGIC);
566 st->fetch_thread = EINA_TRUE;
570 #define elm_store_new(type) (type*)_elm_store_new(sizeof(type))
573 _elm_store_filesystem_free(Elm_Store *store)
575 Elm_Store_Filesystem *st = (Elm_Store_Filesystem *)store;
576 eina_stringshare_del(st->dir);
580 _elm_store_filesystem_item_free(Elm_Store_Item *item)
582 Elm_Store_Item_Filesystem *sti = (Elm_Store_Item_Filesystem *)item;
583 eina_stringshare_del(sti->path);
587 elm_store_filesystem_new(void)
589 Elm_Store_Filesystem *st = elm_store_new(Elm_Store_Filesystem);
590 EINA_SAFETY_ON_NULL_RETURN_VAL(st, NULL);
592 EINA_MAGIC_SET(st, ELM_STORE_FILESYSTEM_MAGIC);
593 st->base.free = _elm_store_filesystem_free;
594 st->base.item.free = _elm_store_filesystem_item_free;
600 elm_store_free(Elm_Store *st)
602 void (*item_free)(Elm_Store_Item *);
603 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
606 ecore_thread_cancel(st->list_th);
612 eina_list_free(st->realized);
613 item_free = st->item.free;
616 Elm_Store_Item *sti = (Elm_Store_Item *)st->items;
617 if (sti->eval_job) ecore_job_del(sti->eval_job);
620 ecore_thread_cancel(sti->fetch_th);
621 sti->fetch_th = NULL;
623 if (item_free) item_free(sti);
626 if (st->cb.unfetch.func)
627 st->cb.unfetch.func(st->cb.unfetch.data, sti, NULL);
635 evas_object_event_callback_del_full(st->genlist, EVAS_CALLBACK_DEL, _store_genlist_del, st);
636 evas_object_smart_callback_del(st->genlist, "realized", _store_genlist_item_realized);
637 evas_object_smart_callback_del(st->genlist, "unrealized", _store_genlist_item_unrealized);
638 elm_genlist_clear(st->genlist);
641 if (st->free) st->free(st);
645 st->live = EINA_FALSE;
648 evas_object_event_callback_del_full(st->genlist, EVAS_CALLBACK_DEL, _genlist_del, st);
649 evas_object_smart_callback_del(st->genlist, "realized", _item_realized);
650 evas_object_smart_callback_del(st->genlist, "unrealized", _item_unrealized);
651 elm_genlist_clear(st->genlist);
656 Eina_List *header_list;
658 EINA_LIST_FOREACH_SAFE(st->header_items, l, l_next, header_list)
663 Eina_List *in_l_next;
665 EINA_LIST_FOREACH_SAFE(header_list, in_l, in_l_next, sti)
669 if (st->fetch_thread && sti->fetch_th)
671 ecore_thread_cancel(sti->fetch_th);
672 sti->fetch_th = NULL;
676 int index = elm_store_item_index_get(sti);
677 if (index != -1) _item_unfetch(st, index);
679 if (st->cb.item_free.func)
681 st->cb.item_free.func(st->cb.item_free.data, sti->item_info);
682 sti->item_info = NULL;
687 st->header_items = eina_list_remove(st->header_items, header_list);
688 header_list = eina_list_free(header_list);
691 st->header_items = eina_list_free(st->header_items);
697 elm_store_target_genlist_set(Elm_Store *st, Evas_Object *obj)
699 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
700 if (st->genlist == obj) return;
705 evas_object_event_callback_del_full(st->genlist, EVAS_CALLBACK_DEL, _store_genlist_del, st);
706 evas_object_smart_callback_del(st->genlist, "realized", _store_genlist_item_realized);
707 evas_object_smart_callback_del(st->genlist, "unrealized", _store_genlist_item_unrealized);
711 evas_object_event_callback_del_full(st->genlist, EVAS_CALLBACK_DEL, _genlist_del, st);
712 evas_object_smart_callback_del(st->genlist, "realized", _item_realized);
713 evas_object_smart_callback_del(st->genlist, "unrealized", _item_unrealized);
715 elm_genlist_clear(st->genlist);
718 if (!st->genlist) return;
721 evas_object_smart_callback_add(st->genlist, "realized", _store_genlist_item_realized, st);
722 evas_object_smart_callback_add(st->genlist, "unrealized", _store_genlist_item_unrealized, st);
723 evas_object_event_callback_add(st->genlist, EVAS_CALLBACK_DEL, _store_genlist_del, st);
727 evas_object_smart_callback_add(st->genlist, "realized", _item_realized, st);
728 evas_object_smart_callback_add(st->genlist, "unrealized", _item_unrealized, st);
729 evas_object_event_callback_add(st->genlist, EVAS_CALLBACK_DEL, _genlist_del, st);
730 st->block_count = elm_genlist_block_count_get(st->genlist);
732 elm_genlist_clear(st->genlist);
736 elm_store_filesystem_directory_set(Elm_Store *store, const char *dir)
738 Elm_Store_Filesystem *st = (Elm_Store_Filesystem *)store;
739 if (!EINA_MAGIC_CHECK(store, ELM_STORE_MAGIC)) return;
740 if (!EINA_MAGIC_CHECK(st, ELM_STORE_FILESYSTEM_MAGIC)) return;
743 ecore_thread_cancel(store->list_th);
744 store->list_th = NULL;
746 if (!eina_stringshare_replace(&st->dir, dir)) return;
747 store->list_th = ecore_thread_feedback_run(_store_filesystem_list_do,
748 _store_filesystem_list_update,
749 _store_filesystem_list_end,
750 _store_filesystem_list_cancel,
755 elm_store_filesystem_directory_get(const Elm_Store *store)
757 const Elm_Store_Filesystem *st = (const Elm_Store_Filesystem *)store;
758 if (!EINA_MAGIC_CHECK(store, ELM_STORE_MAGIC)) return NULL;
759 if (!EINA_MAGIC_CHECK(st, ELM_STORE_FILESYSTEM_MAGIC)) return NULL;
764 elm_store_cache_set(Elm_Store *st, int max)
766 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
767 if (max < 0) max = 0;
769 if(!st->type) _store_cache_trim(st);
773 elm_store_cache_get(const Elm_Store *st)
775 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return 0;
776 return st->cache_max;
780 elm_store_list_func_set(Elm_Store *st, Elm_Store_Item_List_Cb func, const void *data)
782 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
783 st->cb.list.func = func;
784 st->cb.list.data = (void *)data;
788 elm_store_fetch_func_set(Elm_Store *st, Elm_Store_Item_Fetch_Cb func, const void *data)
790 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
791 st->cb.fetch.func = func;
792 st->cb.fetch.data = (void *)data;
796 elm_store_fetch_thread_set(Elm_Store *st, Eina_Bool use_thread)
798 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
799 st->fetch_thread = !!use_thread;
803 elm_store_fetch_thread_get(const Elm_Store *st)
805 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return EINA_FALSE;
806 return st->fetch_thread;
810 elm_store_unfetch_func_set(Elm_Store *st, Elm_Store_Item_Unfetch_Cb func, const void *data)
812 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
813 st->cb.unfetch.func = func;
814 st->cb.unfetch.data = (void *)data;
818 elm_store_sorted_set(Elm_Store *st, Eina_Bool sorted)
820 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
825 elm_store_sorted_get(const Elm_Store *st)
827 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return EINA_FALSE;
832 elm_store_item_data_set(Elm_Store_Item *sti, void *data)
834 if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return;
841 elm_store_item_data_get(Elm_Store_Item *sti)
843 if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return NULL;
851 EAPI const Elm_Store *
852 elm_store_item_store_get(const Elm_Store_Item *sti)
854 if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return NULL;
859 EAPI const Elm_Genlist_Item *
860 elm_store_item_genlist_item_get(const Elm_Store_Item *sti)
862 if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return NULL;
868 elm_store_item_filesystem_path_get(const Elm_Store_Item *item)
870 Elm_Store_Item_Filesystem *sti = (Elm_Store_Item_Filesystem *)item;
871 Elm_Store_Filesystem *st;
872 if (!EINA_MAGIC_CHECK(item, ELM_STORE_ITEM_MAGIC)) return NULL;
873 if (!EINA_MAGIC_CHECK(item->store, ELM_STORE_MAGIC)) return NULL;
874 /* ensure we're dealing with filesystem item */
875 st = (Elm_Store_Filesystem *)item->store;
876 if (!EINA_MAGIC_CHECK(st, ELM_STORE_FILESYSTEM_MAGIC)) return NULL;
881 // TODO: BEGIN -DBsystem store
884 _store_init(size_t size)
886 Elm_Store *st = calloc(1, size);
887 if (!st) return NULL;
889 eina_magic_string_set(ELM_STORE_MAGIC, "Elm_Store");
890 eina_magic_string_set(ELM_STORE_FILESYSTEM_MAGIC, "Elm_Store_Filesystem");
891 eina_magic_string_set(ELM_STORE_ITEM_MAGIC, "Elm_Store_Item");
892 eina_magic_string_set(ELM_STORE_DBSYSTEM_MAGIC, "Elm_Store_DBsystem");
894 _store_item_class.item_style = "default";
895 _store_item_class.func.label_get = (GenlistItemLabelGetFunc)_item_label_get;
896 _store_item_class.func.icon_get = (GenlistItemIconGetFunc)_item_icon_get;
897 _store_item_class.func.state_get = NULL;
898 _store_item_class.func.del = NULL;
900 EINA_MAGIC_SET(st, ELM_STORE_MAGIC);
901 st->cache_max = CACHE_COUNT;
902 st->start_fetch_index = 0;
903 st->end_fetch_index = 0;
904 st->live = EINA_TRUE;
905 st->multi_load = EINA_FALSE;
906 st->total_item_count = 0;
907 st->fetch_thread = EINA_FALSE;
912 #define _store_new(type) (type *)_store_init(sizeof(type))
915 _genlist_del(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
917 EINA_SAFETY_ON_NULL_RETURN(data);
918 Elm_Store *st = data;
919 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
925 _store_fetch_do(void *data, Ecore_Thread *th __UNUSED__)
927 Elm_Store_Item *sti = data;
933 sti->store->cb.fetch.func(sti->store->cb.fetch.data, sti, sti->item_info);
935 sti->fetched = EINA_TRUE;
941 _store_fetch_end(void *data, Ecore_Thread *th)
943 Elm_Store_Item *sti = data;
945 if(sti->data) elm_genlist_item_update(sti->item);
947 if (th == sti->fetch_th) sti->fetch_th = NULL;
951 _store_fetch_cancel(void *data, Ecore_Thread *th)
953 Elm_Store_Item *sti = data;
955 if (th == sti->fetch_th) sti->fetch_th = NULL;
956 if(sti->data) elm_genlist_item_update(sti->item);
960 static Elm_Store_Item *
961 _item_fetch(Elm_Store *st, int index)
963 EINA_SAFETY_ON_NULL_RETURN_VAL(st,NULL);
969 Eina_List *header_list;
972 EINA_LIST_FOREACH_SAFE(st->header_items, l, l_next, header_list)
976 if ((in_index + eina_list_count(header_list)) > index)
978 sti = eina_list_nth(header_list, index - in_index);
981 if (st->cb.fetch.func)
984 if (st->fetch_thread)
988 sti->fetch_th = ecore_thread_run(_store_fetch_do,
997 st->cb.fetch.func(st->cb.fetch.data, sti, sti->item_info);
999 sti->fetched = EINA_TRUE;
1012 in_index = in_index + eina_list_count(header_list);
1020 static Elm_Store_Item *
1021 _item_unfetch(Elm_Store *st, int index)
1023 EINA_SAFETY_ON_NULL_RETURN_VAL(st,NULL);
1026 Elm_Store_Item *sti;
1029 Eina_List *header_list;
1033 EINA_LIST_FOREACH_SAFE(st->header_items, l, l_next, header_list)
1037 if ((in_index + eina_list_count(header_list)) > index)
1039 sti = eina_list_nth(header_list, index - in_index);
1042 if (st->cb.unfetch.func)
1048 ecore_thread_cancel(sti->fetch_th);
1049 sti->fetch_th = NULL;
1053 st->cb.unfetch.func(st->cb.unfetch.data, sti, sti->item_info);
1055 sti->fetched = EINA_FALSE;
1067 in_index = in_index + eina_list_count(header_list);
1075 static const Elm_Store_Item_Mapping *
1076 _item_mapping_find(Elm_Store_Item *sti, const char *part)
1078 if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return NULL;
1079 const Elm_Store_Item_Mapping *m;
1086 for (m = sti->item_info->mapping; m; m++)
1088 if (m->type == ELM_STORE_ITEM_MAPPING_NONE) break;
1089 if (!strcmp(part, m->part)) return m;
1095 _item_realize(Elm_Store_Item *sti)
1097 if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return;
1098 Elm_Store *st = sti->store;
1099 if (sti->store->live)
1101 int index = elm_store_item_index_get(sti);
1105 if ((st->start_fetch_index <= index) && (index <= (st->start_fetch_index + st->cache_max)))
1109 _item_unfetch(st, index);
1111 _item_fetch(st, index);
1113 if(st->end_fetch_index < index)
1115 st->end_fetch_index = index;
1118 else if (st->start_fetch_index > index)
1120 int diff = st->start_fetch_index - index;
1122 for (loop = 1; loop <= diff; loop++)
1124 _item_unfetch(st, st->end_fetch_index);
1125 st->end_fetch_index--;
1126 _item_fetch(sti->store, (st->start_fetch_index - loop));
1128 st->start_fetch_index = index;
1130 else if (index > st->end_fetch_index)
1132 int diff = index - st->end_fetch_index;
1134 for (loop = 1; loop <= diff; loop++)
1136 _item_unfetch(st, st->start_fetch_index);
1137 st->start_fetch_index++;
1138 _item_fetch(st, (st->end_fetch_index + loop));
1140 st->end_fetch_index = index;
1151 _item_label_get(void *data, Evas_Object *obj __UNUSED__, const char *part)
1153 EINA_SAFETY_ON_NULL_RETURN_VAL(data, strdup(""));
1154 Elm_Store_Item *sti = data;
1155 EINA_SAFETY_ON_NULL_RETURN_VAL(sti,NULL);
1157 if (sti->store->live)
1170 const Elm_Store_Item_Mapping *m = _item_mapping_find(sti, part);
1175 case ELM_STORE_ITEM_MAPPING_LABEL:
1176 s = *(char **)(((unsigned char *)sti->data) + m->offset);
1179 case ELM_STORE_ITEM_MAPPING_CUSTOM:
1180 if (m->details.custom.func)
1181 s = m->details.custom.func(sti->data, sti, part);
1205 static Evas_Object *
1206 _item_icon_get(void *data, Evas_Object *obj, const char *part)
1208 EINA_SAFETY_ON_NULL_RETURN_VAL(data,NULL);
1209 Elm_Store_Item *sti = data;
1210 EINA_SAFETY_ON_NULL_RETURN_VAL(sti,NULL);
1212 if (sti->store->live)
1224 const Elm_Store_Item_Mapping *m = _item_mapping_find(sti, part);
1227 Evas_Object *ic = NULL;
1228 const char *s = NULL;
1232 case ELM_STORE_ITEM_MAPPING_ICON:
1233 ic = elm_icon_add(obj);
1234 s = *(char **)(((unsigned char *)sti->data) + m->offset);
1235 elm_icon_order_lookup_set(ic, m->details.icon.lookup_order);
1236 evas_object_size_hint_aspect_set(ic,
1237 EVAS_ASPECT_CONTROL_VERTICAL,
1240 elm_icon_smooth_set(ic, m->details.icon.smooth);
1241 elm_icon_no_scale_set(ic, m->details.icon.no_scale);
1242 elm_icon_scale_set(ic,
1243 m->details.icon.scale_up,
1244 m->details.icon.scale_down);
1248 if (m->details.icon.standard_name)
1249 elm_icon_standard_set(ic, s);
1251 elm_icon_file_set(ic, s, NULL);
1255 case ELM_STORE_ITEM_MAPPING_PHOTO:
1256 ic = elm_icon_add(obj);
1257 s = *(char **)(((unsigned char *)sti->data) + m->offset);
1258 elm_photo_size_set(ic, m->details.photo.size);
1260 elm_photo_file_set(ic, s);
1263 case ELM_STORE_ITEM_MAPPING_CUSTOM:
1264 if (m->details.custom.func)
1265 ic = m->details.custom.func(sti->data, sti, part);
1282 _item_realized(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1284 /* EINA_SAFETY_ON_NULL_RETURN(data);
1285 EINA_SAFETY_ON_NULL_RETURN(event_info);
1286 Elm_Store *st = data;
1287 Elm_Genlist_Item *gli = event_info;
1288 Elm_Store_Item *sti = elm_genlist_item_data_get(gli);
1290 EINA_SAFETY_ON_NULL_RETURN(sti);
1292 int index = elm_store_item_index_get(sti);
1294 if (st->fetch_thread)
1296 if ((st->start_fetch_index <= index) && (index <= st->end_fetch_index))
1298 int middle_index = sti->store->start_fetch_index + (sti->store->cache_max) / 2;
1300 if ((middle_index < index) && (sti->store->end_fetch_index < sti->store->total_item_count))
1302 int diff = index - middle_index;
1304 for (loop = 0; loop < diff; loop++)
1306 _item_unfetch(st, sti->store->start_fetch_index);
1307 sti->store->start_fetch_index++;
1308 _item_fetch(st, (sti->store->end_fetch_index + 1));
1309 sti->store->end_fetch_index++;
1312 else if ((middle_index > index) && (sti->store->start_fetch_index > 0))
1314 int diff = st->current_top_index - index;
1316 for (loop = 0; loop < diff; loop++)
1318 _item_unfetch(st, sti->store->end_fetch_index);
1319 sti->store->end_fetch_index--;
1320 _item_fetch(st, (sti->store->start_fetch_index - 1));
1321 sti->store->start_fetch_index--;
1325 if ((!sti->fetched))
1327 _item_fetch(st, index);
1333 if ((st->current_top_index > index))
1335 st->current_top_index = index;
1337 else if ((st->current_top_index + SCREEN_ITEM_COUNT) < index)
1339 st->current_top_index = st->current_top_index + (index - (st->current_top_index + SCREEN_ITEM_COUNT));
1346 _item_unrealized(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1348 /* EINA_SAFETY_ON_NULL_RETURN(data);
1349 EINA_SAFETY_ON_NULL_RETURN(event_info);
1350 Elm_Genlist_Item *gli = event_info;
1351 Elm_Store_Item *sti = elm_genlist_item_data_get(gli);
1352 EINA_SAFETY_ON_NULL_RETURN(sti);*/
1356 _item_del(void *data, Evas_Object *obj __UNUSED__)
1358 EINA_SAFETY_ON_NULL_RETURN(data);
1359 Elm_Store_Item *sti = data;
1360 EINA_SAFETY_ON_NULL_RETURN(sti);
1361 if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return;
1362 elm_store_item_del(sti);
1366 _list_do(void *data, Ecore_Thread *th __UNUSED__)
1368 EINA_SAFETY_ON_NULL_RETURN(data);
1369 Elm_Store *st = data;
1370 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
1372 if (st->multi_load == EINA_TRUE)
1374 Elm_Store_Item_Info *item_info;
1375 Eina_Bool ok = EINA_FALSE;
1377 for (loop = 0; loop < st->item_count; loop++)
1379 item_info = calloc(1, sizeof(Elm_Store_Item_Info));
1380 if (!item_info) return;
1381 item_info->index = loop;
1383 if (st->cb.list.func)
1385 ok = st->cb.list.func(st->cb.list.data, item_info);
1387 if (ok) ecore_thread_feedback(th, item_info);
1388 else free(item_info);
1389 if (ecore_thread_check(th)) break;
1395 _list_update(void *data, Ecore_Thread *th __UNUSED__, void *msg)
1397 EINA_SAFETY_ON_NULL_RETURN(data);
1398 EINA_SAFETY_ON_NULL_RETURN(msg);
1399 Elm_Store *st = data;
1400 Elm_Store_Item_Info *info = msg;
1402 elm_store_item_add(st, info);
1406 _list_end(void *data, Ecore_Thread *th)
1408 Elm_Store *st = data;
1409 if (th == st->list_th) st->list_th = NULL;
1413 _list_cancel(void *data, Ecore_Thread *th)
1415 Elm_Store *st = data;
1416 if (th == st->list_th) st->list_th = NULL;
1420 _item_select_cb(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
1422 EINA_SAFETY_ON_NULL_RETURN(event_info);
1424 const Elm_Genlist_Item *it = (Elm_Genlist_Item *)event_info;
1425 Elm_Store_Item *sti = elm_genlist_item_data_get(it);
1426 if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return;
1428 if (sti->store->cb.item_select.func)
1430 sti->store->cb.item_select.func(sti->store->cb.item_select.data, sti);
1435 _group_item_append(Elm_Store_Item *sti, Elm_Genlist_Item_Class *itc)
1437 EINA_SAFETY_ON_NULL_RETURN(sti);
1438 if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return;
1439 Elm_Store *st = sti->store;
1442 if (st->header_items)
1444 Eina_Bool header_add = EINA_TRUE;
1447 Eina_List *header_list;
1449 EINA_LIST_FOREACH_SAFE(st->header_items, l, l_next, header_list)
1453 Elm_Store_Item *item = eina_list_nth(header_list, 0);
1454 if(item && item->item_info)
1456 if (item->item_info->group_index == sti->item_info->group_index)
1458 header_add = EINA_FALSE;
1466 Eina_List *new_header_list = NULL;
1467 sti->item_info->index = 0;
1468 new_header_list = eina_list_append(new_header_list, sti);
1469 st->total_item_count++;
1471 Eina_Bool last_header = EINA_TRUE;
1474 Eina_List *header_list;
1476 EINA_LIST_FOREACH_SAFE(st->header_items, l, l_next, header_list)
1480 Elm_Store_Item *group_sti = eina_list_nth(header_list, 0);
1481 if(group_sti && group_sti->item_info)
1483 if(group_sti->item_info->item_type == ELM_GENLIST_ITEM_GROUP)
1486 if (st->cb.item_sort.func)
1488 sort = st->cb.item_sort.func(st->cb.item_sort.data, sti->item_info, group_sti->item_info);
1490 if(sort == ELM_STORE_ITEM_SORT_LOW)
1492 st->header_items = eina_list_prepend_relative(st->header_items, new_header_list, header_list);
1493 sti->item = elm_genlist_item_insert_before(st->genlist,
1498 ELM_GENLIST_ITEM_GROUP,
1501 last_header = EINA_FALSE;
1515 st->header_items = eina_list_append(st->header_items, new_header_list);
1516 sti->item = elm_genlist_item_append(st->genlist,
1520 ELM_GENLIST_ITEM_GROUP,
1524 elm_store_item_update(sti);
1529 Eina_List *header_list = NULL;
1530 sti->item_info->index = 0;
1531 header_list = eina_list_append(header_list, sti);
1532 st->total_item_count++;
1533 st->header_items = eina_list_append(st->header_items, header_list);
1534 sti->item = elm_genlist_item_append(st->genlist,
1538 ELM_GENLIST_ITEM_GROUP,
1541 elm_store_item_update(sti);
1547 _normal_item_append(Elm_Store_Item *sti, Elm_Genlist_Item_Class *itc)
1549 EINA_SAFETY_ON_NULL_RETURN(sti);
1550 if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return;
1551 Elm_Store *st = sti->store;
1554 if (sti->item_info->rec_item == EINA_TRUE)
1556 if (sti->item_info->group_index == sti->item_info->pre_group_index)
1560 Eina_List *header_list;
1562 EINA_LIST_FOREACH_SAFE(st->header_items, l, l_next, header_list)
1566 Elm_Store_Item *header_item = eina_list_nth(header_list, 0);
1567 if(header_item && header_item->item_info)
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);
1605 Eina_List *header_list;
1607 EINA_LIST_FOREACH_SAFE(st->header_items, l, l_next, header_list)
1611 Elm_Store_Item *header_item = eina_list_nth(header_list, 0);
1612 if(header_item && header_item->item_info)
1614 if (header_item->item_info->group_index == sti->item_info->pre_group_index)
1616 Eina_Bool removed = EINA_FALSE;
1618 Eina_List *in_l_next;
1619 Elm_Store_Item *remove_item;
1621 EINA_LIST_FOREACH_SAFE(header_list, in_l, in_l_next, remove_item)
1625 if (removed == EINA_TRUE)
1627 remove_item->item_info->index--;
1632 if (st->cb.item_sort.func)
1634 sort = st->cb.item_sort.func(st->cb.item_sort.data, sti->item_info, remove_item->item_info);
1636 if(sort == ELM_STORE_ITEM_SORT_SAME)
1638 if (remove_item->fetched)
1640 int index = elm_store_item_index_get(remove_item);
1643 _item_unfetch(st, index);
1650 if (st->cb.item_free.func)
1652 st->cb.item_free.func(st->cb.item_free.data, remove_item->item_info);
1653 remove_item->item_info = NULL;
1656 Eina_List *temp_header_list = header_list;
1657 header_list = eina_list_remove(header_list, remove_item);
1658 st->total_item_count--;
1659 LKD(remove_item->lock);
1660 elm_genlist_item_del(remove_item->item);
1663 if (eina_list_count(header_list) == 0)
1665 st->header_items = eina_list_remove(st->header_items, temp_header_list);
1667 else if(eina_list_count(header_list) == 1)
1669 Elm_Store_Item *temp_sti = eina_list_nth(header_list, 0);
1670 if(temp_sti && temp_sti->item_info)
1672 if (temp_sti->item_info->item_type == ELM_GENLIST_ITEM_GROUP)
1674 if (temp_sti->fetched)
1676 int index = elm_store_item_index_get(temp_sti);
1679 _item_unfetch(st, index);
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;
1693 header_list = eina_list_remove(header_list, temp_sti);
1694 st->total_item_count--;
1695 LKD(temp_sti->lock);
1696 elm_genlist_item_del(temp_sti->item);
1698 st->header_items = eina_list_remove(st->header_items, temp_header_list);
1702 temp_header_list = NULL;
1703 removed = EINA_TRUE;
1714 else if (header_item->item_info->group_index == sti->item_info->group_index)
1716 Eina_Bool last_add = EINA_TRUE;
1718 Eina_List *in_l_next;
1719 Elm_Store_Item *comp_item;
1721 EINA_LIST_FOREACH_SAFE(header_list, in_l, in_l_next, comp_item)
1725 if(last_add == EINA_FALSE)
1727 comp_item->item_info->index++;
1732 if (st->cb.item_sort.func)
1734 sort = st->cb.item_sort.func(st->cb.item_sort.data, sti->item_info, comp_item->item_info);
1736 if(sort == ELM_STORE_ITEM_SORT_LOW)
1738 sti->item_info->index = comp_item->item_info->index;
1739 comp_item->item_info->index++;
1740 header_list = eina_list_prepend_relative(header_list, sti, comp_item);
1741 st->total_item_count++;
1742 sti->item = elm_genlist_item_insert_before(st->genlist,
1747 ELM_GENLIST_ITEM_NONE,
1748 (Evas_Smart_Cb)sti->store->cb.item_select.func,
1749 (void *)sti->store->cb.item_select.data);
1750 elm_store_item_update(sti);
1751 last_add = EINA_FALSE;
1756 Elm_Store_Item *last_sti = eina_list_nth(header_list, eina_list_count(header_list) - 1);
1757 sti->item_info->index = eina_list_count(header_list);
1758 header_list = eina_list_append(header_list, sti);
1759 st->total_item_count++;
1760 sti->item = elm_genlist_item_insert_after(st->genlist,
1765 ELM_GENLIST_ITEM_NONE,
1766 (Evas_Smart_Cb)sti->store->cb.item_select.func,
1767 (void *)sti->store->cb.item_select.data);
1768 elm_store_item_update(sti);
1769 last_add = EINA_FALSE;
1777 Elm_Store_Item *last_sti = eina_list_nth(header_list, eina_list_count(header_list) - 1);
1778 sti->item_info->index = eina_list_count(header_list);
1779 header_list = eina_list_append(header_list, sti);
1780 st->total_item_count++;
1781 sti->item = elm_genlist_item_insert_after(st->genlist,
1786 ELM_GENLIST_ITEM_NONE,
1787 (Evas_Smart_Cb)sti->store->cb.item_select.func,
1788 (void *)sti->store->cb.item_select.data);
1789 elm_store_item_update(sti);
1799 if (st->header_items)
1801 Eina_Bool normal_add = EINA_TRUE;
1804 Eina_List *header_list;
1806 EINA_LIST_FOREACH_SAFE(st->header_items, l, l_next, header_list)
1810 Elm_Store_Item *header_item = eina_list_nth(header_list, 0);
1812 if(header_item && header_item->item_info)
1814 if (header_item->item_info->group_index == sti->item_info->group_index)
1817 Eina_List *in_l_next;
1818 Elm_Store_Item *comp_item;
1820 EINA_LIST_FOREACH_SAFE(header_list, in_l, in_l_next, comp_item)
1824 if(normal_add == EINA_FALSE)
1826 comp_item->item_info->index++;
1831 if (st->cb.item_sort.func)
1833 sort = st->cb.item_sort.func(st->cb.item_sort.data, sti->item_info, comp_item->item_info);
1835 if(sort == ELM_STORE_ITEM_SORT_LOW)
1837 sti->item_info->index = comp_item->item_info->index;
1838 comp_item->item_info->index++;
1839 header_list = eina_list_prepend_relative(header_list, sti, comp_item);
1840 st->total_item_count++;
1841 sti->item = elm_genlist_item_insert_before(st->genlist,
1846 ELM_GENLIST_ITEM_NONE,
1847 (Evas_Smart_Cb)sti->store->cb.item_select.func,
1848 (void *)sti->store->cb.item_select.data);
1849 normal_add = EINA_FALSE;
1850 elm_store_item_update(sti);
1855 Elm_Store_Item *last_sti = eina_list_nth(header_list, eina_list_count(header_list) - 1);
1856 sti->item_info->index = eina_list_count(header_list);
1857 header_list = eina_list_append(header_list, sti);
1858 st->total_item_count++;
1859 sti->item = elm_genlist_item_insert_after(st->genlist,
1864 ELM_GENLIST_ITEM_NONE,
1865 (Evas_Smart_Cb)sti->store->cb.item_select.func,
1866 (void *)sti->store->cb.item_select.data);
1867 normal_add = EINA_FALSE;
1868 elm_store_item_update(sti);
1876 Elm_Store_Item *last_sti = eina_list_nth(header_list, eina_list_count(header_list) - 1);
1877 sti->item_info->index = eina_list_count(header_list);
1878 header_list = eina_list_append(header_list, sti);
1879 st->total_item_count++;
1880 sti->item = elm_genlist_item_insert_after(st->genlist,
1885 ELM_GENLIST_ITEM_NONE,
1886 (Evas_Smart_Cb)sti->store->cb.item_select.func,
1887 (void *)sti->store->cb.item_select.data);
1888 normal_add = EINA_FALSE;
1889 elm_store_item_update(sti);
1891 if(normal_add == EINA_FALSE)
1901 Eina_List *new_header_list = NULL;
1902 sti->item_info->index = 0;
1903 new_header_list = eina_list_append(new_header_list, sti);
1904 st->total_item_count++;
1905 st->header_items = eina_list_append(st->header_items, new_header_list);
1906 sti->item = elm_genlist_item_append(st->genlist,
1910 ELM_GENLIST_ITEM_NONE,
1911 (Evas_Smart_Cb)sti->store->cb.item_select.func,
1912 (void *)sti->store->cb.item_select.data);
1913 elm_store_item_update(sti);
1920 Eina_List *new_header_list = NULL;
1921 sti->item_info->index = 0;
1922 new_header_list = eina_list_append(new_header_list, sti);
1923 st->total_item_count++;
1924 st->header_items = eina_list_append(st->header_items, new_header_list);
1925 sti->item = elm_genlist_item_append(st->genlist,
1929 ELM_GENLIST_ITEM_NONE,
1930 (Evas_Smart_Cb)sti->store->cb.item_select.func,
1931 (void *)sti->store->cb.item_select.data);
1932 elm_store_item_update(sti);
1940 _item_free(Elm_Store_Item *sti)
1942 if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return;
1943 elm_store_item_del(sti);
1947 _store_free(Elm_Store *st)
1949 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
1951 Elm_Store_DBsystem *std = (Elm_Store_DBsystem *)st;
1952 eina_stringshare_del(std->p_db);
1957 * Add a new dbsystem Store object
1959 * @return The new object or NULL if it cannot be created
1964 elm_store_dbsystem_new(void)
1966 Elm_Store_DBsystem *std = _store_new(Elm_Store_DBsystem);
1967 EINA_SAFETY_ON_NULL_RETURN_VAL(std, NULL);
1969 EINA_MAGIC_SET(std, ELM_STORE_DBSYSTEM_MAGIC);
1970 std->base.free = _store_free;
1971 std->base.item.free = _item_free;
1976 * Sets the item count of a store
1978 * @param st The store object
1979 * @param count The item count of an store
1984 elm_store_item_count_set(Elm_Store *st, int count)
1986 EINA_SAFETY_ON_NULL_RETURN(st);
1987 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
1989 st->item_count = count;
1992 st->multi_load = EINA_TRUE;
1996 st->multi_load = EINA_FALSE;
2002 * Set the select func that select the state of a list item whether true or false
2004 * @param st The store object
2005 * @param func The select cb function of an store
2006 * @param data The new data pointer to set
2011 elm_store_item_select_func_set(Elm_Store *st, Elm_Store_Item_Select_Cb func, const void *data)
2013 EINA_SAFETY_ON_NULL_RETURN(st);
2014 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
2016 st->cb.item_select.func = func;
2017 st->cb.item_select.data = (void *)data;
2021 * Sets the sort func that sort the item with a next in the list
2023 * @param st The store object
2024 * @param func The sort cb function of an store
2025 * @param data The new data pointer to set
2030 elm_store_item_sort_func_set(Elm_Store *st, Elm_Store_Item_Sort_Cb func, const void *data)
2032 EINA_SAFETY_ON_NULL_RETURN(st);
2033 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
2035 st->cb.item_sort.func = func;
2036 st->cb.item_sort.data = (void *)data;
2040 * Set the store item free func
2042 * @param st The store object
2043 * @param func The free cb function of an store
2044 * @param data The new data pointer to set
2049 elm_store_item_free_func_set(Elm_Store *st, Elm_Store_Item_Free_Cb func, const void *data)
2051 EINA_SAFETY_ON_NULL_RETURN(st);
2052 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
2054 st->cb.item_free.func = func;
2055 st->cb.item_free.data = (void *)data;
2059 * Get the item index that included header items
2061 * @param sti The store item object
2062 * @return The item index in genlist
2067 elm_store_item_index_get(const Elm_Store_Item *sti)
2069 EINA_SAFETY_ON_NULL_RETURN_VAL(sti, -1);
2070 if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return -1;
2071 Elm_Store *st = sti->store;
2078 Eina_List *header_list;
2080 EINA_LIST_FOREACH_SAFE(st->header_items, l, l_next, header_list)
2084 Elm_Store_Item *temp_sti = eina_list_nth(header_list, 0);
2085 if(temp_sti && temp_sti->item_info && sti->item_info)
2087 if (sti->item_info->group_index == temp_sti->item_info->group_index)
2090 Eina_List *in_l_next;
2091 Elm_Store_Item *comp_item;
2093 EINA_LIST_FOREACH_SAFE(header_list, in_l, in_l_next, comp_item)
2097 if (comp_item->item_info->index == sti->item_info->index)
2110 index = index + eina_list_count(header_list);
2124 * Get the item index of real data that don't included header items
2126 * @param sti The store item object
2127 * @return The real item index
2132 elm_store_item_data_index_get(const Elm_Store_Item *sti)
2134 EINA_SAFETY_ON_NULL_RETURN_VAL(sti, -1);
2135 if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return -1;
2136 Elm_Store *st = sti->store;
2140 if (sti->item_info->item_type == ELM_GENLIST_ITEM_NONE)
2143 int group_item_count = 0;
2146 Eina_List *header_list;
2148 EINA_LIST_FOREACH_SAFE(st->header_items, l, l_next, header_list)
2152 Elm_Store_Item *temp_sti = eina_list_nth(header_list, 0);
2153 if(temp_sti && temp_sti->item_info && sti->item_info)
2156 if(temp_sti->item_info->item_type == ELM_GENLIST_ITEM_GROUP)
2161 if (temp_sti->item_info->group_index == sti->item_info->group_index)
2164 Eina_List *in_l_next;
2165 Elm_Store_Item *comp_item;
2167 EINA_LIST_FOREACH_SAFE(header_list, in_l, in_l_next, comp_item)
2171 if (comp_item->item_info->index == sti->item_info->index)
2173 return (index - group_item_count);
2185 index = index + eina_list_count(header_list);
2199 * Get the DB pointer of an item
2201 * @param sti The store item object
2202 * @return The DB pointer of item
2207 elm_store_dbsystem_db_get(const Elm_Store_Item *sti)
2209 if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return NULL;
2211 const Elm_Store_DBsystem *std = (const Elm_Store_DBsystem *)sti->store;
2212 if (!EINA_MAGIC_CHECK(sti->store, ELM_STORE_MAGIC)) return NULL;
2213 if (!EINA_MAGIC_CHECK(std, ELM_STORE_DBSYSTEM_MAGIC)) return NULL;
2218 * Set the DB pointer of an item
2220 * @param sti The store item object
2221 * @parm p_db The DB pointer of item
2226 elm_store_dbsystem_db_set(Elm_Store *store, void *p_db)
2228 Elm_Store_DBsystem *std = (Elm_Store_DBsystem *)store;
2229 if (!EINA_MAGIC_CHECK(store, ELM_STORE_MAGIC)) return;
2230 if (!EINA_MAGIC_CHECK(std, ELM_STORE_DBSYSTEM_MAGIC)) return;
2236 ecore_thread_cancel(store->list_th);
2237 store->list_th = NULL;
2239 store->list_th = ecore_thread_feedback_run(_list_do, _list_update, _list_end, _list_cancel, store, EINA_TRUE);
2243 * Append the item to the genlist
2245 * @param st The store object
2246 * @param info The store item info dbsystem object
2247 * @return The item of store
2251 EAPI Elm_Store_Item *
2252 elm_store_item_add(Elm_Store *st, Elm_Store_Item_Info *info)
2254 EINA_SAFETY_ON_NULL_RETURN_VAL(st, NULL);
2255 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return NULL;
2256 EINA_SAFETY_ON_NULL_RETURN_VAL(info, NULL);
2257 Elm_Store_Item *sti;
2258 Elm_Genlist_Item_Class *itc;
2260 sti = calloc(1, sizeof(Elm_Store_Item));
2261 if (!sti) return NULL;
2264 EINA_MAGIC_SET(sti, ELM_STORE_ITEM_MAGIC);
2267 sti->item_info = info;
2268 sti->fetched = EINA_FALSE;
2270 itc = info->item_class;
2271 if (!itc) itc = &_store_item_class;
2274 itc->func.label_get = (GenlistItemLabelGetFunc)_item_label_get;
2275 itc->func.icon_get = (GenlistItemIconGetFunc)_item_icon_get;
2276 itc->func.state_get = NULL;
2277 itc->func.del = NULL;
2282 if (sti->item_info->item_type == ELM_GENLIST_ITEM_GROUP)
2284 _group_item_append(sti, itc);
2288 _normal_item_append(sti, itc);
2299 * Realize the visible items to the screen
2301 * @param st The store object
2306 elm_store_visible_items_update(Elm_Store *st)
2308 EINA_SAFETY_ON_NULL_RETURN(st);
2309 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
2311 Eina_List *realized_list = elm_genlist_realized_items_get(st->genlist);
2315 Elm_Genlist_Item *it;
2316 EINA_LIST_FOREACH(realized_list, l, it)
2320 Elm_Store_Item *realized_sti = elm_genlist_item_data_get(it);
2321 int index = elm_store_item_index_get(realized_sti);
2324 if(realized_sti->fetched)
2326 _item_unfetch(st, index);
2328 _item_fetch(st, index);
2329 if (realized_sti->data) elm_genlist_item_update(realized_sti->item);
2341 * Realize the item to the screen
2343 * @param sti The store item object
2348 elm_store_item_update(Elm_Store_Item *sti)
2350 EINA_SAFETY_ON_NULL_RETURN(sti);
2351 if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return;
2352 Elm_Store *st = sti->store;
2354 int index = elm_store_item_index_get(sti);
2357 if ((st->start_fetch_index <= index) && (index <= (st->start_fetch_index + st->cache_max)))
2361 _item_unfetch(st, index);
2363 _item_fetch(st, index);
2365 if(st->end_fetch_index < (st->total_item_count-1))
2367 if( (st->end_fetch_index - st->cache_max) == st->start_fetch_index)
2369 _item_unfetch(st, (st->total_item_count-1));
2373 st->end_fetch_index = (st->total_item_count-1);
2376 if(sti->data) elm_genlist_item_update(sti->item);
2386 * Delete the item of genlist
2388 * @param sti The store item object
2393 elm_store_item_del(Elm_Store_Item *sti)
2395 EINA_SAFETY_ON_NULL_RETURN(sti);
2396 if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return;
2397 Elm_Store *st = sti->store;
2401 Eina_List *header_list;
2405 EINA_LIST_FOREACH_SAFE(st->header_items, l, l_next, header_list)
2409 Elm_Store_Item *header_item = eina_list_nth(header_list, 0);
2410 if(header_item && header_item->item_info && sti->item_info)
2413 if (header_item->item_info->group_index == sti->item_info->group_index)
2415 Eina_Bool removed = EINA_FALSE;
2417 Eina_List *in_l_next;
2418 Elm_Store_Item *remove_sti;
2419 EINA_LIST_FOREACH_SAFE(header_list, in_l, in_l_next, remove_sti)
2423 if (removed == EINA_TRUE)
2425 remove_sti->item_info->index--;
2429 if (remove_sti->item_info->index == sti->item_info->index)
2431 if (remove_sti->fetched)
2433 int index = elm_store_item_index_get(remove_sti);
2436 _item_unfetch(st, index);
2443 if (st->cb.item_free.func)
2445 st->cb.item_free.func(st->cb.item_free.data, remove_sti->item_info);
2446 remove_sti->item_info = NULL;
2449 Eina_List *temp_header_list = header_list;
2450 header_list = eina_list_remove(header_list, remove_sti);
2451 st->total_item_count--;
2452 LKD(remove_sti->lock);
2453 elm_genlist_item_del(remove_sti->item);
2456 if (eina_list_count(header_list) == 0)
2458 st->header_items = eina_list_remove(st->header_items, temp_header_list);
2460 else if (eina_list_count(header_list) == 1)
2462 Elm_Store_Item *temp_sti = eina_list_nth(header_list, 0);
2463 if(temp_sti && temp_sti->item_info)
2465 if (temp_sti->item_info->item_type == ELM_GENLIST_ITEM_GROUP)
2467 if (temp_sti->fetched)
2469 int index = elm_store_item_index_get(temp_sti);
2472 _item_unfetch(st, index);
2479 if (st->cb.item_free.func)
2481 st->cb.item_free.func(st->cb.item_free.data, temp_sti->item_info);
2482 temp_sti->item_info = NULL;
2485 header_list = eina_list_remove(header_list, temp_sti);
2486 st->total_item_count--;
2487 LKD(temp_sti->lock);
2488 elm_genlist_item_del(temp_sti->item);
2490 st->header_items = eina_list_remove(st->header_items, temp_header_list);
2494 temp_header_list = NULL;
2495 removed = EINA_TRUE;
2507 // TODO: END -DBsystem store