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