1 #ifdef HAVE_CONFIG_H
2 # include "elementary_config.h"
3 #endif
4
5 #include <Elementary.h>
6 #include <Elementary_Cursor.h>
7
8 #include "elm_priv.h"
9 #include "elm_genlist_eo.h"
10
11 typedef struct _Elm_Store_Filesystem Elm_Store_Filesystem;
12 typedef struct _Elm_Store_Item_Filesystem Elm_Store_Item_Filesystem;
13
14 #define ELM_STORE_MAGIC 0x3f89ea56
15 #define ELM_STORE_FILESYSTEM_MAGIC 0x3f89ea57
16 #define ELM_STORE_ITEM_MAGIC 0x5afe8c1d
17
18 struct _Elm_Store
19 {
20 EINA_MAGIC;
21 void (*free)(Elm_Store *store);
22 struct
23 {
24 void (*free)(Elm_Store_Item *item);
25 } item;
26 Evas_Object *genlist;
27 Ecore_Thread *list_th;
28 Eina_Inlist *items;
29 Eina_List *realized;
30 int realized_count;
31 int cache_max;
32 struct
33 {
34 struct
35 {
36 Elm_Store_Item_List_Cb func;
37 void *data;
38 } list;
39 struct
40 {
41 Elm_Store_Item_Fetch_Cb func;
42 void *data;
43 } fetch;
44 struct
45 {
46 Elm_Store_Item_Unfetch_Cb func;
47 void *data;
48 } unfetch;
49 } cb;
50 Eina_Bool sorted : 1;
51 Eina_Bool fetch_thread : 1;
52 };
53
54 struct _Elm_Store_Item
55 {
56 EINA_INLIST;
57 EINA_MAGIC;
58 Elm_Store *store;
59 Elm_Object_Item *item;
60 Ecore_Thread *fetch_th;
61 Ecore_Job *eval_job;
62 const Elm_Store_Item_Mapping *mapping;
63 void *data;
64 Eina_Lock lock;
65 Eina_Bool live : 1;
66 Eina_Bool was_live : 1;
67 Eina_Bool realized : 1;
68 Eina_Bool fetched : 1;
69 };
70
71 struct _Elm_Store_Filesystem
72 {
73 Elm_Store base;
74 EINA_MAGIC;
75 const char *dir;
76 };
77
78 struct _Elm_Store_Item_Filesystem
79 {
80 Elm_Store_Item base;
81 const char *path;
82 };
83
84 static Elm_Genlist_Item_Class _store_item_class;
85
86 static void
_store_cache_trim(Elm_Store * st)87 _store_cache_trim(Elm_Store *st)
88 {
89 while ((st->realized) &&
90 (((int)eina_list_count(st->realized) - st->realized_count)
91 > st->cache_max))
92 {
93 Elm_Store_Item *sti = st->realized->data;
94 if (sti->realized)
95 {
96 st->realized = eina_list_remove_list(st->realized, st->realized);
97 sti->realized = EINA_FALSE;
98 }
99 eina_lock_take(&sti->lock);
100 if (!sti->fetched)
101 {
102 eina_lock_release(&sti->lock);
103 ELM_SAFE_FREE(sti->fetch_th, ecore_thread_cancel);
104 eina_lock_take(&sti->lock);
105 }
106 sti->fetched = EINA_FALSE;
107 //// let fetch/unfetch do the locking
108 // eina_lock_release(&sti->lock);
109 if (st->cb.unfetch.func)
110 st->cb.unfetch.func(st->cb.unfetch.data, sti);
111 // eina_lock_take(&sti->lock);
112 sti->data = NULL;
113 eina_lock_release(&sti->lock);
114 }
115 }
116
117 static void
_store_genlist_del(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)118 _store_genlist_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
119 {
120 Elm_Store *st = data;
121 st->genlist = NULL;
122 ELM_SAFE_FREE(st->list_th, ecore_thread_cancel);
123 st->realized = eina_list_free(st->realized);
124 while (st->items)
125 {
126 Elm_Store_Item *sti = (Elm_Store_Item *)st->items;
127 ELM_SAFE_FREE(sti->eval_job, ecore_job_del);
128 ELM_SAFE_FREE(sti->fetch_th, ecore_thread_cancel);
129 if (sti->store->item.free) sti->store->item.free(sti);
130 eina_lock_take(&sti->lock);
131 if (sti->data)
132 {
133 if (st->cb.unfetch.func)
134 st->cb.unfetch.func(st->cb.unfetch.data, sti);
135 sti->data = NULL;
136 }
137 eina_lock_release(&sti->lock);
138 eina_lock_free(&sti->lock);
139 st->items = eina_inlist_remove(st->items, EINA_INLIST_GET(sti));
140 free(sti);
141 }
142 // FIXME: kill threads and more
143 }
144
145 ////// **** WARNING ***********************************************************
146 //// * This function runs inside a thread outside efl mainloop. Be careful! *
147 // ************************************************************************
148 /* TODO: refactor lock part into core? this does not depend on filesystem part */
149 static void
_store_filesystem_fetch_do(void * data,Ecore_Thread * th EINA_UNUSED)150 _store_filesystem_fetch_do(void *data, Ecore_Thread *th EINA_UNUSED)
151 {
152 Elm_Store_Item *sti = data;
153 eina_lock_take(&sti->lock);
154 if (sti->data)
155 {
156 eina_lock_release(&sti->lock);
157 return;
158 }
159 if (!sti->fetched)
160 {
161 //// let fetch/unfetch do the locking
162 // eina_lock_release(&sti->lock);
163 if (sti->store->cb.fetch.func)
164 sti->store->cb.fetch.func(sti->store->cb.fetch.data, sti);
165 // eina_lock_take(&sti->lock);
166 sti->fetched = EINA_TRUE;
167 }
168 eina_lock_release(&sti->lock);
169 }
170 // ************************************************************************
171 //// * End of separate thread function. *
172 ////// ************************************************************************
173 /* TODO: refactor lock part into core? this does not depend on filesystem part */
174 static void
_store_filesystem_fetch_end(void * data,Ecore_Thread * th)175 _store_filesystem_fetch_end(void *data, Ecore_Thread *th)
176 {
177 Elm_Store_Item *sti = data;
178 eina_lock_take(&sti->lock);
179 if (sti->data) elm_genlist_item_update(sti->item);
180 eina_lock_release(&sti->lock);
181 if (th == sti->fetch_th) sti->fetch_th = NULL;
182 }
183
184 /* TODO: refactor lock part into core? this does not depend on filesystem part */
185 static void
_store_filesystem_fetch_cancel(void * data,Ecore_Thread * th)186 _store_filesystem_fetch_cancel(void *data, Ecore_Thread *th)
187 {
188 Elm_Store_Item *sti = data;
189 eina_lock_take(&sti->lock);
190 if (th == sti->fetch_th) sti->fetch_th = NULL;
191 if (sti->data) elm_genlist_item_update(sti->item);
192 eina_lock_release(&sti->lock);
193 }
194
195 static void
_store_item_eval(void * data)196 _store_item_eval(void *data)
197 {
198 Elm_Store_Item *sti = data;
199 sti->eval_job = NULL;
200 if (sti->live == sti->was_live) return;
201 sti->was_live = sti->live;
202 if (sti->live)
203 {
204 _store_cache_trim(sti->store);
205 if (sti->realized)
206 sti->store->realized = eina_list_remove(sti->store->realized, sti);
207 sti->store->realized = eina_list_append(sti->store->realized, sti);
208 sti->realized = EINA_TRUE;
209 if ((sti->store->fetch_thread) && (!sti->fetch_th))
210 sti->fetch_th = ecore_thread_run(_store_filesystem_fetch_do,
211 _store_filesystem_fetch_end,
212 _store_filesystem_fetch_cancel,
213 sti);
214 else if ((!sti->store->fetch_thread))
215 {
216 _store_filesystem_fetch_do(sti, NULL);
217 _store_filesystem_fetch_end(sti, NULL);
218 }
219 }
220 else
221 {
222 ELM_SAFE_FREE(sti->fetch_th, ecore_thread_cancel);
223 _store_cache_trim(sti->store);
224 }
225 }
226
227 static void
_store_genlist_item_realized(void * data,const Efl_Event * event)228 _store_genlist_item_realized(void *data, const Efl_Event *event)
229 {
230 Elm_Store *st = data;
231 Elm_Object_Item *gli = event->info;
232 Elm_Store_Item *sti = elm_object_item_data_get(gli);
233 if (!sti) return;
234 st->realized_count++;
235 sti->live = EINA_TRUE;
236 ecore_job_del(sti->eval_job);
237 sti->eval_job = ecore_job_add(_store_item_eval, sti);
238 }
239
240 static void
_store_genlist_item_unrealized(void * data,const Efl_Event * event)241 _store_genlist_item_unrealized(void *data, const Efl_Event *event)
242 {
243 Elm_Store *st = data;
244 Elm_Object_Item *gli = event->info;
245 Elm_Store_Item *sti = elm_object_item_data_get(gli);
246 if (!sti) return;
247 st->realized_count--;
248 sti->live = EINA_FALSE;
249 ecore_job_del(sti->eval_job);
250 sti->eval_job = ecore_job_add(_store_item_eval, sti);
251 }
252
253 static const Elm_Store_Item_Mapping *
_store_item_mapping_find(Elm_Store_Item * sti,const char * part)254 _store_item_mapping_find(Elm_Store_Item *sti, const char *part)
255 {
256 const Elm_Store_Item_Mapping *m;
257
258 for (m = sti->mapping; m; m ++)
259 {
260 if (m->type == ELM_STORE_ITEM_MAPPING_NONE) break;
261 if (!strcmp(part, m->part)) return m;
262 }
263 return NULL;
264 }
265
266 static char *
_store_item_text_get(void * data,Evas_Object * obj EINA_UNUSED,const char * part)267 _store_item_text_get(void *data, Evas_Object *obj EINA_UNUSED, const char *part)
268 {
269 Elm_Store_Item *sti = data;
270 const char *s = "";
271 eina_lock_take(&sti->lock);
272 if (sti->data)
273 {
274 const Elm_Store_Item_Mapping *m = _store_item_mapping_find(sti, part);
275 if (m)
276 {
277 switch (m->type)
278 {
279 case ELM_STORE_ITEM_MAPPING_LABEL:
280 s = *(char **)(((unsigned char *)sti->data) + m->offset);
281 break;
282 case ELM_STORE_ITEM_MAPPING_CUSTOM:
283 if (m->details.custom.func)
284 s = m->details.custom.func(sti->data, sti, part);
285 break;
286 default:
287 break;
288 }
289 }
290 }
291 eina_lock_release(&sti->lock);
292 return s ? strdup(s) : NULL;
293 }
294
295 static Evas_Object *
_store_item_content_get(void * data,Evas_Object * obj,const char * part)296 _store_item_content_get(void *data, Evas_Object *obj, const char *part)
297 {
298 Elm_Store_Item *sti = data;
299 eina_lock_take(&sti->lock);
300 if (sti->data)
301 {
302 const Elm_Store_Item_Mapping *m = _store_item_mapping_find(sti, part);
303 if (m)
304 {
305 Evas_Object *ic = NULL;
306 const char *s = NULL;
307
308 switch (m->type)
309 {
310 case ELM_STORE_ITEM_MAPPING_ICON:
311 ic = elm_icon_add(obj);
312 s = *(char **)(((unsigned char *)sti->data) + m->offset);
313 evas_object_size_hint_aspect_set(ic,
314 EVAS_ASPECT_CONTROL_VERTICAL,
315 m->details.icon.w,
316 m->details.icon.h);
317 elm_image_smooth_set(ic, m->details.icon.smooth);
318 elm_image_no_scale_set(ic, m->details.icon.no_scale);
319 elm_image_resizable_set(ic,
320 m->details.icon.scale_up,
321 m->details.icon.scale_down);
322 if (s)
323 {
324 if (m->details.icon.standard_name)
325 elm_icon_standard_set(ic, s);
326 else
327 elm_image_file_set(ic, s, NULL);
328 }
329 break;
330 case ELM_STORE_ITEM_MAPPING_PHOTO:
331 ic = elm_icon_add(obj);
332 s = *(char **)(((unsigned char *)sti->data) + m->offset);
333 elm_photo_size_set(ic, m->details.photo.size);
334 if (s)
335 elm_photo_file_set(ic, s);
336 break;
337 case ELM_STORE_ITEM_MAPPING_CUSTOM:
338 if (m->details.custom.func)
339 ic = m->details.custom.func(sti->data, sti, part);
340 break;
341 default:
342 break;
343 }
344 eina_lock_release(&sti->lock);
345 return ic;
346 }
347 }
348 eina_lock_release(&sti->lock);
349 return NULL;
350 }
351
352 static void
_store_item_del(void * data EINA_UNUSED,Evas_Object * obj EINA_UNUSED)353 _store_item_del(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED)
354 {
355 }
356
357 ////// **** WARNING ***********************************************************
358 //// * This function runs inside a thread outside efl mainloop. Be careful! *
359 // ************************************************************************
360 static int
_store_filesystem_sort_cb(void * d1,void * d2)361 _store_filesystem_sort_cb(void *d1, void *d2)
362 {
363 Elm_Store_Item_Info *info1 = d1, *info2 = d2;
364 if ((!info1->sort_id) || (!info2->sort_id)) return 0;
365 return strcoll(info1->sort_id, info2->sort_id);
366 }
367
368 static void
_store_filesystem_list_do(void * data,Ecore_Thread * th EINA_UNUSED)369 _store_filesystem_list_do(void *data, Ecore_Thread *th EINA_UNUSED)
370 {
371 Elm_Store_Filesystem *st = data;
372 Eina_Iterator *it;
373 const Eina_File_Direct_Info *finf;
374 Eina_List *sorted = NULL;
375 Elm_Store_Item_Info_Filesystem *info;
376
377 // FIXME: need a way to abstract the open, list, feed items from list
378 // and maybe get initial sortable key vals etc.
379 it = eina_file_stat_ls(st->dir);
380 if (!it) return;
381 EINA_ITERATOR_FOREACH(it, finf)
382 {
383 Eina_Bool ok;
384 size_t pathsz = finf->path_length + 1;
385
386 if (finf->path[finf->name_start] == '.') continue ;
387
388 info = calloc(1, sizeof(Elm_Store_Item_Info_Filesystem) + pathsz);
389 if (!info) continue;
390 info->path = ((char *)info) + sizeof(Elm_Store_Item_Info_Filesystem);
391 memcpy(info->path, finf->path, pathsz);
392 ok = EINA_TRUE;
393 if (st->base.cb.list.func)
394 ok = st->base.cb.list.func(st->base.cb.list.data, &info->base);
395 if (ok)
396 {
397 if (!st->base.sorted) ecore_thread_feedback(th, info);
398 else sorted = eina_list_append(sorted, info);
399 }
400 else
401 {
402 free(info->base.sort_id);
403 free(info);
404 }
405 if (ecore_thread_check(th)) break;
406 }
407 eina_iterator_free(it);
408 if (sorted)
409 {
410 sorted = eina_list_sort(sorted, 0,
411 EINA_COMPARE_CB(_store_filesystem_sort_cb));
412 EINA_LIST_FREE(sorted, info)
413 {
414 if (!ecore_thread_check(th)) ecore_thread_feedback(th, info);
415 }
416 }
417 }
418 // ************************************************************************
419 //// * End of separate thread function. *
420 ////// ************************************************************************
421
422 static void
_store_filesystem_list_end(void * data,Ecore_Thread * th)423 _store_filesystem_list_end(void *data, Ecore_Thread *th)
424 {
425 Elm_Store *st = data;
426 if (th == st->list_th) st->list_th = NULL;
427 }
428
429 static void
_store_filesystem_list_cancel(void * data,Ecore_Thread * th)430 _store_filesystem_list_cancel(void *data, Ecore_Thread *th)
431 {
432 Elm_Store *st = data;
433 if (th == st->list_th) st->list_th = NULL;
434 }
435
436 static void
_store_filesystem_list_update(void * data,Ecore_Thread * th EINA_UNUSED,void * msg)437 _store_filesystem_list_update(void *data, Ecore_Thread *th EINA_UNUSED, void *msg)
438 {
439 Elm_Store *st = data;
440 Elm_Store_Item_Filesystem *sti;
441 Elm_Genlist_Item_Class *itc;
442 Elm_Store_Item_Info_Filesystem *info = msg;
443
444 sti = calloc(1, sizeof(Elm_Store_Item_Filesystem));
445 if (!sti) goto done;
446 eina_lock_new(&sti->base.lock);
447 EINA_MAGIC_SET(&(sti->base), ELM_STORE_ITEM_MAGIC);
448 sti->base.store = st;
449 sti->base.data = info->base.data;
450 sti->base.mapping = info->base.mapping;
451 sti->path = eina_stringshare_add(info->path);
452
453 itc = info->base.item_class;
454 if (!itc) itc = &_store_item_class;
455 else
456 {
457 itc->func.text_get = _store_item_text_get;
458 itc->func.content_get = _store_item_content_get;
459 itc->func.state_get = NULL; // FIXME: support state gets later
460 itc->func.del = _store_item_del;
461 }
462
463 // FIXME: handle being a parent (tree)
464 sti->base.item = elm_genlist_item_append(st->genlist, itc,
465 sti/* item data */,
466 NULL/* parent */,
467 ELM_GENLIST_ITEM_NONE,
468 NULL/* func */,
469 NULL/* func data */);
470 st->items = eina_inlist_append(st->items, (Eina_Inlist *)sti);
471 done:
472 free(info->base.sort_id);
473 free(info);
474 }
475
476 // public api calls
477 static Elm_Store *
_elm_store_new(size_t size)478 _elm_store_new(size_t size)
479 {
480 Elm_Store *st = calloc(1, size);
481 EINA_SAFETY_ON_NULL_RETURN_VAL(st, NULL);
482
483 // TODO: BEGIN - move to elm_store_init()
484 eina_magic_string_set(ELM_STORE_MAGIC, "Elm_Store");
485 eina_magic_string_set(ELM_STORE_FILESYSTEM_MAGIC, "Elm_Store_Filesystem");
486 eina_magic_string_set(ELM_STORE_ITEM_MAGIC, "Elm_Store_Item");
487 // setup default item class (always the same) if list cb doesn't provide one
488 _store_item_class.item_style = "default";
489 _store_item_class.func.text_get = _store_item_text_get;
490 _store_item_class.func.content_get = _store_item_content_get;
491 _store_item_class.func.state_get = NULL; // FIXME: support state gets later
492 _store_item_class.func.del = _store_item_del;
493 // TODO: END - move to elm_store_init()
494
495 EINA_MAGIC_SET(st, ELM_STORE_MAGIC);
496 st->cache_max = 128;
497 st->fetch_thread = EINA_TRUE;
498 return st;
499 }
500 #define elm_store_new(type) (type*)_elm_store_new(sizeof(type))
501
502 static void
_elm_store_filesystem_free(Elm_Store * store)503 _elm_store_filesystem_free(Elm_Store *store)
504 {
505 Elm_Store_Filesystem *st = (Elm_Store_Filesystem *)store;
506 eina_stringshare_del(st->dir);
507 }
508
509 static void
_elm_store_filesystem_item_free(Elm_Store_Item * item)510 _elm_store_filesystem_item_free(Elm_Store_Item *item)
511 {
512 Elm_Store_Item_Filesystem *sti = (Elm_Store_Item_Filesystem *)item;
513 eina_stringshare_del(sti->path);
514 }
515
516 EAPI Elm_Store *
elm_store_filesystem_new(void)517 elm_store_filesystem_new(void)
518 {
519 Elm_Store_Filesystem *st = elm_store_new(Elm_Store_Filesystem);
520 EINA_SAFETY_ON_NULL_RETURN_VAL(st, NULL);
521
522 EINA_MAGIC_SET(st, ELM_STORE_FILESYSTEM_MAGIC);
523 st->base.free = _elm_store_filesystem_free;
524 st->base.item.free = _elm_store_filesystem_item_free;
525
526 return &st->base;
527 }
528
529 EAPI void
elm_store_free(Elm_Store * st)530 elm_store_free(Elm_Store *st)
531 {
532 void (*item_free)(Elm_Store_Item *);
533 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
534 ELM_SAFE_FREE(st->list_th, ecore_thread_cancel);
535 st->realized = eina_list_free(st->realized);
536 item_free = st->item.free;
537 while (st->items)
538 {
539 Elm_Store_Item *sti = (Elm_Store_Item *)st->items;
540 ELM_SAFE_FREE(sti->eval_job, ecore_job_del);
541 ELM_SAFE_FREE(sti->fetch_th, ecore_thread_cancel);
542 if (item_free) item_free(sti);
543 eina_lock_take(&sti->lock);
544 if (sti->data)
545 {
546 if (st->cb.unfetch.func)
547 st->cb.unfetch.func(st->cb.unfetch.data, sti);
548 sti->data = NULL;
549 }
550 eina_lock_release(&sti->lock);
551 eina_lock_free(&sti->lock);
552 st->items = eina_inlist_remove(st->items, EINA_INLIST_GET(sti));
553 free(sti);
554 }
555 if (st->genlist)
556 {
557 evas_object_event_callback_del_full(st->genlist, EVAS_CALLBACK_DEL, _store_genlist_del, st);
558 efl_event_callback_del(st->genlist, ELM_GENLIST_EVENT_REALIZED, _store_genlist_item_realized, st);
559 efl_event_callback_del(st->genlist, ELM_GENLIST_EVENT_UNREALIZED, _store_genlist_item_unrealized, st);
560 elm_genlist_clear(st->genlist);
561 st->genlist = NULL;
562 }
563 if (st->free) st->free(st);
564 free(st);
565 }
566
567 EAPI void
elm_store_target_genlist_set(Elm_Store * st,Evas_Object * obj)568 elm_store_target_genlist_set(Elm_Store *st, Evas_Object *obj)
569 {
570 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
571 if (st->genlist == obj) return;
572 if (st->genlist)
573 {
574 evas_object_event_callback_del_full(st->genlist, EVAS_CALLBACK_DEL, _store_genlist_del, st);
575 efl_event_callback_del(st->genlist, ELM_GENLIST_EVENT_REALIZED, _store_genlist_item_realized, st);
576 efl_event_callback_del(st->genlist, ELM_GENLIST_EVENT_UNREALIZED, _store_genlist_item_unrealized, st);
577 elm_genlist_clear(st->genlist);
578 }
579 st->genlist = obj;
580 if (!st->genlist) return;
581 efl_event_callback_add(st->genlist, ELM_GENLIST_EVENT_REALIZED, _store_genlist_item_realized, st);
582 efl_event_callback_add(st->genlist, ELM_GENLIST_EVENT_UNREALIZED, _store_genlist_item_unrealized, st);
583 evas_object_event_callback_add(st->genlist, EVAS_CALLBACK_DEL, _store_genlist_del, st);
584 elm_genlist_clear(st->genlist);
585 }
586
587 EAPI void
elm_store_filesystem_directory_set(Elm_Store * store,const char * dir)588 elm_store_filesystem_directory_set(Elm_Store *store, const char *dir)
589 {
590 Elm_Store_Filesystem *st = (Elm_Store_Filesystem *)store;
591 if (!EINA_MAGIC_CHECK(store, ELM_STORE_MAGIC)) return;
592 if (!EINA_MAGIC_CHECK(st, ELM_STORE_FILESYSTEM_MAGIC)) return;
593 ELM_SAFE_FREE(store->list_th, ecore_thread_cancel);
594 if (!eina_stringshare_replace(&st->dir, dir)) return;
595 store->list_th = ecore_thread_feedback_run(_store_filesystem_list_do,
596 _store_filesystem_list_update,
597 _store_filesystem_list_end,
598 _store_filesystem_list_cancel,
599 st, EINA_TRUE);
600 }
601
602 EAPI const char *
elm_store_filesystem_directory_get(const Elm_Store * store)603 elm_store_filesystem_directory_get(const Elm_Store *store)
604 {
605 const Elm_Store_Filesystem *st = (const Elm_Store_Filesystem *)store;
606 if (!EINA_MAGIC_CHECK(store, ELM_STORE_MAGIC)) return NULL;
607 if (!EINA_MAGIC_CHECK(st, ELM_STORE_FILESYSTEM_MAGIC)) return NULL;
608 return st->dir;
609 }
610
611 EAPI void
elm_store_cache_set(Elm_Store * st,int max)612 elm_store_cache_set(Elm_Store *st, int max)
613 {
614 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
615 if (max < 0) max = 0;
616 st->cache_max = max;
617 _store_cache_trim(st);
618 }
619
620 EAPI int
elm_store_cache_get(const Elm_Store * st)621 elm_store_cache_get(const Elm_Store *st)
622 {
623 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return 0;
624 return st->cache_max;
625 }
626
627 EAPI void
elm_store_list_func_set(Elm_Store * st,Elm_Store_Item_List_Cb func,const void * data)628 elm_store_list_func_set(Elm_Store *st, Elm_Store_Item_List_Cb func, const void *data)
629 {
630 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
631 st->cb.list.func = func;
632 st->cb.list.data = (void *)data;
633 }
634
635 EAPI void
elm_store_fetch_func_set(Elm_Store * st,Elm_Store_Item_Fetch_Cb func,const void * data)636 elm_store_fetch_func_set(Elm_Store *st, Elm_Store_Item_Fetch_Cb func, const void *data)
637 {
638 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
639 st->cb.fetch.func = func;
640 st->cb.fetch.data = (void *)data;
641 }
642
643 EAPI void
elm_store_fetch_thread_set(Elm_Store * st,Eina_Bool use_thread)644 elm_store_fetch_thread_set(Elm_Store *st, Eina_Bool use_thread)
645 {
646 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
647 st->fetch_thread = !!use_thread;
648 }
649
650 EAPI Eina_Bool
elm_store_fetch_thread_get(const Elm_Store * st)651 elm_store_fetch_thread_get(const Elm_Store *st)
652 {
653 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return EINA_FALSE;
654 return st->fetch_thread;
655 }
656
657 EAPI void
elm_store_unfetch_func_set(Elm_Store * st,Elm_Store_Item_Unfetch_Cb func,const void * data)658 elm_store_unfetch_func_set(Elm_Store *st, Elm_Store_Item_Unfetch_Cb func, const void *data)
659 {
660 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
661 st->cb.unfetch.func = func;
662 st->cb.unfetch.data = (void *)data;
663 }
664
665 EAPI void
elm_store_sorted_set(Elm_Store * st,Eina_Bool sorted)666 elm_store_sorted_set(Elm_Store *st, Eina_Bool sorted)
667 {
668 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
669 st->sorted = sorted;
670 }
671
672 EAPI Eina_Bool
elm_store_sorted_get(const Elm_Store * st)673 elm_store_sorted_get(const Elm_Store *st)
674 {
675 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return EINA_FALSE;
676 return st->sorted;
677 }
678
679 EAPI void
elm_store_item_data_set(Elm_Store_Item * sti,void * data)680 elm_store_item_data_set(Elm_Store_Item *sti, void *data)
681 {
682 if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return;
683 //// let fetch/unfetch do the locking
684 // eina_lock_take(&sti->lock);
685 sti->data = data;
686 // eina_lock_release(&sti->lock);
687 }
688
689 EAPI void *
elm_store_item_data_get(Elm_Store_Item * sti)690 elm_store_item_data_get(Elm_Store_Item *sti)
691 {
692 if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return NULL;
693 void *d;
694 //// let fetch/unfetch do the locking
695 // eina_lock_take(&sti->lock);
696 d = sti->data;
697 // eina_lock_release(&sti->lock);
698 return d;
699 }
700
701 EAPI const Elm_Store *
elm_store_item_store_get(const Elm_Store_Item * sti)702 elm_store_item_store_get(const Elm_Store_Item *sti)
703 {
704 if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return NULL;
705 // dont need lock
706 return sti->store;
707 }
708
709 EAPI const Elm_Object_Item *
elm_store_item_genlist_item_get(const Elm_Store_Item * sti)710 elm_store_item_genlist_item_get(const Elm_Store_Item *sti)
711 {
712 if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return NULL;
713 // dont need lock
714 return sti->item;
715 }
716
717 EAPI const char *
elm_store_item_filesystem_path_get(const Elm_Store_Item * item)718 elm_store_item_filesystem_path_get(const Elm_Store_Item *item)
719 {
720 Elm_Store_Item_Filesystem *sti = (Elm_Store_Item_Filesystem *)item;
721 Elm_Store_Filesystem *st;
722 if (!EINA_MAGIC_CHECK(item, ELM_STORE_ITEM_MAGIC)) return NULL;
723 if (!EINA_MAGIC_CHECK(item->store, ELM_STORE_MAGIC)) return NULL;
724 /* ensure we're dealing with filesystem item */
725 st = (Elm_Store_Filesystem *)item->store;
726 if (!EINA_MAGIC_CHECK(st, ELM_STORE_FILESYSTEM_MAGIC)) return NULL;
727 // dont need lock
728 return sti->path;
729 }
730