Tizen 2.1 release
[platform/core/uifw/e17.git] / src / modules / fileman / e_int_config_mime.c
1 #include "e.h"
2 #include "e_int_config_mime_edit.h"
3
4 typedef struct _Config_Glob Config_Glob;
5 typedef struct _Config_Mime Config_Mime;
6 typedef struct _Config_Type Config_Type;
7 struct _Config_Glob 
8 {
9    const char *name;
10 };
11 struct _Config_Mime 
12 {
13    const char *mime;
14    Eina_List *globs;
15 };
16 struct _Config_Type 
17 {
18    const char *name;
19    const char *type;
20 };
21 struct _E_Config_Dialog_Data 
22 {
23    Eina_List *mimes;
24    const char *cur_type;
25    struct
26      {
27         Evas_Object *tlist, *list;
28      } gui;
29    E_Config_Dialog *cfd, *edit_dlg;
30 };
31
32 static void        *_create_data     (E_Config_Dialog *cfd);
33 static void         _free_data       (E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata);
34 static Evas_Object *_basic_create    (E_Config_Dialog *cfd, Evas *evas, E_Config_Dialog_Data *cfdata);
35 static void         _fill_list       (E_Config_Dialog_Data *cfdata, const char *mtype);
36 static void         _fill_tlist      (E_Config_Dialog_Data *cfdata);
37 static void         _load_mimes      (E_Config_Dialog_Data *cfdata, char *file);
38 static void         _load_globs      (E_Config_Dialog_Data *cfdata, char *file);
39 static void         _fill_types      (E_Config_Dialog_Data *cfdata);
40 static void         _tlist_cb_change (void *data);
41 static int          _sort_mimes      (const void *data1, const void *data2);
42 static Config_Mime *_find_mime       (E_Config_Dialog_Data *cfdata, char *mime);
43 static Config_Glob *_find_glob       (Config_Mime *mime, char *glob);
44 static void         _cb_config       (void *data, void *data2);
45
46 Eina_List *types = NULL;
47
48 E_Config_Dialog *
49 e_int_config_mime(E_Container *con, const char *params __UNUSED__) 
50 {
51    E_Config_Dialog *cfd;
52    E_Config_Dialog_View *v;
53    
54    if (e_config_dialog_find("E", "fileman/file_icons")) return NULL;
55    
56    v = E_NEW(E_Config_Dialog_View, 1);
57    v->create_cfdata = _create_data;
58    v->free_cfdata = _free_data;
59    v->basic.create_widgets = _basic_create;
60    
61    cfd = e_config_dialog_new(con, _("File Icons"), "E", "fileman/file_icons",
62                              "preferences-file-icons", 0, v, NULL);
63    return cfd;
64 }
65
66 void
67 e_int_config_mime_edit_done(void *data) 
68 {
69    E_Config_Dialog_Data *cfdata;
70    
71    cfdata = data;
72    if (!cfdata) return;
73    if (cfdata->edit_dlg)
74      cfdata->edit_dlg = NULL;
75    _tlist_cb_change(cfdata);
76 }
77
78 static void
79 _fill_data(E_Config_Dialog_Data *cfdata) 
80 {
81    const char *s, *homedir;
82    Eina_List *l;
83    char buf[4096];
84
85    if (!cfdata) return;
86    homedir = e_user_homedir_get();
87
88    snprintf(buf, sizeof(buf), "/usr/local/etc/mime.types");
89    if (ecore_file_exists(buf)) _load_mimes(cfdata, buf);
90    snprintf(buf, sizeof(buf), "/etc/mime.types");
91    if (ecore_file_exists(buf)) _load_mimes(cfdata, buf);
92
93    EINA_LIST_FOREACH(efreet_config_dirs_get(), l, s)
94      {
95         snprintf(buf, sizeof(buf), "%s/mime/globs", s);
96         if (ecore_file_exists(buf)) _load_globs(cfdata, buf);
97      }
98    
99    snprintf(buf, sizeof(buf), "%s/.mime.types", homedir);
100    if (ecore_file_exists(buf)) _load_mimes(cfdata, buf);
101    
102    snprintf(buf, sizeof(buf), "%s/mime/globs", efreet_data_home_get());
103    if (ecore_file_exists(buf)) _load_globs(cfdata, buf);
104    
105    cfdata->mimes = eina_list_sort(cfdata->mimes, 0, _sort_mimes);
106    _fill_types(cfdata);
107 }
108
109 static void *
110 _create_data(E_Config_Dialog *cfd) 
111 {
112    E_Config_Dialog_Data *cfdata;
113    
114    cfdata = E_NEW(E_Config_Dialog_Data, 1);
115    cfdata->cfd = cfd;
116    _fill_data(cfdata);
117    return cfdata;
118 }
119
120 static void
121 _free_data(E_Config_Dialog *cfd __UNUSED__, E_Config_Dialog_Data *cfdata) 
122 {
123    Config_Type *t;
124    Config_Mime *m;
125
126    if (cfdata->edit_dlg) 
127      {
128         e_object_del(E_OBJECT(cfdata->edit_dlg));
129         cfdata->edit_dlg = NULL;
130      }
131
132    EINA_LIST_FREE(types, t)
133      {
134         if (!t) continue;
135
136         eina_stringshare_del(t->name);
137         eina_stringshare_del(t->type);
138         E_FREE(t);
139      }
140
141    EINA_LIST_FREE(cfdata->mimes, m)
142      {
143         Config_Glob *g;
144
145         if (!m) continue;
146
147         EINA_LIST_FREE(m->globs, g)
148           {
149              if (!g) continue;
150
151              eina_stringshare_del(g->name);
152              E_FREE(g);
153           }
154
155         eina_stringshare_del(m->mime);
156         E_FREE(m);
157      }
158
159    E_FREE(cfdata);
160 }
161
162 static Evas_Object *
163 _basic_create(E_Config_Dialog *cfd, Evas *evas, E_Config_Dialog_Data *cfdata) 
164 {
165    Evas_Object *o, *of, *ol;
166    Evas_Object *ob;
167    
168    o = e_widget_list_add(evas, 0, 1);
169    of  = e_widget_framelist_add(evas, _("Categories"), 0);
170    ol = e_widget_ilist_add(evas, 16, 16, &(cfdata->cur_type));
171    cfdata->gui.tlist = ol;
172    _fill_tlist(cfdata);
173    e_widget_framelist_object_append(of, ol);
174    e_widget_list_object_append(o, of, 1, 1, 0.5);
175
176    of = e_widget_frametable_add(evas, _("File Types"), 0);
177    ol = e_widget_ilist_add(evas, 16, 16, NULL);
178    cfdata->gui.list = ol;
179    e_widget_ilist_go(ol);
180    e_widget_size_min_set(cfdata->gui.list, 250, 200);
181    e_widget_frametable_object_append(of, ol, 0, 0, 3, 1, 1, 1, 1, 1);
182
183    ob = e_widget_button_add(evas, _("Set"), "configure", _cb_config, cfdata, NULL);
184    e_widget_frametable_object_append(of, ob, 1, 1, 1, 1, 1, 1, 1, 0);
185    e_widget_list_object_append(o, of, 1, 1, 0.5);
186
187    e_dialog_resizable_set(cfd->dia, 1);
188    return o;
189 }
190
191 static void 
192 _fill_list(E_Config_Dialog_Data *cfdata, const char *mtype) 
193 {
194    Config_Mime *m;
195    Eina_List *l;
196    Evas_Coord w, h;
197    Evas *evas;
198
199    evas = evas_object_evas_get(cfdata->gui.list);
200    evas_event_freeze(evas);
201    edje_freeze();
202    e_widget_ilist_freeze(cfdata->gui.list);
203
204    e_widget_ilist_clear(cfdata->gui.list);
205    EINA_LIST_FOREACH(cfdata->mimes, l, m)
206      {
207         Evas_Object *icon = NULL;
208         const char *tmp;
209         char buf[4096];
210         int edj = 0, img = 0;
211
212         if (!m) return;
213         if (!strstr(m->mime, mtype)) continue;
214         tmp = e_fm_mime_icon_get(m->mime);
215         if (!tmp) 
216           snprintf(buf, sizeof(buf), "e/icons/fileman/file");
217         else if (!strcmp(tmp, "THUMB"))
218           snprintf(buf, sizeof(buf), "e/icons/fileman/mime/%s", m->mime);
219         else if (!strncmp(tmp, "e/icons/fileman/mime/", 21))
220           snprintf(buf, sizeof(buf), "e/icons/fileman/mime/%s", m->mime);
221         else 
222           {
223              char *p;
224              
225              p = strrchr(tmp, '.');
226              if ((p) && (!strcmp(p, ".edj")))
227                edj = 1;
228              else if (p)
229                img = 1;
230           }
231         if (edj) 
232           {
233              icon = edje_object_add(evas);
234              if (!e_theme_edje_object_set(icon, tmp, "icon"))
235                e_theme_edje_object_set(icon, "base/theme/fileman", "e/icons/fileman/file");
236           }
237         else if (img) 
238           icon = e_widget_image_add_from_file(evas, tmp, 16, 16);
239         else 
240           {
241              icon = edje_object_add(evas);
242              if (!e_theme_edje_object_set(icon, "base/theme/fileman", buf))
243                e_theme_edje_object_set(icon, "base/theme/fileman", "e/icons/fileman/file");
244           }
245         e_widget_ilist_append(cfdata->gui.list, icon, m->mime, NULL, NULL, NULL);
246      }
247    e_widget_ilist_go(cfdata->gui.list);
248    e_widget_size_min_get(cfdata->gui.list, &w, &h);
249    e_widget_size_min_set(cfdata->gui.list, w, 200);
250    e_widget_ilist_thaw(cfdata->gui.list);
251    edje_thaw();
252    evas_event_thaw(evas);
253 }
254
255 static void 
256 _fill_tlist(E_Config_Dialog_Data *cfdata) 
257 {
258    Config_Type *tmp;
259    Eina_List *l;
260    Evas_Coord w, h;
261
262    evas_event_freeze(evas_object_evas_get(cfdata->gui.tlist));
263    edje_freeze();
264    e_widget_ilist_freeze(cfdata->gui.tlist);
265    e_widget_ilist_clear(cfdata->gui.tlist);
266    EINA_LIST_FOREACH(types, l, tmp)
267      {
268         Evas_Object *icon;
269         char buf[4096];
270         char *t;
271
272         if (!tmp) continue;
273         t = strdup(tmp->name);
274         t[0] = tolower(t[0]);
275         icon = edje_object_add(evas_object_evas_get(cfdata->gui.tlist));
276         snprintf(buf, sizeof(buf), "e/icons/fileman/mime/%s", t);
277         if (!e_theme_edje_object_set(icon, "base/theme/fileman", buf))
278           e_theme_edje_object_set(icon, "base/theme/fileman", "e/icons/fileman/file");
279         e_widget_ilist_append(cfdata->gui.tlist, icon, tmp->name, _tlist_cb_change, cfdata, tmp->type);
280      }
281    
282    e_widget_ilist_go(cfdata->gui.tlist);
283    e_widget_size_min_get(cfdata->gui.tlist, &w, &h);
284    e_widget_size_min_set(cfdata->gui.tlist, w, 225);
285    e_widget_ilist_thaw(cfdata->gui.tlist);
286    edje_thaw();
287    evas_event_thaw(evas_object_evas_get(cfdata->gui.tlist));
288 }
289
290 static void 
291 _load_mimes(E_Config_Dialog_Data *cfdata, char *file) 
292 {
293    FILE *f;
294    char buf[4096], mimetype[4096], ext[4096];
295    char *p, *pp;
296    Config_Mime *config_mime;
297    Config_Glob *config_glob;
298
299    if (!cfdata) return;
300    
301    f = fopen(file, "rb");
302    if (!f) return;
303    while (fgets(buf, sizeof(buf), f))
304      {
305         p = buf;
306         while (isblank(*p) && (*p != 0) && (*p != '\n')) p++;
307         if (*p == '#') continue;
308         if ((*p == '\n') || (*p == 0)) continue;
309         pp = p;
310         while (!isblank(*p) && (*p != 0) && (*p != '\n')) p++;
311         if ((*p == '\n') || (*p == 0)) continue;
312         strncpy(mimetype, pp, (p - pp));
313         mimetype[p - pp] = 0;
314         do 
315           {
316              while (isblank(*p) && (*p != 0) && (*p != '\n')) p++;
317              if ((*p == '\n') || (*p == 0)) continue;
318              pp = p;
319              while (!isblank(*p) && (*p != 0) && (*p != '\n')) p++;
320              strncpy(ext, pp, (p - pp));
321              ext[p - pp] = 0;
322              config_mime = _find_mime(cfdata, mimetype);
323              if (!config_mime) 
324                {
325                   config_mime = E_NEW(Config_Mime, 1);
326                   if (config_mime)
327                     {
328                        config_mime->mime = eina_stringshare_add(mimetype);
329                        if (!config_mime->mime) 
330                          free(config_mime);
331                        else 
332                          {
333                             config_glob = E_NEW(Config_Glob, 1);
334                             config_glob->name = eina_stringshare_add(ext);
335                             config_mime->globs = eina_list_append(config_mime->globs, config_glob);
336                             cfdata->mimes = eina_list_append(cfdata->mimes, config_mime);
337                          }
338                     }
339                }
340           }
341         while ((*p != '\n') && (*p != 0));
342      }
343    fclose(f);
344 }
345
346 static void 
347 _load_globs(E_Config_Dialog_Data *cfdata, char *file) 
348 {
349    FILE *f;
350    char buf[4096], mimetype[4096], ext[4096];
351    char *p, *pp;
352    Config_Mime *config_mime;
353    Config_Glob *config_glob;
354
355    if (!cfdata) return;
356    
357    f = fopen(file, "rb");
358    if (!f) return;
359    while (fgets(buf, sizeof(buf), f))
360      {
361         p = buf;
362         while (isblank(*p) && (*p != 0) && (*p != '\n')) p++;
363         if (*p == '#') continue;
364         if ((*p == '\n') || (*p == 0)) continue;
365         pp = p;
366         while ((*p != ':') && (*p != 0) && (*p != '\n')) p++;
367         if ((*p == '\n') || (*p == 0)) continue;
368         strncpy(mimetype, pp, (p - pp));
369         mimetype[p - pp] = 0;
370         p++;
371         pp = ext;
372         while ((*p != 0) && (*p != '\n')) 
373           {
374              *pp = *p;
375              pp++;
376              p++;
377           }
378         *pp = 0;
379         config_mime = _find_mime(cfdata, mimetype);
380         if (!config_mime) 
381           {
382              config_mime = E_NEW(Config_Mime, 1);
383              if (config_mime)
384                {
385                   config_mime->mime = eina_stringshare_add(mimetype);
386                   if (!config_mime->mime) 
387                     free(config_mime);
388                   else 
389                     {
390                        config_glob = E_NEW(Config_Glob, 1);
391                        config_glob->name = eina_stringshare_add(ext);
392                        config_mime->globs = eina_list_append(config_mime->globs, config_glob);
393                        cfdata->mimes = eina_list_append(cfdata->mimes, config_mime);
394                     }
395                }
396           }
397         else 
398           {
399              config_glob = _find_glob(config_mime, ext);
400              if (!config_glob) 
401                {
402                   config_glob = E_NEW(Config_Glob, 1);
403                   config_glob->name = eina_stringshare_add(ext);
404                   config_mime->globs = eina_list_append(config_mime->globs, config_glob);
405                }
406           }
407      }
408    fclose(f);
409 }
410
411 static void
412 _fill_types(E_Config_Dialog_Data *cfdata) 
413 {
414    Config_Mime *m;
415    Eina_List *l;
416
417    EINA_LIST_FOREACH(cfdata->mimes, l, m)
418      {
419         Config_Type *tmp;
420         Eina_List *ll;
421         char *tok;
422         int found = 0;
423
424         if (!m) continue;
425         tok = strtok(strdup(m->mime), "/");
426         if (!tok) continue;
427
428         EINA_LIST_FOREACH(types, ll, tmp)
429           {
430              if (!tmp) continue;
431
432              if (strcmp(tmp->type, tok) >= 0)
433                {
434                   found = 1;
435                   break;
436                }
437           }
438
439         if (!found)
440           {
441              tmp = E_NEW(Config_Type, 1);
442              tmp->type = eina_stringshare_add(tok);
443              tok[0] = toupper(tok[0]);
444              tmp->name = eina_stringshare_add(tok);
445
446              types = eina_list_append(types, tmp);
447           }
448      }
449 }
450
451 static void 
452 _tlist_cb_change(void *data) 
453 {
454    E_Config_Dialog_Data *cfdata;
455    Config_Type *t;
456    Eina_List *l;
457
458    cfdata = data;
459    if (!cfdata) return;
460
461    EINA_LIST_FOREACH(types, l, t)
462      {
463         if (!t) continue;
464         if (t->name != cfdata->cur_type /* Both string are stringshare. */
465             && strcasecmp(t->name, cfdata->cur_type)) continue;
466         _fill_list(cfdata, t->type);
467         break;
468      }
469 }
470
471 static int 
472 _sort_mimes(const void *data1, const void *data2) 
473 {
474    const Config_Mime *m1, *m2;
475    
476    if (!data1) return 1;
477    if (!data2) return -1;
478    
479    m1 = data1;
480    m2 = data2;
481    
482    return (strcmp(m1->mime, m2->mime));
483 }
484
485 static Config_Mime *
486 _find_mime(E_Config_Dialog_Data *cfdata, char *mime) 
487 {
488    Config_Mime *cm;
489    Eina_List *l;
490                     
491    if (!cfdata) return NULL;
492    EINA_LIST_FOREACH(cfdata->mimes, l, cm)
493      {
494         if (!cm) continue;
495         if (!strcmp(cm->mime, mime)) return cm;
496      }
497    return NULL;
498 }
499
500 static Config_Glob *
501 _find_glob(Config_Mime *mime, char *globing) 
502 {
503    Config_Glob *g;
504    Eina_List *l;
505
506    if (!mime) return NULL;
507    EINA_LIST_FOREACH(mime->globs, l, g)
508      {
509         if (!g) continue;
510         if (strcmp(g->name, globing)) continue;
511         return g;
512      }
513    return NULL;
514 }
515
516 static void 
517 _cb_config(void *data, void *data2 __UNUSED__) 
518 {
519    Eina_List *l;
520    E_Config_Dialog_Data *cfdata;
521    E_Config_Mime_Icon *mi = NULL;
522    const char *m;
523    int found = 0;
524
525    cfdata = data;
526    if (!cfdata) return;
527    m = e_widget_ilist_selected_label_get(cfdata->gui.list);
528    if (!m) return;
529
530    EINA_LIST_FOREACH(e_config->mime_icons, l, mi)
531      {
532         if (!mi) continue;
533         if (!mi->mime) continue;
534         if (strcmp(mi->mime, m)) continue;
535         found = 1;
536         break;
537      }
538    if (!found)
539      {
540         mi = E_NEW(E_Config_Mime_Icon, 1);
541         mi->mime = eina_stringshare_add(m);
542      }
543
544    cfdata->edit_dlg = e_int_config_mime_edit(mi, cfdata);
545 }