1 /***************************************************
2 TODO option for maximum items to cache
3 TODO keep common list for recent file instances
4 FIXME
5 */
6
7 #include "e.h"
8 #include "evry_api.h"
9 #include <Efreet_Trash.h>
10
11 /* Increment for Major Changes */
12 #define MOD_CONFIG_FILE_EPOCH 1
13 /* Increment for Minor Changes (ie: user doesn't need a new config) */
14 #define MOD_CONFIG_FILE_GENERATION 0
15 #define MOD_CONFIG_FILE_VERSION ((MOD_CONFIG_FILE_EPOCH * 1000000) + MOD_CONFIG_FILE_GENERATION)
16
17 #define MAX_ITEMS 10
18 #define MAX_SHOWN 300
19 #define TERM_ACTION_DIR "%s"
20
21 #define CMD_NONE 0
22 #define CMD_SHOW_ROOT 1
23 #define CMD_SHOW_HIDDEN 2
24 #define CMD_SHOW_PARENT 3
25
26 #define ACT_TRASH 1
27 #define ACT_DELETE 2
28 #define ACT_COPY 3
29 #define ACT_MOVE 4
30 #define ACT_SORT_DATE 5
31 #define ACT_SORT_NAME 6
32
33 #define ONE_DAY 86400.0
34 #define SIX_DAYS_AGO (ecore_time_unix_get() - ONE_DAY * 6)
35 #define MIN_USAGE 0.0
36
37 /* #undef DBG
38 * #define DBG(...) ERR(__VA_ARGS__) */
39
40 typedef struct _Plugin Plugin;
41 typedef struct _Data Data;
42 typedef struct _Module_Config Module_Config;
43
44 struct _Plugin
45 {
46 Evry_Plugin base;
47
48 Eina_List *files;
49 const char *directory;
50 const char *input;
51 unsigned int command;
52 unsigned int min_query;
53 Eina_Bool parent;
54 Eina_Bool show_hidden;
55 Eina_Bool dirs_only;
56 Eina_Bool show_recent;
57 Eina_Bool sort_by_date;
58
59 Ecore_Thread *thread;
60 Ecore_File_Monitor *dir_mon;
61 int waiting_to_finish;
62 };
63
64 struct _Data
65 {
66 Plugin *plugin;
67 char *directory;
68 long id;
69 int level;
70 int cnt;
71 Eina_List *files;
72 DIR *dirp;
73 int run_cnt;
74 };
75
76 struct _Module_Config
77 {
78 int version;
79
80 unsigned char show_homedir;
81 unsigned char show_recent;
82 unsigned char search_recent;
83 unsigned char cache_dirs;
84 unsigned char search_cache;
85
86 // TODO
87 int sort_by;
88 Eina_List *search_dirs;
89
90 E_Config_Dialog *cfd;
91 E_Module *module;
92 };
93
94 static const Evry_API *evry = NULL;
95 static Evry_Module *evry_module = NULL;
96
97 static Module_Config *_conf;
98 static char _module_icon[] = "system-file-manager";
99 static Eina_List *_plugins = NULL;
100 static Eina_List *_actions = NULL;
101 static const char *_mime_dir;
102 static const char *_mime_mount;
103 static const char *_mime_unknown;
104 static Eina_Bool clear_cache = EINA_FALSE;
105
106 /***************************************************************************/
107
108 static void
_item_fill(Evry_Item_File * file)109 _item_fill(Evry_Item_File *file)
110 {
111 if (!file->mime)
112 {
113 const char *mime = efreet_mime_type_get(file->path);
114
115 if (mime)
116 file->mime = eina_stringshare_add(mime);
117 else
118 file->mime = eina_stringshare_add("unknown");
119 }
120
121 if ((file->mime == _mime_dir) ||
122 (file->mime == _mime_mount))
123 EVRY_ITEM(file)->browseable = EINA_TRUE;
124
125 EVRY_ITEM(file)->context = eina_stringshare_ref(file->mime);
126
127 if (!EVRY_ITEM(file)->detail)
128 evry->util_file_detail_set(file);
129
130 evry->util_file_detail_set(file);
131 }
132
133 static int
_cb_sort(const void * data1,const void * data2)134 _cb_sort(const void *data1, const void *data2)
135 {
136 const Evry_Item *it1 = data1;
137 const Evry_Item *it2 = data2;
138
139 if (it1->browseable && !it2->browseable)
140 return -1;
141
142 if (!it1->browseable && it2->browseable)
143 return 1;
144
145 if (it1->fuzzy_match && it2->fuzzy_match)
146 if (it1->fuzzy_match - it2->fuzzy_match)
147 return it1->fuzzy_match - it2->fuzzy_match;
148
149 return strcasecmp(it1->label, it2->label);
150 }
151
152 static int
_cb_sort_date(const void * data1,const void * data2)153 _cb_sort_date(const void *data1, const void *data2)
154 {
155 const Evry_Item_File *it1 = data1;
156 const Evry_Item_File *it2 = data2;
157
158 return it2->modified - it1->modified;
159 }
160
161 static void
_scan_func(void * data,Ecore_Thread * thread)162 _scan_func(void *data, Ecore_Thread *thread)
163 {
164 Data *d = data;
165 Eina_Iterator *ls;
166 Eina_File_Direct_Info *info;
167 Evry_Item_File *file;
168
169 if (!(ls = eina_file_stat_ls(d->directory)))
170 return;
171
172 EINA_ITERATOR_FOREACH (ls, info)
173 {
174 if ((d->plugin->show_hidden) != (*(info->path + info->name_start) == '.'))
175 continue;
176
177 file = EVRY_ITEM_NEW(Evry_Item_File, d->plugin, NULL, NULL, evry_item_file_free);
178 file->path = strdup(info->path);
179 EVRY_ITEM(file)->label = strdup(info->path + info->name_start);
180 EVRY_ITEM(file)->browseable = (info->type == EINA_FILE_DIR);
181
182 d->files = eina_list_append(d->files, file);
183 /* TODO dont append files in thread, run mime scan
184 * simultaneously. ecore_thread_feedback(thread, file); */
185
186 if (ecore_thread_check(thread))
187 break;
188 }
189
190 eina_iterator_free(ls);
191 }
192
193 static void
_scan_mime_func(void * data,Ecore_Thread * thread)194 _scan_mime_func(void *data, Ecore_Thread *thread)
195 {
196 Data *d = data;
197 Evry_Item_File *file;
198 Eina_List *l;
199 int cnt = 0;
200
201 EINA_LIST_FOREACH (d->files, l, file)
202 {
203 if (ecore_thread_check(thread))
204 break;
205
206 if ((file->mime = efreet_mime_type_get(file->path)))
207 {
208 if (!strncmp(file->mime, "inode/", 6) &&
209 ecore_file_is_dir(file->path))
210 EVRY_ITEM(file)->browseable = EINA_TRUE;
211 }
212 else
213 file->mime = _mime_unknown;
214
215 if (cnt++ > MAX_ITEMS * d->run_cnt) break;
216 }
217 }
218
219 static int
_files_filter(Plugin * p)220 _files_filter(Plugin *p)
221 {
222 int match;
223 int cnt = 0;
224 Evry_Item *it;
225 Eina_List *l;
226 unsigned int len = p->input ? strlen(p->input) : 0;
227
228 EVRY_PLUGIN_ITEMS_CLEAR(p);
229
230 if (!p->command && p->min_query)
231 {
232 if (!p->input)
233 return 0;
234 if (len < p->min_query)
235 return 0;
236 }
237
238 EINA_LIST_FOREACH (p->files, l, it)
239 {
240 if (cnt >= MAX_SHOWN) break;
241
242 if (p->dirs_only && !it->browseable)
243 continue;
244
245 if (len && (match = evry->fuzzy_match(it->label, p->input)))
246 {
247 it->fuzzy_match = match;
248 if (!it->browseable)
249 it->priority = 1;
250 EVRY_PLUGIN_ITEM_APPEND(p, it);
251 cnt++;
252 }
253 else if (len == 0)
254 {
255 if (!it->browseable)
256 it->priority = 1;
257 EVRY_PLUGIN_ITEM_APPEND(p, it);
258 cnt++;
259 }
260 }
261 return cnt;
262 }
263
264 static void
_scan_cancel_func(void * data,Ecore_Thread * thread EINA_UNUSED)265 _scan_cancel_func(void *data, Ecore_Thread *thread EINA_UNUSED)
266 {
267 Data *d = data;
268 Plugin *p = d->plugin;
269 Evry_Item_File *file;
270
271 /* EINA_LIST_FREE(p->files, file)
272 * EVRY_ITEM_FREE(file); */
273
274 EINA_LIST_FREE (d->files, file)
275 {
276 if (file->base.label) free((char *)(file->base.label));
277 if (file->path) free((char *)file->path);
278 E_FREE(file);
279 }
280
281 p->thread = NULL;
282
283 if (p->waiting_to_finish)
284 E_FREE(p);
285
286 free(d->directory);
287 E_FREE(d);
288 }
289
290 static void
_cache_mime_get(History_Types * ht,Evry_Item_File * file)291 _cache_mime_get(History_Types *ht, Evry_Item_File *file)
292 {
293 History_Entry *he;
294 History_Item *hi;
295 Eina_List *l;
296
297 if ((he = eina_hash_find(ht->types, file->path)))
298 {
299 EINA_LIST_FOREACH (he->items, l, hi)
300 {
301 if (!hi->data)
302 continue;
303
304 if (!file->mime)
305 file->mime = hi->data;
306
307 hi->transient = 0;
308 EVRY_ITEM(file)->hi = hi;
309 break;
310 }
311 }
312 }
313
314 static void
_cache_dir_add(Eina_List * files)315 _cache_dir_add(Eina_List *files)
316 {
317 Eina_List *l;
318 Evry_Item *item;
319 History_Item *hi;
320 int cnt = 0;
321
322 EINA_LIST_REVERSE_FOREACH (files, l, item)
323 {
324 GET_FILE(file, item);
325
326 if (!(item->hi) &&
327 (hi = evry->history_item_add(item, NULL, NULL)))
328 {
329 hi->last_used = SIX_DAYS_AGO;
330 hi->usage = MIN_USAGE * (double)cnt++;
331 hi->data = eina_stringshare_ref(file->mime);
332 item->hi = hi;
333 }
334 else if (item->hi && (item->hi->count == 1) &&
335 (item->hi->last_used < SIX_DAYS_AGO))
336 {
337 item->hi->last_used = SIX_DAYS_AGO;
338 item->hi->usage = MIN_USAGE * (double)cnt++;
339 }
340 }
341 }
342
343 static void
_file_add(Plugin * p,Evry_Item * item)344 _file_add(Plugin *p, Evry_Item *item)
345 {
346 GET_FILE(file, item);
347
348 char *filename = (char *)item->label;
349 char *path = (char *)file->path;
350
351 file->path = eina_stringshare_add(path);
352 file->mime = eina_stringshare_add(file->mime);
353
354 item->label = eina_stringshare_add(filename);
355 item->id = eina_stringshare_ref(file->path);
356 item->context = eina_stringshare_ref(file->mime);
357
358 evry->util_file_detail_set(file);
359
360 p->files = eina_list_append(p->files, file);
361
362 E_FREE(filename);
363 E_FREE(path);
364 }
365
366 static void
_scan_end_func(void * data,Ecore_Thread * thread EINA_UNUSED)367 _scan_end_func(void *data, Ecore_Thread *thread EINA_UNUSED)
368 {
369 Data *d = data;
370 Plugin *p = d->plugin;
371 Evry_Item *item;
372 Evry_Item_File *file;
373 Eina_List *l, *ll;
374 History_Types *ht = NULL;
375
376 if (_conf->cache_dirs)
377 ht = evry->history_types_get(EVRY_TYPE_FILE);
378
379 if (!d->run_cnt) /* _scan_func finished */
380 {
381 EINA_LIST_FOREACH_SAFE (d->files, l, ll, item)
382 {
383 GET_FILE(browse, item);
384
385 if (item->browseable)
386 browse->mime = _mime_dir;
387 else if (ht)
388 _cache_mime_get(ht, browse);
389
390 if (browse->mime)
391 {
392 d->files = eina_list_remove_list(d->files, l);
393 _file_add(p, item);
394 }
395 }
396
397 /* sort files by name for mimetypes scan */
398 if (d->files)
399 d->files = eina_list_sort(d->files, -1, _cb_sort);
400 }
401 else /* _scan_mime_func finished */
402 {
403 EINA_LIST_FREE (d->files, file)
404 {
405 if (!file->mime) break;
406 _file_add(p, (Evry_Item *)file);
407 }
408 }
409
410 if (d->files) /* scan mimetypes */
411 {
412 d->run_cnt++;
413 p->thread = ecore_thread_run(_scan_mime_func,
414 _scan_end_func,
415 _scan_cancel_func, d);
416
417 /* wait for first mime scan to finish */
418 if (d->run_cnt == 1) return;
419 }
420 else /* finished all file/mime scan */
421 {
422 free(d->directory);
423 E_FREE(d);
424 p->thread = NULL;
425
426 if (_conf->cache_dirs && !(p->command == CMD_SHOW_HIDDEN))
427 _cache_dir_add(p->files);
428 }
429
430 p->files = eina_list_sort(p->files, -1, _cb_sort);
431
432 _files_filter(p);
433
434 EVRY_PLUGIN_UPDATE(p, EVRY_UPDATE_ADD);
435 }
436
437 static void
_dir_watcher(void * data,Ecore_File_Monitor * em EINA_UNUSED,Ecore_File_Event event,const char * path)438 _dir_watcher(void *data, Ecore_File_Monitor *em EINA_UNUSED, Ecore_File_Event event, const char *path)
439 {
440 Plugin *p = data;
441 Evry_Item_File *file;
442 const char *label;
443 Eina_List *ll, *l;
444
445 switch (event)
446 {
447 case ECORE_FILE_EVENT_DELETED_SELF:
448 EINA_LIST_FREE (p->files, file)
449 evry->item_free(EVRY_ITEM(file));
450 break;
451
452 case ECORE_FILE_EVENT_CREATED_DIRECTORY:
453 case ECORE_FILE_EVENT_CREATED_FILE:
454 label = ecore_file_file_get(path);
455
456 file = EVRY_ITEM_NEW(Evry_Item_File, p, label, NULL, evry_item_file_free);
457 file->path = eina_stringshare_add(path);
458
459 if (event == ECORE_FILE_EVENT_CREATED_DIRECTORY)
460 file->mime = eina_stringshare_ref(_mime_dir);
461
462 _item_fill(file);
463 p->files = eina_list_append(p->files, file);
464 break;
465
466 case ECORE_FILE_EVENT_DELETED_FILE:
467 case ECORE_FILE_EVENT_DELETED_DIRECTORY:
468 label = eina_stringshare_add(path);
469
470 EINA_LIST_FOREACH_SAFE (p->files, l, ll, file)
471 {
472 if (file->path != label) continue;
473
474 p->files = eina_list_remove_list(p->files, l);
475
476 EVRY_ITEM_FREE(file);
477 break;
478 }
479 eina_stringshare_del(label);
480 break;
481
482 default:
483 return;
484 }
485
486 _files_filter(p);
487
488 EVRY_PLUGIN_UPDATE(p, EVRY_UPDATE_ADD);
489 }
490
491 static void
_read_directory(Plugin * p)492 _read_directory(Plugin *p)
493 {
494 Data *d = E_NEW(Data, 1);
495 d->plugin = p;
496 d->directory = strdup(p->directory);
497 d->run_cnt = 0;
498
499 p->thread = ecore_thread_run(_scan_func, _scan_end_func, _scan_cancel_func, d);
500
501 if (p->dir_mon)
502 ecore_file_monitor_del(p->dir_mon);
503
504 p->dir_mon = ecore_file_monitor_add(p->directory, _dir_watcher, p);
505 }
506
507 static Evry_Plugin *
_browse(Evry_Plugin * plugin,const Evry_Item * it)508 _browse(Evry_Plugin *plugin, const Evry_Item *it)
509 {
510 Plugin *p = NULL;
511
512 if (!it || !(CHECK_TYPE(it, EVRY_TYPE_FILE)))
513 return NULL;
514
515 GET_FILE(file, it);
516
517 if (!evry->file_path_get(file) ||
518 !ecore_file_is_dir(file->path))
519 return NULL;
520
521 EVRY_PLUGIN_INSTANCE(p, plugin);
522
523 p->directory = eina_stringshare_add(file->path);
524 p->parent = EINA_TRUE;
525
526 _read_directory(p);
527
528 return EVRY_PLUGIN(p);
529 }
530
531 static Evry_Plugin *
_begin(Evry_Plugin * plugin,const Evry_Item * it)532 _begin(Evry_Plugin *plugin, const Evry_Item *it)
533 {
534 Plugin *p = NULL;
535
536 if (it)
537 {
538 const char *dir = NULL;
539
540 if ((CHECK_TYPE(it, EVRY_TYPE_FILE)) ||
541 (CHECK_SUBTYPE(it, EVRY_TYPE_FILE)))
542 {
543 /* browse */
544 GET_FILE(file, it);
545 if (!evry->file_path_get(file))
546 return NULL;
547
548 if (!ecore_file_is_dir(file->path))
549 {
550 char *tmp = ecore_file_dir_get(file->path);
551 dir = eina_stringshare_add(tmp);
552 E_FREE(tmp);
553 }
554 else
555 {
556 dir = eina_stringshare_add(file->path);
557 }
558 }
559 else
560 {
561 /* provide object */
562 if (!(CHECK_TYPE(it, EVRY_TYPE_ACTION)))
563 return NULL;
564 }
565
566 if (!dir)
567 dir = eina_stringshare_add(e_user_homedir_get());
568
569 EVRY_PLUGIN_INSTANCE(p, plugin);
570 p->directory = dir;
571 p->parent = EINA_FALSE;
572 p->min_query = 0;
573 _read_directory(p);
574
575 return EVRY_PLUGIN(p);
576 }
577 else
578 {
579 /* provide subject */
580 EVRY_PLUGIN_INSTANCE(p, plugin);
581 p->parent = EINA_FALSE;
582 p->directory = eina_stringshare_add(e_user_homedir_get());
583 p->min_query = plugin->config->min_query;
584 _read_directory(p);
585
586 return EVRY_PLUGIN(p);
587 }
588
589 return NULL;
590 }
591
592 static void
_folder_item_add(Plugin * p,const char * path,int prio)593 _folder_item_add(Plugin *p, const char *path, int prio)
594 {
595 Evry_Item_File *file;
596
597 file = EVRY_ITEM_NEW(Evry_Item_File, p, path, NULL, evry_item_file_free);
598 file->path = eina_stringshare_add(path);
599 file->mime = eina_stringshare_ref(_mime_dir);
600 EVRY_ITEM(file)->browseable = EINA_TRUE;
601 EVRY_ITEM(file)->priority = prio;
602 EVRY_ITEM(file)->usage = -1;
603 p->files = eina_list_append(p->files, file);
604 EVRY_PLUGIN_ITEM_APPEND(p, file);
605 }
606
607 static void
_free_files(Plugin * p)608 _free_files(Plugin *p)
609 {
610 Evry_Item_File *file;
611
612 EVRY_PLUGIN_ITEMS_CLEAR(p);
613
614 if (p->thread)
615 ecore_thread_cancel(p->thread);
616 p->thread = NULL;
617
618 EINA_LIST_FREE (p->files, file)
619 EVRY_ITEM_FREE(file);
620
621 if (p->dir_mon)
622 ecore_file_monitor_del(p->dir_mon);
623 p->dir_mon = NULL;
624 }
625
626 static void
_finish(Evry_Plugin * plugin)627 _finish(Evry_Plugin *plugin)
628 {
629 GET_PLUGIN(p, plugin);
630
631 IF_RELEASE(p->input);
632 IF_RELEASE(p->directory);
633
634 if (p->thread)
635 p->waiting_to_finish = 1;
636
637 _free_files(p);
638
639 if (!p->waiting_to_finish)
640 E_FREE(p);
641 }
642
643 static int
_fetch(Evry_Plugin * plugin,const char * input)644 _fetch(Evry_Plugin *plugin, const char *input)
645 {
646 GET_PLUGIN(p, plugin);
647 unsigned int len = (input ? strlen(input) : 0);
648
649 if (!p->command)
650 EVRY_PLUGIN_ITEMS_CLEAR(p);
651
652 IF_RELEASE(p->input);
653
654 if (!p->parent && input && (input[0] == '/'))
655 {
656 if (p->command != CMD_SHOW_ROOT)
657 {
658 _free_files(p);
659
660 eina_stringshare_replace(&p->directory, input);
661
662 _read_directory(p);
663
664 p->command = CMD_SHOW_ROOT;
665
666 return 0;
667 }
668 int lendir = p->directory ? strlen(p->directory) : 0;
669 lendir = (lendir <= 1) ? lendir : lendir + 1;
670
671 p->input = eina_stringshare_add(input + lendir);
672 }
673 else if (p->directory && input && !strncmp(input, "..", 2))
674 {
675 if (p->command != CMD_SHOW_PARENT)
676 {
677 char *dir;
678 char buf[PATH_MAX+1];
679 int prio = 0;
680
681 if (strncmp(p->directory, "/", 1))
682 return 0;
683
684 _free_files(p);
685
686 strncpy(buf, p->directory, sizeof(buf) - 1);
687
688 _folder_item_add(p, p->directory, prio++);
689
690 buf[sizeof(buf) - 1] = 0;
691 while (strlen(buf) > 1)
692 {
693 dir = dirname(buf);
694 _folder_item_add(p, dir, prio++);
695 strncpy(buf, dir, sizeof(buf) - 1);
696 }
697
698 p->command = CMD_SHOW_PARENT;
699 }
700 return 1;
701 }
702 else if (p->directory && input && !strncmp(input, ".", 1))
703 {
704 if (p->command != CMD_SHOW_HIDDEN)
705 {
706 _free_files(p);
707
708 p->show_hidden = EINA_TRUE;
709 _read_directory(p);
710
711 p->command = CMD_SHOW_HIDDEN;
712
713 return 0;
714 }
715 p->input = eina_stringshare_add(input);
716 }
717 else if (p->command)
718 {
719 /* clear command items */
720 _free_files(p);
721
722 if (p->command == CMD_SHOW_ROOT)
723 {
724 IF_RELEASE(p->directory);
725 p->directory = eina_stringshare_add(e_user_homedir_get());
726 }
727
728 p->command = CMD_NONE;
729 p->show_hidden = EINA_FALSE;
730
731 _read_directory(p);
732 }
733
734 if (input && !p->command)
735 p->input = eina_stringshare_add(input);
736
737 if ((p->command) || (!p->min_query) || (len >= p->min_query))
738 _files_filter(p);
739
740 return EVRY_PLUGIN_HAS_ITEMS(p);
741 }
742
743 /***************************************************************************/
744 /* recent files */
745
746 static int
_cb_sort_recent(const void * data1,const void * data2)747 _cb_sort_recent(const void *data1, const void *data2)
748 {
749 const Evry_Item *it1 = data1;
750 const Evry_Item *it2 = data2;
751
752 if (it1->browseable && !it2->browseable)
753 return -1;
754
755 if (!it1->browseable && it2->browseable)
756 return 1;
757
758 if (it1->hi && it2->hi)
759 return it1->hi->last_used > it2->hi->last_used ? -1 : 1;
760
761 if (it1->fuzzy_match && it2->fuzzy_match)
762 if (it1->fuzzy_match - it2->fuzzy_match)
763 return it1->fuzzy_match - it2->fuzzy_match;
764
765 return strcasecmp(it1->label, it2->label);
766 }
767
768 static int
_recentf_files_filter(Plugin * p)769 _recentf_files_filter(Plugin *p)
770 {
771 int match;
772 int cnt = 0;
773 Evry_Item *it;
774 Eina_List *l, *new = NULL;
775
776 EVRY_PLUGIN_ITEMS_CLEAR(p);
777
778 EINA_LIST_FOREACH (p->files, l, it)
779 {
780 if (p->dirs_only && !it->browseable)
781 continue;
782
783 if (!p->input)
784 {
785 if (!it->browseable)
786 it->priority = 1;
787 new = eina_list_append(new, it);
788 continue;
789 }
790
791 if (it->fuzzy_match <= 0)
792 {
793 if ((match = evry->fuzzy_match(it->label, p->input)) ||
794 (match = evry->fuzzy_match(EVRY_FILE(it)->path, p->input)))
795 it->fuzzy_match = match;
796 else
797 it->fuzzy_match = 0;
798
799 DBG("check match %d %s", it->fuzzy_match, it->label);
800 }
801
802 if (it->fuzzy_match)
803 {
804 if (!it->browseable)
805 it->priority = 1;
806 new = eina_list_append(new, it);
807 }
808 }
809
810 new = eina_list_sort(new, -1, _cb_sort_recent);
811
812 EINA_LIST_FREE (new, it)
813 {
814 if (cnt++ < MAX_SHOWN)
815 EVRY_PLUGIN_ITEM_APPEND(p, it);
816 }
817
818 return cnt;
819 }
820
821 #if 0
822 /* use thread only to not block ui for ecore_file_exists ... */
823
824 static void
825 _recentf_func(void *data)
826 {
827 Data *d = data;
828 Eina_List *l;
829 Evry_Item_File *file;
830
831 EINA_LIST_FOREACH (d->files, l, file)
832 {
833 if ((!evry->file_path_get(file)) ||
834 (!ecore_file_exists(file->path)))
835 {
836 EVRY_ITEM(file)->hi->last_used -= ONE_DAY;
837 EVRY_ITEM(file)->hi = NULL;
838 }
839 }
840 }
841
842 static void
843 _recentf_cancel_func(void *data)
844 {
845 Data *d = data;
846 Plugin *p = d->plugin;
847 Evry_Item_File *file;
848
849 EINA_LIST_FREE (d->files, file)
850 EVRY_ITEM_FREE(file);
851
852 E_FREE(d);
853
854 if (p->waiting_to_finish)
855 E_FREE(p);
856 }
857
858 static void
859 _recentf_end_func(void *data)
860 {
861 Data *d = data;
862 Plugin *p = d->plugin;
863 Evry_Item *it;
864
865 EINA_LIST_FREE (d->files, it)
866 {
867 GET_FILE(file, it);
868
869 if (!it->hi)
870 {
871 evry->item_free(it);
872 continue;
873 }
874
875 _item_fill(file);
876
877 if (!it->hi->data)
878 it->hi->data = eina_stringshare_ref(file->mime);
879
880 p->files = eina_list_append(p->files, it);
881 }
882
883 _recentf_files_filter(p);
884
885 EVRY_PLUGIN_UPDATE(p, EVRY_UPDATE_ADD);
886
887 p->thread = NULL;
888 E_FREE(d);
889 }
890
891 #endif
892
893 static Eina_Bool
_recentf_items_add_cb(const Eina_Hash * hash EINA_UNUSED,const void * key,void * data,void * fdata)894 _recentf_items_add_cb(const Eina_Hash *hash EINA_UNUSED, const void *key, void *data, void *fdata)
895 {
896 History_Entry *he = data;
897 History_Item *hi = NULL, *hi2;
898 Eina_List *l, *ll;
899 Evry_Item_File *file;
900 double last_used = 0.0;
901 Data *d = fdata;
902 Plugin *p = d->plugin;
903 const char *label;
904 const char *path;
905 int match = 0;
906
907 EINA_LIST_FOREACH (he->items, l, hi2)
908 if (hi2->last_used > last_used)
909 {
910 last_used = hi2->last_used;
911 hi = hi2;
912 }
913
914 if (!hi)
915 return EINA_TRUE;
916
917 if (clear_cache)
918 {
919 DBG("clear %s", (char *)key);
920
921 /* transient marks them for deletion */
922 if (hi->count == 1)
923 {
924 hi->usage = 0;
925 hi->count = 0;
926 hi->transient = 1;
927 }
928
929 return EINA_TRUE;
930 }
931
932 if (hi->transient)
933 return EINA_TRUE;
934
935 if (!_conf->search_cache)
936 {
937 if ((hi->count == 1) && (hi->last_used < SIX_DAYS_AGO))
938 return EINA_TRUE;
939 }
940
941 path = (const char *)key;
942
943 if (!(label = ecore_file_file_get(path)))
944 return EINA_TRUE;
945
946 path = eina_stringshare_add(path);
947
948 EINA_LIST_FOREACH (p->files, ll, file)
949 {
950 if (file->path == path)
951 {
952 eina_stringshare_del(path);
953 EVRY_ITEM(file)->fuzzy_match = -1;
954 return EINA_TRUE;
955 }
956 }
957
958 /* searching subdirs */
959 if (p->directory)
960 {
961 /* dont show recent files from same dir */
962 int len = strlen(p->directory);
963 char *end = strrchr(path, '/');
964 if (strncmp(path, p->directory, len) ||
965 (end - path) <= len)
966 {
967 /* DBG("not in dir %s", path); */
968 eina_stringshare_del(path);
969 return EINA_TRUE;
970 }
971 }
972
973 if (!(match = evry->fuzzy_match(label, p->input)) &&
974 !(match = evry->fuzzy_match(path, p->input)))
975 {
976 eina_stringshare_del(path);
977 return EINA_TRUE;
978 }
979
980 file = EVRY_ITEM_NEW(Evry_Item_File, p, label, NULL, evry_item_file_free);
981 file->path = path;
982
983 if (hi->data)
984 file->mime = eina_stringshare_add(hi->data);
985
986 EVRY_ITEM(file)->hi = hi;
987 EVRY_ITEM(file)->fuzzy_match = match;
988 EVRY_ITEM(file)->id = eina_stringshare_ref(file->path);
989
990 _item_fill(file);
991
992 if (!hi->data)
993 hi->data = eina_stringshare_ref(file->mime);
994
995 d->files = eina_list_append(d->files, file);
996
997 if (eina_list_count(d->files) > 100)
998 return EINA_FALSE;
999
1000 return EINA_TRUE;
1001 }
1002
1003 static Evry_Plugin *
_recentf_browse(Evry_Plugin * plugin,const Evry_Item * it)1004 _recentf_browse(Evry_Plugin *plugin, const Evry_Item *it)
1005 {
1006 Plugin *p = NULL;
1007
1008 if (!it || !(CHECK_TYPE(it, EVRY_TYPE_FILE)))
1009 return NULL;
1010
1011 GET_FILE(file, it);
1012
1013 if (!evry->file_path_get(file) ||
1014 !ecore_file_is_dir(file->path))
1015 return NULL;
1016
1017 EVRY_PLUGIN_INSTANCE(p, plugin);
1018 p->directory = eina_stringshare_add(file->path);
1019 p->parent = EINA_TRUE;
1020
1021 return EVRY_PLUGIN(p);
1022 }
1023
1024 static Evry_Plugin *
_recentf_begin(Evry_Plugin * plugin,const Evry_Item * it)1025 _recentf_begin(Evry_Plugin *plugin, const Evry_Item *it)
1026 {
1027 Plugin *p;
1028
1029 if (it && !(CHECK_TYPE(it, EVRY_TYPE_ACTION)))
1030 return NULL;
1031
1032 EVRY_PLUGIN_INSTANCE(p, plugin);
1033 p->parent = EINA_FALSE;
1034
1035 if (it)
1036 {
1037 /* provide object */
1038 }
1039 else
1040 {
1041 /* provide subject */
1042 p->min_query = plugin->config->min_query;
1043
1044 if (clear_cache)
1045 {
1046 History_Types *ht = evry->history_types_get(EVRY_TYPE_FILE);
1047 if (ht)
1048 eina_hash_foreach(ht->types, _recentf_items_add_cb, p);
1049
1050 clear_cache = EINA_FALSE;
1051 }
1052 }
1053
1054 return EVRY_PLUGIN(p);
1055 }
1056
1057 static int
_recentf_fetch(Evry_Plugin * plugin,const char * input)1058 _recentf_fetch(Evry_Plugin *plugin, const char *input)
1059 {
1060 GET_PLUGIN(p, plugin);
1061 Evry_Item_File *file;
1062 History_Types *ht;
1063 int len = (input ? strlen(input) : 0);
1064
1065 IF_RELEASE(p->input);
1066
1067 /* if (p->thread)
1068 * ecore_thread_cancel(p->thread);
1069 * p->thread = NULL; */
1070
1071 if (input && isspace(input[len - 1]))
1072 return EVRY_PLUGIN_HAS_ITEMS(p);
1073
1074 if (len >= plugin->config->min_query)
1075 {
1076 if (input)
1077 p->input = eina_stringshare_add(input);
1078
1079 if ((ht = evry->history_types_get(EVRY_TYPE_FILE)))
1080 {
1081 Data *d = E_NEW(Data, 1);
1082 d->plugin = p;
1083 eina_hash_foreach(ht->types, _recentf_items_add_cb, d);
1084 EINA_LIST_FREE (d->files, file)
1085 p->files = eina_list_append(p->files, file);
1086 E_FREE(d);
1087
1088 _recentf_files_filter(p);
1089
1090 /* _recentf_end_func(d);
1091 * p->thread = NULL; */
1092 /* p->thread = ecore_thread_run(_recentf_func, _recentf_end_func,
1093 * _recentf_cancel_func, d); */
1094 }
1095 return EVRY_PLUGIN_HAS_ITEMS(p);
1096 }
1097
1098 EVRY_PLUGIN_ITEMS_CLEAR(p);
1099
1100 return 0;
1101 }
1102
1103 /***************************************************************************/
1104 /* actions */
1105
1106 static int
_open_folder_check(Evry_Action * act EINA_UNUSED,const Evry_Item * it)1107 _open_folder_check(Evry_Action *act EINA_UNUSED, const Evry_Item *it)
1108 {
1109 return it->browseable && e_action_find("fileman");
1110 }
1111
1112 static int
_open_folder_action(Evry_Action * act)1113 _open_folder_action(Evry_Action *act)
1114 {
1115 E_Action *action;
1116 char *dir;
1117
1118 if (!(action = e_action_find("fileman")))
1119 return 0;
1120
1121 GET_FILE(file, act->it1.item);
1122
1123 if (!(evry->file_path_get(file)))
1124 return 0;
1125
1126 if (!IS_BROWSEABLE(file))
1127 {
1128 dir = ecore_file_dir_get(file->path);
1129 if (!dir) return 0;
1130 action->func.go(E_OBJECT(e_comp), dir);
1131 free(dir);
1132 }
1133 else
1134 {
1135 action->func.go(E_OBJECT(e_comp), file->path);
1136 }
1137
1138 return 1;
1139 }
1140
1141 static int
_file_trash_action(Evry_Action * act)1142 _file_trash_action(Evry_Action *act)
1143 {
1144 Efreet_Uri *euri;
1145 int ok = 0;
1146 int force = (EVRY_ITEM_DATA_INT_GET(act) == ACT_DELETE);
1147
1148 GET_FILE(file, act->it1.item);
1149
1150 if (!(evry->file_url_get(file)))
1151 return 0;
1152
1153 euri = efreet_uri_decode(file->url);
1154
1155 if (euri)
1156 {
1157 ok = efreet_trash_delete_uri(euri, force);
1158 efreet_uri_free(euri);
1159 }
1160
1161 return ok > 0;
1162 }
1163
1164 static int
_file_copy_action(Evry_Action * act)1165 _file_copy_action(Evry_Action *act)
1166 {
1167 GET_FILE(src, act->it1.item);
1168 GET_FILE(dst, act->it2.item);
1169
1170 char buf[PATH_MAX];
1171 char *ddst;
1172
1173 if (!(evry->file_path_get(src)))
1174 return 0;
1175
1176 if (!(evry->file_path_get(dst)))
1177 return 0;
1178
1179 if (!ecore_file_is_dir(dst->path))
1180 ddst = ecore_file_dir_get(dst->path);
1181 else
1182 ddst = strdup(dst->path);
1183 if (!ddst)
1184 return 0;
1185
1186 snprintf(buf, sizeof(buf), "%s/%s", ddst, ecore_file_file_get(src->path));
1187 free(ddst);
1188
1189 DBG(" %s -> %s\n", src->path, buf);
1190
1191 if (EVRY_ITEM_DATA_INT_GET(act) == ACT_COPY)
1192 {
1193 return ecore_file_cp(src->path, buf);
1194 }
1195 else if (EVRY_ITEM_DATA_INT_GET(act) == ACT_MOVE)
1196 {
1197 return ecore_file_mv(src->path, buf);
1198 }
1199
1200 return 0;
1201 }
1202
1203 static void
_sort_by_date(Plugin * p)1204 _sort_by_date(Plugin *p)
1205 {
1206 Eina_List *l;
1207 Evry_Item_File *file;
1208 struct stat s;
1209
1210 EINA_LIST_FOREACH (p->files, l, file)
1211 {
1212 if (file->modified)
1213 continue;
1214
1215 if (lstat(file->path, &s) == 0)
1216 file->modified = s.st_mtime;
1217
1218 EVRY_ITEM(file)->usage = -1;
1219 }
1220
1221 p->files = eina_list_sort(p->files, -1, _cb_sort_date);
1222 _files_filter(p);
1223
1224 EVRY_PLUGIN_UPDATE(p, EVRY_UPDATE_ADD);
1225 }
1226
1227 static void
_sort_by_name(Plugin * p)1228 _sort_by_name(Plugin *p)
1229 {
1230 Eina_List *l;
1231 Evry_Item *it;
1232
1233 EINA_LIST_FOREACH (p->files, l, it)
1234 it->usage = 0;
1235
1236 p->files = eina_list_sort(p->files, -1, _cb_sort);
1237 _files_filter(p);
1238
1239 EVRY_PLUGIN_UPDATE(p, EVRY_UPDATE_ADD);
1240 }
1241
1242 static int
_file_sort_action(Evry_Action * act)1243 _file_sort_action(Evry_Action *act)
1244 {
1245 GET_PLUGIN(p, act->it1.item);
1246 if (!p) return 0;
1247
1248 if (EVRY_ITEM_DATA_INT_GET(act) == ACT_SORT_DATE)
1249 {
1250 _sort_by_date(p);
1251 }
1252 else
1253 {
1254 _sort_by_name(p);
1255 }
1256
1257 return 0;
1258 }
1259
1260 static int
_cb_key_down(Evry_Plugin * plugin,const Ecore_Event_Key * ev)1261 _cb_key_down(Evry_Plugin *plugin, const Ecore_Event_Key *ev)
1262 {
1263 GET_PLUGIN(p, plugin);
1264
1265 if (!strcmp(ev->key, "F1"))
1266 {
1267 _sort_by_name(p);
1268 return 1;
1269 }
1270 if (!strcmp(ev->key, "F2"))
1271 {
1272 _sort_by_date(p);
1273 return 1;
1274 }
1275
1276 return 0;
1277 }
1278
1279 static int
_plugins_init(const Evry_API * api)1280 _plugins_init(const Evry_API *api)
1281 {
1282 Evry_Action *act, *act_sort_date, *act_sort_name;
1283 Evry_Plugin *p;
1284 int prio = 0;
1285 const char *config_path;
1286
1287 evry = api;
1288
1289 if (!evry->api_version_check(EVRY_API_VERSION))
1290 return EINA_FALSE;
1291
1292 config_path = eina_stringshare_add("launcher/everything-files");
1293 _mime_dir = eina_stringshare_add("inode/directory");
1294 _mime_mount = eina_stringshare_add("inode/mountpoint");
1295 _mime_unknown = eina_stringshare_add("unknown");
1296
1297 #define ACTION_NEW(_name, _type2, _icon, _act, _check, _register) \
1298 act = EVRY_ACTION_NEW(_name, EVRY_TYPE_FILE, _type2, _icon, _act, _check); \
1299 if (_register) evry->action_register(act, prio++); \
1300 _actions = eina_list_append(_actions, act); \
1301
1302 ACTION_NEW(N_("Copy To ..."), EVRY_TYPE_FILE, "go-next",
1303 _file_copy_action, NULL, 1);
1304 act->it2.subtype = EVRY_TYPE_DIR;
1305 EVRY_ITEM_DATA_INT_SET(act, ACT_COPY);
1306
1307 ACTION_NEW(N_("Move To ..."), EVRY_TYPE_FILE, "go-next",
1308 _file_copy_action, NULL, 1);
1309 act->it2.subtype = EVRY_TYPE_DIR;
1310 EVRY_ITEM_DATA_INT_SET(act, ACT_MOVE);
1311
1312 ACTION_NEW(N_("Move to Trash"), 0, "user-trash",
1313 _file_trash_action, NULL, 1);
1314 EVRY_ITEM_DATA_INT_SET(act, ACT_TRASH);
1315
1316 ACTION_NEW(N_("Open Directory"), 0, "folder-open",
1317 _open_folder_action, _open_folder_check, 1);
1318 act->remember_context = EINA_TRUE;
1319
1320 ACTION_NEW(N_("Sort by Date"), 0, "go-up",
1321 _file_sort_action, NULL, 0);
1322 EVRY_ITEM_DATA_INT_SET(act, ACT_SORT_DATE);
1323 act_sort_date = act;
1324
1325 ACTION_NEW(N_("Sort by Name"), 0, "go-up",
1326 _file_sort_action, NULL, 0);
1327 EVRY_ITEM_DATA_INT_SET(act, ACT_SORT_NAME);
1328 act_sort_name = act;
1329
1330 #undef ACTION_NEW
1331
1332 p = EVRY_PLUGIN_BASE(N_("Files"), _module_icon, EVRY_TYPE_FILE,
1333 _begin, _finish, _fetch);
1334 p->input_type = EVRY_TYPE_FILE;
1335 p->cb_key_down = &_cb_key_down;
1336 p->browse = &_browse;
1337 p->config_path = eina_stringshare_ref(config_path);
1338 p->actions = eina_list_append(p->actions, act_sort_date);
1339 p->actions = eina_list_append(p->actions, act_sort_name);
1340 _plugins = eina_list_append(_plugins, p);
1341
1342 if (evry->plugin_register(p, EVRY_PLUGIN_SUBJECT, 2))
1343 p->config->min_query = 1;
1344
1345 p = EVRY_PLUGIN_BASE(N_("Files"), _module_icon, EVRY_TYPE_FILE,
1346 _begin, _finish, _fetch);
1347 p->cb_key_down = &_cb_key_down;
1348 p->browse = &_browse;
1349 p->config_path = eina_stringshare_ref(config_path);
1350 p->actions = eina_list_append(p->actions, act_sort_date);
1351 p->actions = eina_list_append(p->actions, act_sort_name);
1352 _plugins = eina_list_append(_plugins, p);
1353 evry->plugin_register(p, EVRY_PLUGIN_OBJECT, 2);
1354
1355 if (!_conf->show_recent && !_conf->search_recent)
1356 return EINA_TRUE;
1357
1358 p = EVRY_PLUGIN_BASE(N_("Recent Files"), _module_icon, EVRY_TYPE_FILE,
1359 _recentf_begin, _finish, _recentf_fetch);
1360 p->browse = &_recentf_browse;
1361 p->config_path = eina_stringshare_ref(config_path);
1362
1363 if (evry->plugin_register(p, EVRY_PLUGIN_SUBJECT, 3))
1364 {
1365 p->config->top_level = EINA_FALSE;
1366 p->config->min_query = 3;
1367 }
1368 _plugins = eina_list_append(_plugins, p);
1369
1370 p = EVRY_PLUGIN_BASE(N_("Recent Files"), _module_icon, EVRY_TYPE_FILE,
1371 _recentf_begin, _finish, _recentf_fetch);
1372 p->browse = &_recentf_browse;
1373 p->config_path = eina_stringshare_ref(config_path);
1374
1375 if (evry->plugin_register(p, EVRY_PLUGIN_OBJECT, 3))
1376 {
1377 p->config->top_level = EINA_FALSE;
1378 p->config->min_query = 3;
1379 }
1380 _plugins = eina_list_append(_plugins, p);
1381 eina_stringshare_del(config_path);
1382
1383 return EINA_TRUE;
1384 }
1385
1386 static void
_plugins_shutdown(void)1387 _plugins_shutdown(void)
1388 {
1389 Evry_Action *act;
1390 Evry_Plugin *p;
1391
1392 eina_stringshare_del(_mime_dir);
1393 eina_stringshare_del(_mime_mount);
1394 eina_stringshare_del(_mime_unknown);
1395
1396 EINA_LIST_FREE (_plugins, p)
1397 {
1398 if (p->actions)
1399 eina_list_free(p->actions);
1400 EVRY_PLUGIN_FREE(p);
1401 }
1402
1403 EINA_LIST_FREE (_actions, act)
1404 evry->action_free(act);
1405 }
1406
1407 /***************************************************************************/
1408
1409 static E_Config_DD *conf_edd = NULL;
1410
1411 struct _E_Config_Dialog_Data
1412 {
1413 int show_homedir;
1414 int show_recent;
1415 int search_recent;
1416 int search_cache;
1417 int cache_dirs;
1418 };
1419
1420 static void *_create_data(E_Config_Dialog *cfd);
1421 static void _free_data(E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata);
1422 static void _fill_data(E_Config_Dialog_Data *cfdata);
1423 static Evas_Object *_basic_create(E_Config_Dialog *cfd, Evas *evas, E_Config_Dialog_Data *cfdata);
1424 static int _basic_apply(E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata);
1425
1426 static E_Config_Dialog *
_conf_dialog(Evas_Object * parent EINA_UNUSED,const char * params EINA_UNUSED)1427 _conf_dialog(Evas_Object *parent EINA_UNUSED, const char *params EINA_UNUSED)
1428 {
1429 E_Config_Dialog *cfd = NULL;
1430 E_Config_Dialog_View *v = NULL;
1431
1432 if (e_config_dialog_find("everything-files", "extensions/everything-files")) return NULL;
1433
1434 v = E_NEW(E_Config_Dialog_View, 1);
1435 if (!v) return NULL;
1436
1437 v->create_cfdata = _create_data;
1438 v->free_cfdata = _free_data;
1439 v->basic.create_widgets = _basic_create;
1440 v->basic.apply_cfdata = _basic_apply;
1441
1442 cfd = e_config_dialog_new(NULL, _("Everything Files"), "everything-files",
1443 "extensions/everything-files", _module_icon, 0, v, NULL);
1444
1445 _conf->cfd = cfd;
1446 return cfd;
1447 }
1448
1449 static void
_clear_cache_cb(void * data EINA_UNUSED,void * data2 EINA_UNUSED)1450 _clear_cache_cb(void *data EINA_UNUSED, void *data2 EINA_UNUSED)
1451 {
1452 clear_cache = EINA_TRUE;
1453 }
1454
1455 static Evas_Object *
_basic_create(E_Config_Dialog * cfd EINA_UNUSED,Evas * evas,E_Config_Dialog_Data * cfdata)1456 _basic_create(E_Config_Dialog *cfd EINA_UNUSED, Evas *evas, E_Config_Dialog_Data *cfdata)
1457 {
1458 Evas_Object *o = NULL, *of = NULL, *ow = NULL;
1459
1460 o = e_widget_list_add(evas, 0, 0);
1461
1462 of = e_widget_framelist_add(evas, _("General"), 0);
1463 e_widget_framelist_content_align_set(of, 0.0, 0.0);
1464
1465 /* ow = e_widget_check_add(evas, _("Show home directory"),
1466 * &(cfdata->show_homedir));
1467 * e_widget_framelist_object_append(of, ow); */
1468
1469 ow = e_widget_check_add(evas, _("Show recent files"),
1470 &(cfdata->show_recent));
1471 e_widget_framelist_object_append(of, ow);
1472
1473 ow = e_widget_check_add(evas, _("Search recent files"),
1474 &(cfdata->search_recent));
1475 e_widget_framelist_object_append(of, ow);
1476
1477 ow = e_widget_check_add(evas, _("Search cached files"),
1478 &(cfdata->search_cache));
1479 e_widget_framelist_object_append(of, ow);
1480
1481 ow = e_widget_check_add(evas, _("Cache visited directories"),
1482 &(cfdata->cache_dirs));
1483 e_widget_framelist_object_append(of, ow);
1484
1485 ow = e_widget_button_add(evas, _("Clear cache"), NULL,
1486 _clear_cache_cb,
1487 NULL, NULL);
1488 e_widget_framelist_object_append(of, ow);
1489
1490 e_widget_list_object_append(o, of, 1, 1, 0.5);
1491 return o;
1492 }
1493
1494 static void *
_create_data(E_Config_Dialog * cfd EINA_UNUSED)1495 _create_data(E_Config_Dialog *cfd EINA_UNUSED)
1496 {
1497 E_Config_Dialog_Data *cfdata = NULL;
1498
1499 cfdata = E_NEW(E_Config_Dialog_Data, 1);
1500 _fill_data(cfdata);
1501 return cfdata;
1502 }
1503
1504 static void
_free_data(E_Config_Dialog * cfd EINA_UNUSED,E_Config_Dialog_Data * cfdata)1505 _free_data(E_Config_Dialog *cfd EINA_UNUSED, E_Config_Dialog_Data *cfdata)
1506 {
1507 _conf->cfd = NULL;
1508 E_FREE(cfdata);
1509 }
1510
1511 static void
_fill_data(E_Config_Dialog_Data * cfdata)1512 _fill_data(E_Config_Dialog_Data *cfdata)
1513 {
1514 #define C(_name) cfdata->_name = _conf->_name;
1515 C(show_homedir);
1516 C(show_recent);
1517 C(search_recent);
1518 C(search_cache);
1519 C(cache_dirs);
1520 #undef C
1521 }
1522
1523 static int
_basic_apply(E_Config_Dialog * cfd EINA_UNUSED,E_Config_Dialog_Data * cfdata)1524 _basic_apply(E_Config_Dialog *cfd EINA_UNUSED, E_Config_Dialog_Data *cfdata)
1525 {
1526 #define C(_name) _conf->_name = cfdata->_name;
1527 C(show_homedir);
1528 C(show_recent);
1529 C(search_recent);
1530 C(search_cache);
1531 C(cache_dirs);
1532 #undef C
1533
1534 e_config_domain_save("module.everything-files", conf_edd, _conf);
1535 e_config_save_queue();
1536 return 1;
1537 }
1538
1539 static void
_conf_new(void)1540 _conf_new(void)
1541 {
1542 _conf = E_NEW(Module_Config, 1);
1543 _conf->show_recent = 0;
1544 _conf->show_homedir = 1;
1545 _conf->search_recent = 1;
1546 _conf->cache_dirs = 0;
1547 _conf->search_cache = 0;
1548
1549 _conf->version = MOD_CONFIG_FILE_VERSION;
1550 }
1551
1552 static void
_conf_free(void)1553 _conf_free(void)
1554 {
1555 E_FREE(_conf);
1556 }
1557
1558 static void
_conf_init(E_Module * m)1559 _conf_init(E_Module *m)
1560 {
1561 char title[4096];
1562
1563 snprintf(title, sizeof(title), "%s: %s", _("Everything Plugin"), _("Files"));
1564
1565 e_configure_registry_item_add("launcher/everything-files", 110, title,
1566 NULL, _module_icon, _conf_dialog);
1567
1568 conf_edd = E_CONFIG_DD_NEW("Module_Config", Module_Config);
1569
1570 #undef T
1571 #undef D
1572 #define T Module_Config
1573 #define D conf_edd
1574 E_CONFIG_VAL(D, T, version, INT);
1575 E_CONFIG_VAL(D, T, show_homedir, UCHAR);
1576 E_CONFIG_VAL(D, T, show_recent, UCHAR);
1577 E_CONFIG_VAL(D, T, search_recent, UCHAR);
1578 E_CONFIG_VAL(D, T, search_cache, UCHAR);
1579 E_CONFIG_VAL(D, T, cache_dirs, UCHAR);
1580 #undef T
1581 #undef D
1582
1583 _conf = e_config_domain_load("module.everything-files", conf_edd);
1584
1585 if (_conf && !e_util_module_config_check(_("Everything Files"),
1586 _conf->version,
1587 MOD_CONFIG_FILE_VERSION))
1588 _conf_free();
1589
1590 if (!_conf) _conf_new();
1591
1592 _conf->module = m;
1593 }
1594
1595 static void
_conf_shutdown(void)1596 _conf_shutdown(void)
1597 {
1598 e_configure_registry_item_del("launcher/everything-files");
1599
1600 E_FREE(_conf);
1601 E_CONFIG_DD_FREE(conf_edd);
1602 }
1603
1604 /***************************************************************************/
1605
1606 Eina_Bool
evry_plug_files_init(E_Module * m)1607 evry_plug_files_init(E_Module *m)
1608 {
1609 _conf_init(m);
1610
1611 EVRY_MODULE_NEW(evry_module, evry, _plugins_init, _plugins_shutdown);
1612
1613 return EINA_TRUE;
1614 }
1615
1616 void
evry_plug_files_shutdown(void)1617 evry_plug_files_shutdown(void)
1618 {
1619 EVRY_MODULE_FREE(evry_module);
1620
1621 _conf_shutdown();
1622 }
1623
1624 void
evry_plug_files_save(void)1625 evry_plug_files_save(void)
1626 {
1627 e_config_domain_save("module.everything-files", conf_edd, _conf);
1628 }
1629
1630