Git init
[framework/uifw/e17.git] / src / modules / fileman / e_mod_main.c
1 #include "e.h"
2 #include "e_fm_device.h"
3 #include "e_mod_main.h"
4 #include "e_mod_config.h"
5 #include "e_mod_dbus.h"
6
7 /* actual module specifics */
8 static void _e_mod_action_fileman_cb(E_Object   *obj,
9                                      const char *params);
10 static void _e_mod_menu_gtk_cb(void        *data,
11                                E_Menu      *m,
12                                E_Menu_Item *mi);
13 static void _e_mod_menu_virtual_cb(void        *data,
14                                    E_Menu      *m,
15                                    E_Menu_Item *mi);
16 static void _e_mod_menu_volume_cb(void        *data,
17                                   E_Menu      *m,
18                                   E_Menu_Item *mi);
19 static void      _e_mod_menu_add(void   *data,
20                                  E_Menu *m);
21 static void      _e_mod_fileman_config_load(void);
22 static void      _e_mod_fileman_config_free(void);
23 static Eina_Bool _e_mod_cb_config_timer(void *data);
24 static Eina_Bool _e_mod_zone_add(void *data,
25                                  int   type,
26                                  void *event);
27
28 static E_Module *conf_module = NULL;
29 static E_Action *act = NULL;
30 static E_Int_Menu_Augmentation *maug = NULL;
31 static Ecore_Event_Handler *zone_add_handler = NULL;
32
33 static E_Config_DD *conf_edd = NULL;
34 Config *fileman_config = NULL;
35
36 /* module setup */
37 EAPI E_Module_Api e_modapi =
38 {
39    E_MODULE_API_VERSION,
40    "Fileman"
41 };
42
43 EAPI void *
44 e_modapi_init(E_Module *m)
45 {
46    Eina_List *l, *ll, *lll;
47    E_Manager *man;
48    E_Container *con;
49    E_Zone *zone;
50
51    conf_module = m;
52
53    //eina_init();
54
55    /* Setup Entry in Config Panel */
56    e_configure_registry_category_add("fileman", 100, _("Files"),
57                                      NULL, "system-file-manager");
58    e_configure_registry_item_add("fileman/fileman", 10, _("File Manager"),
59                                  NULL, "system-file-manager",
60                                  e_int_config_fileman);
61    e_configure_registry_item_add("fileman/file_icons", 20, _("File Icons"),
62                                  NULL, "preferences-file-icons",
63                                  e_int_config_mime);
64    /* Setup Config edd */
65    _e_mod_fileman_config_load();
66
67    /* add module supplied action */
68    act = e_action_add("fileman");
69    if (act)
70      {
71         act->func.go = _e_mod_action_fileman_cb;
72         e_action_predef_name_set(_("Launch"), _("File Manager"),
73                                  "fileman", NULL, "syntax: /path/to/dir or ~/path/to/dir or favorites or desktop, examples: /boot/grub, ~/downloads", 1);
74      }
75    maug = e_int_menus_menu_augmentation_add_sorted
76        ("main/1", _("Files"), _e_mod_menu_add, NULL, NULL, NULL);
77    e_module_delayed_set(m, 1);
78
79    /* Hook into zones */
80    for (l = e_manager_list(); l; l = l->next)
81      {
82         man = l->data;
83         for (ll = man->containers; ll; ll = ll->next)
84           {
85              con = ll->data;
86              for (lll = con->zones; lll; lll = lll->next)
87                {
88                   zone = lll->data;
89                   if (e_fwin_zone_find(zone)) continue;
90                   if ((zone->container->num == 0) && (zone->num == 0) &&
91                       (fileman_config->view.show_desktop_icons))
92                     e_fwin_zone_new(zone, "desktop", "/");
93                   else
94                     {
95                        char buf[256];
96
97                        if (fileman_config->view.show_desktop_icons)
98                          {
99                             snprintf(buf, sizeof(buf), "%i",
100                                      (zone->container->num + zone->num));
101                             e_fwin_zone_new(zone, "desktop", buf);
102                          }
103                     }
104                }
105           }
106      }
107    zone_add_handler = ecore_event_handler_add(E_EVENT_ZONE_ADD,
108                                               _e_mod_zone_add, NULL);
109
110    /* FIXME: add system event for new zone creation, and on creation, add an fwin to the zone */
111
112    e_fileman_dbus_init();
113
114    return m;
115 }
116
117 EAPI int
118 e_modapi_shutdown(E_Module *m __UNUSED__)
119 {
120    Eina_List *l, *ll, *lll;
121    E_Manager *man;
122    E_Container *con;
123    E_Zone *zone;
124    E_Config_Dialog *cfd;
125
126    e_fileman_dbus_shutdown();
127
128    ecore_event_handler_del(zone_add_handler);
129    zone_add_handler = NULL;
130
131    /* Unhook zone fm */
132    for (l = e_manager_list(); l; l = l->next)
133      {
134         man = l->data;
135         for (ll = man->containers; ll; ll = ll->next)
136           {
137              con = ll->data;
138              for (lll = con->zones; lll; lll = lll->next)
139                {
140                   zone = lll->data;
141                   if (!zone) continue;
142                   e_fwin_zone_shutdown(zone);
143                }
144           }
145      }
146
147    /* remove module-supplied menu additions */
148    if (maug)
149      {
150         e_int_menus_menu_augmentation_del("main/1", maug);
151         maug = NULL;
152      }
153    /* remove module-supplied action */
154    if (act)
155      {
156         e_action_predef_name_del(_("Launch"), _("File Manager"));
157         e_action_del("fileman");
158         act = NULL;
159      }
160    while ((cfd = e_config_dialog_get("E", "fileman/mime_edit_dialog")))
161       e_object_del(E_OBJECT(cfd));
162    while ((cfd = e_config_dialog_get("E", "fileman/file_icons")))
163       e_object_del(E_OBJECT(cfd));
164    while ((cfd = e_config_dialog_get("E", "fileman/fileman")))
165       e_object_del(E_OBJECT(cfd));
166    
167    e_configure_registry_item_del("fileman/file_icons");
168    e_configure_registry_item_del("fileman/fileman");
169    e_configure_registry_category_del("fileman");
170
171    _e_mod_fileman_config_free();
172    E_CONFIG_DD_FREE(conf_edd);
173
174    //eina_shutdown();
175
176    conf_module = NULL;
177    return 1;
178 }
179
180 EAPI int
181 e_modapi_save(E_Module *m __UNUSED__)
182 {
183    e_config_domain_save("module.fileman", conf_edd, fileman_config);
184    return 1;
185 }
186
187 /* action callback */
188 static void
189 _e_mod_action_fileman_cb(E_Object   *obj,
190                          const char *params)
191 {
192    E_Zone *zone = NULL;
193
194    if (obj)
195      {
196         if (obj->type == E_MANAGER_TYPE)
197           zone = e_util_zone_current_get((E_Manager *)obj);
198         else if (obj->type == E_CONTAINER_TYPE)
199           zone = e_util_zone_current_get(((E_Container *)obj)->manager);
200         else if (obj->type == E_ZONE_TYPE)
201           zone = e_util_zone_current_get(((E_Zone *)obj)->container->manager);
202         else
203           zone = e_util_zone_current_get(e_manager_current_get());
204      }
205    if (!zone) zone = e_util_zone_current_get(e_manager_current_get());
206    if (zone)
207      {
208         if (params && params[0] == '/')
209           e_fwin_new(zone->container, "/", params);
210         else if (params && params[0] == '~')
211           e_fwin_new(zone->container, "~/", params + 1);
212         else if (params && strcmp(params, "(none)")) /* avoid matching paths that no longer exist */
213           {
214              char *path;
215              path = e_util_shell_env_path_eval(params);
216              if (path)
217                {
218                   e_fwin_new(zone->container, path, "/");
219                   free(path);
220                }
221           }
222         else
223           e_fwin_new(zone->container, "favorites", "/");
224      }
225 }
226
227 /* menu item callback(s) */
228 //~ static int
229 //~ _e_mod_fileman_defer_cb(void *data)
230 //~ {
231 //~ E_Zone *zone;
232
233 //~ zone = data;
234 //~ if (zone) e_fwin_new(zone->container, "favorites", "/");
235 //~ return 0;
236 //~ }
237
238 //~ static void
239 //~ _e_mod_fileman_cb(void *data, E_Menu *m, E_Menu_Item *mi)
240 //~ {
241 //~ ecore_idle_enterer_add(_e_mod_fileman_defer_cb, m->zone);
242 //~ }
243
244 static void
245 _e_mod_menu_gtk_cb(void           *data,
246                    E_Menu         *m,
247                    E_Menu_Item *mi __UNUSED__)
248 {
249    char *path;
250
251    if (!(path = data)) return;
252    if (m->zone) e_fwin_new(m->zone->container, NULL, path);
253    eina_stringshare_del(path);
254 }
255
256 static void
257 _e_mod_menu_virtual_cb(void           *data,
258                        E_Menu         *m,
259                        E_Menu_Item *mi __UNUSED__)
260 {
261    if (m->zone) e_fwin_new(m->zone->container, data, "/");
262 }
263
264 static void
265 _e_mod_menu_volume_cb(void           *data,
266                       E_Menu         *m,
267                       E_Menu_Item *mi __UNUSED__)
268 {
269    E_Volume *vol = data;
270
271    if (vol->mounted)
272      {
273         if (m->zone)
274           e_fwin_new(m->zone->container, NULL, vol->mount_point);
275      }
276    else
277      {
278         char buf[PATH_MAX];
279
280         snprintf(buf, sizeof(buf), "removable:%s", vol->udi);
281         e_fwin_new(e_container_current_get(e_manager_current_get()),
282                    buf, "/");
283      }
284 }
285
286 static void
287 _e_mod_fileman_parse_gtk_bookmarks(E_Menu   *m,
288                                    Eina_Bool need_separator)
289 {
290    char line[PATH_MAX];
291    char buf[PATH_MAX];
292    E_Menu_Item *mi;
293    Efreet_Uri *uri;
294    char *alias;
295    FILE *fp;
296
297    snprintf(buf, sizeof(buf), "%s/.gtk-bookmarks", e_user_homedir_get());
298    fp = fopen(buf, "r");
299    if (fp)
300      {
301         while(fgets(line, sizeof(line), fp))
302           {
303              alias = NULL;
304              line[strlen(line) - 1] = '\0';
305              alias = strchr(line, ' ');
306              if (alias)
307                {
308                   line[alias - line] = '\0';
309                   alias++;
310                }
311              uri = efreet_uri_decode(line);
312              if (uri && uri->path)
313                {
314                   if (ecore_file_exists(uri->path))
315                     {
316                        if (need_separator)
317                          {
318                             mi = e_menu_item_new(m);
319                             e_menu_item_separator_set(mi, 1);
320                             need_separator = 0;
321                          }
322
323                        mi = e_menu_item_new(m);
324                        e_menu_item_label_set(mi, alias ? alias :
325                                              ecore_file_file_get(uri->path));
326                        e_util_menu_item_theme_icon_set(mi, "folder");
327                        e_menu_item_callback_set(mi, _e_mod_menu_gtk_cb,
328                                                 (void *)eina_stringshare_add(uri->path));
329                     }
330                }
331              if (uri) efreet_uri_free(uri);
332           }
333         fclose(fp);
334      }
335 }
336
337 /* menu item add hook */
338 void
339 _e_mod_menu_generate(void *data __UNUSED__,
340                      E_Menu    *m)
341 {
342    E_Menu_Item *mi;
343    E_Volume *vol;
344    const Eina_List *l;
345
346    /* Home */
347    mi = e_menu_item_new(m);
348    e_menu_item_label_set(mi, _("Home"));
349    e_util_menu_item_theme_icon_set(mi, "user-home");
350    e_menu_item_callback_set(mi, _e_mod_menu_virtual_cb, "~/");
351
352    /* Desktop */
353    mi = e_menu_item_new(m);
354    e_menu_item_label_set(mi, _("Desktop"));
355    e_util_menu_item_theme_icon_set(mi, "user-desktop");
356    e_menu_item_callback_set(mi, _e_mod_menu_virtual_cb, "desktop");
357
358    /* Favorites */
359    mi = e_menu_item_new(m);
360    e_menu_item_label_set(mi, _("Favorites"));
361    e_util_menu_item_theme_icon_set(mi, "user-bookmarks");
362    e_menu_item_callback_set(mi, _e_mod_menu_virtual_cb, "favorites");
363
364    /* Trash */
365    //~ mi = e_menu_item_new(em);
366    //~ e_menu_item_label_set(mi, D_("Trash"));
367    //~ e_util_menu_item_theme_icon_set(mi, "user-trash");
368    //~ e_menu_item_callback_set(mi, _places_run_fm, "trash:///");
369
370    /* Root */
371    mi = e_menu_item_new(m);
372    e_menu_item_label_set(mi, _("Root"));
373    e_util_menu_item_theme_icon_set(mi, "computer");
374    e_menu_item_callback_set(mi, _e_mod_menu_virtual_cb, "/");
375
376    Eina_Bool need_separator = 1;
377
378    /* Volumes */
379    Eina_Bool volumes_visible = 0;
380    EINA_LIST_FOREACH(e_fm2_device_volume_list_get(), l, vol)
381      {
382         if (vol->mount_point && !strcmp(vol->mount_point, "/")) continue;
383
384         if (need_separator)
385           {
386              mi = e_menu_item_new(m);
387              e_menu_item_separator_set(mi, 1);
388              need_separator = 0;
389           }
390
391         mi = e_menu_item_new(m);
392         e_menu_item_label_set(mi, vol->label);
393         e_util_menu_item_theme_icon_set(mi, vol->icon);
394         e_menu_item_callback_set(mi, _e_mod_menu_volume_cb, vol);
395         volumes_visible = 1;
396      }
397
398    /* Favorites */
399    //~ if (places_conf->show_bookm)
400    //~ {
401    _e_mod_fileman_parse_gtk_bookmarks(m, need_separator || volumes_visible > 0);
402    //~ }
403
404    e_menu_pre_activate_callback_set(m, NULL, NULL);
405 }
406
407 void
408 _e_mod_menu_add(void *data __UNUSED__,
409                 E_Menu    *m)
410 {
411 #ifdef ENABLE_FILES
412    E_Menu_Item *mi;
413    E_Menu *sub;
414
415    mi = e_menu_item_new(m);
416    e_menu_item_label_set(mi, _("Files"));
417    e_util_menu_item_theme_icon_set(mi, "system-file-manager");
418    sub = e_menu_new();
419    e_menu_item_submenu_set(mi, sub);
420    e_menu_pre_activate_callback_set(sub, _e_mod_menu_generate, NULL);
421 #endif
422 }
423
424 /* Abstract fileman config load/create to one function for maintainability */
425 static void
426 _e_mod_fileman_config_load(void)
427 {
428    conf_edd = E_CONFIG_DD_NEW("Fileman_Config", Config);
429    #undef T
430    #undef D
431    #define T Config
432    #define D conf_edd
433    E_CONFIG_VAL(D, T, config_version, INT);
434    E_CONFIG_VAL(D, T, view.mode, INT);
435    E_CONFIG_VAL(D, T, view.open_dirs_in_place, UCHAR);
436    E_CONFIG_VAL(D, T, view.selector, UCHAR);
437    E_CONFIG_VAL(D, T, view.single_click, UCHAR);
438    E_CONFIG_VAL(D, T, view.no_subdir_jump, UCHAR);
439    E_CONFIG_VAL(D, T, view.no_subdir_drop, UCHAR);
440    E_CONFIG_VAL(D, T, view.always_order, UCHAR);
441    E_CONFIG_VAL(D, T, view.link_drop, UCHAR);
442    E_CONFIG_VAL(D, T, view.fit_custom_pos, UCHAR);
443    E_CONFIG_VAL(D, T, view.show_full_path, UCHAR);
444    E_CONFIG_VAL(D, T, view.show_desktop_icons, UCHAR);
445    E_CONFIG_VAL(D, T, view.show_toolbar, UCHAR);
446    E_CONFIG_VAL(D, T, icon.icon.w, INT);
447    E_CONFIG_VAL(D, T, icon.icon.h, INT);
448    E_CONFIG_VAL(D, T, icon.list.w, INT);
449    E_CONFIG_VAL(D, T, icon.list.h, INT);
450    E_CONFIG_VAL(D, T, icon.fixed.w, UCHAR);
451    E_CONFIG_VAL(D, T, icon.fixed.h, UCHAR);
452    E_CONFIG_VAL(D, T, icon.extension.show, UCHAR);
453    E_CONFIG_VAL(D, T, list.sort.no_case, UCHAR);
454    E_CONFIG_VAL(D, T, list.sort.dirs.first, UCHAR);
455    E_CONFIG_VAL(D, T, list.sort.dirs.last, UCHAR);
456    E_CONFIG_VAL(D, T, selection.single, UCHAR);
457    E_CONFIG_VAL(D, T, selection.windows_modifiers, UCHAR);
458    E_CONFIG_VAL(D, T, theme.background, STR);
459    E_CONFIG_VAL(D, T, theme.frame, STR);
460    E_CONFIG_VAL(D, T, theme.icons, STR);
461    E_CONFIG_VAL(D, T, theme.fixed, UCHAR);
462
463    fileman_config = e_config_domain_load("module.fileman", conf_edd);
464    if (fileman_config)
465      {
466         if ((fileman_config->config_version >> 16) < MOD_CONFIG_FILE_EPOCH)
467           {
468              _e_mod_fileman_config_free();
469              ecore_timer_add(1.0, _e_mod_cb_config_timer,
470                              _("Fileman Module Settings data needed upgrading. Your old configuration<br>"
471                                "has been wiped and a new set of defaults initialized. This<br>"
472                                "will happen regularly during development, so don't report a<br>"
473                                "bug. This simply means Fileman module needs new configuration<br>"
474                                "data by default for usable functionality that your old<br>"
475                                "configuration simply lacks. This new set of defaults will fix<br>"
476                                "that by adding it in. You can re-configure things now to your<br>"
477                                "liking. Sorry for the hiccup in your configuration.<br>"));
478           }
479         else if (fileman_config->config_version > MOD_CONFIG_FILE_VERSION)
480           {
481              _e_mod_fileman_config_free();
482              ecore_timer_add(1.0, _e_mod_cb_config_timer,
483                              _("Your Fileman Module configuration is NEWER than Fileman Module version. This is very<br>"
484                                "strange. This should not happen unless you downgraded<br>"
485                                "the Fileman Module or copied the configuration from a place where<br>"
486                                "a newer version of the Fileman Module was running. This is bad and<br>"
487                                "as a precaution your configuration has been now restored to<br>"
488                                "defaults. Sorry for the inconvenience.<br>"));
489           }
490      }
491
492    if (!fileman_config)
493      {
494         fileman_config = E_NEW(Config, 1);
495         fileman_config->config_version = (MOD_CONFIG_FILE_EPOCH << 16);
496      }
497 #define IFMODCFG(v) \
498   if ((fileman_config->config_version & 0xffff) < (v)) {
499 #define IFMODCFGEND }
500
501     IFMODCFG(0x008d);
502     fileman_config->view.mode = E_FM2_VIEW_MODE_GRID_ICONS;
503     fileman_config->view.open_dirs_in_place = 0;
504     fileman_config->view.selector = 0;
505     fileman_config->view.single_click = 0;
506     fileman_config->view.no_subdir_jump = 0;
507     fileman_config->view.show_full_path = 0;
508     fileman_config->view.show_desktop_icons = 1;
509     fileman_config->icon.icon.w = 48;
510     fileman_config->icon.icon.h = 48;
511     fileman_config->icon.fixed.w = 0;
512     fileman_config->icon.fixed.h = 0;
513     fileman_config->icon.extension.show = 1;
514     fileman_config->list.sort.no_case = 1;
515     fileman_config->list.sort.dirs.first = 1;
516     fileman_config->list.sort.dirs.last = 0;
517     fileman_config->selection.single = 0;
518     fileman_config->selection.windows_modifiers = 0;
519     IFMODCFGEND;
520
521     IFMODCFG(0x0101);
522     fileman_config->view.show_toolbar = 0;
523     IFMODCFGEND;
524
525     fileman_config->config_version = MOD_CONFIG_FILE_VERSION;
526
527     /* UCHAR's give nasty compile warnings about comparisons so not gonna limit those */
528     E_CONFIG_LIMIT(fileman_config->view.mode, E_FM2_VIEW_MODE_ICONS, E_FM2_VIEW_MODE_LIST);
529     E_CONFIG_LIMIT(fileman_config->icon.icon.w, 16, 256);
530     E_CONFIG_LIMIT(fileman_config->icon.icon.h, 16, 256);
531     E_CONFIG_LIMIT(fileman_config->icon.list.w, 16, 256);
532     E_CONFIG_LIMIT(fileman_config->icon.list.h, 16, 256);
533
534     e_config_save_queue();
535 }
536
537 static void
538 _e_mod_fileman_config_free(void)
539 {
540    if (fileman_config->theme.background)
541      eina_stringshare_del(fileman_config->theme.background);
542    if (fileman_config->theme.frame)
543      eina_stringshare_del(fileman_config->theme.frame);
544    if (fileman_config->theme.icons)
545      eina_stringshare_del(fileman_config->theme.icons);
546    E_FREE(fileman_config);
547 }
548
549 static Eina_Bool
550 _e_mod_cb_config_timer(void *data)
551 {
552    e_util_dialog_show(_("Fileman Settings Updated"), "%s", (char *)data);
553    return ECORE_CALLBACK_CANCEL;
554 }
555
556 static Eina_Bool
557 _e_mod_zone_add(__UNUSED__ void *data,
558                 int              type,
559                 void            *event)
560 {
561    E_Event_Zone_Add *ev;
562    E_Zone *zone;
563
564    if (type != E_EVENT_ZONE_ADD) return ECORE_CALLBACK_PASS_ON;
565    ev = event;
566    zone = ev->zone;
567    if (e_fwin_zone_find(zone)) return ECORE_CALLBACK_PASS_ON;
568    if ((zone->container->num == 0) && (zone->num == 0) &&
569        (fileman_config->view.show_desktop_icons))
570      e_fwin_zone_new(zone, "desktop", "/");
571    else
572      {
573         char buf[256];
574
575         if (fileman_config->view.show_desktop_icons)
576           {
577              snprintf(buf, sizeof(buf), "%i",
578                       (zone->container->num + zone->num));
579              e_fwin_zone_new(zone, "desktop", buf);
580           }
581      }
582    return ECORE_CALLBACK_PASS_ON;
583 }
584