Tizen 2.1 release
[platform/core/uifw/e17.git] / src / bin / e_configure.c
1 #include "e.h"
2
3 static void      _e_configure_menu_module_item_cb(void *data, E_Menu *m, E_Menu_Item *mi);
4 static void      _e_configure_menu_add(void *data, E_Menu *m);
5 static void      _e_configure_efreet_desktop_cleanup(void);
6 static void      _e_configure_efreet_desktop_update(void);
7 static Eina_Bool _e_configure_cb_efreet_desktop_cache_update(void *data, int type, void *event);
8 static void      _e_configure_registry_item_full_add(const char *path, int pri, const char *label, const char *icon_file, const char *icon, E_Config_Dialog *(*func)(E_Container * con, const char *params), void (*generic_func)(E_Container *con, const char *params), Efreet_Desktop *desktop, const char *params);
9 static void      _e_configure_registry_item_free(E_Configure_It *eci);
10
11 static void      _configure_job(void *data);
12 static Eina_Bool _configure_init_timer(void *data);
13
14 EAPI Eina_List *e_configure_registry = NULL;
15
16 static Eina_List *handlers = NULL;
17 static E_Int_Menu_Augmentation *maug = NULL;
18 static Ecore_Job *update_job = NULL;
19
20 static struct
21 {
22    void        (*func)(const void *data, E_Container *con, const char *params, Efreet_Desktop *desktop);
23    const char *data;
24 } custom_desktop_exec = { NULL, NULL };
25
26 EINTERN void
27 e_configure_init(void)
28 {
29    e_configure_registry_category_add("extensions", 90, _("Extensions"), NULL, "preferences-extensions");
30    e_configure_registry_item_add("extensions/modules", 10, _("Modules"), NULL, "preferences-plugin", e_int_config_modules);
31
32    maug = e_int_menus_menu_augmentation_add_sorted
33        ("config/1", _("Modules"), _e_configure_menu_add, NULL, NULL, NULL);
34
35    if (update_job)
36      {
37         ecore_job_del(update_job);
38         update_job = NULL;
39      }
40    ecore_timer_add(0.0, _configure_init_timer, NULL);
41 }
42
43 EAPI void
44 e_configure_registry_call(const char *path, E_Container *con, const char *params)
45 {
46    E_Configure_Cat *ecat;
47    Eina_List *l;
48    char *cat;
49    const char *item;
50
51    /* path is "category/item" */
52    cat = ecore_file_dir_get(path);
53    if (!cat) return;
54    item = ecore_file_file_get(path);
55    if (!con) con = e_container_current_get(e_manager_current_get());
56    EINA_LIST_FOREACH(e_configure_registry, l, ecat)
57      if (!strcmp(cat, ecat->cat))
58        {
59           E_Configure_It *eci;
60           Eina_List *ll;
61
62           EINA_LIST_FOREACH(ecat->items, ll, eci)
63             if (!strcmp(item, eci->item))
64               {
65                  if (!params) params = eci->params;
66
67                  if (eci->func) eci->func(con, params);
68                  else if (eci->generic_func)
69                    eci->generic_func(con, params);
70                  else if (eci->desktop)
71                    {
72                       if (custom_desktop_exec.func)
73                         custom_desktop_exec.func(custom_desktop_exec.data,
74                                                  con, params, eci->desktop);
75                       else
76                         e_exec(e_util_zone_current_get(con->manager),
77                                eci->desktop, NULL, NULL, "config");
78                    }
79                  break;
80               }
81           break;
82        }
83    free(cat);
84 }
85
86 EAPI void
87 e_configure_registry_item_add(const char *path, int pri, const char *label, const char *icon_file, const char *icon, E_Config_Dialog *(*func)(E_Container * con, const char *params))
88 {
89    _e_configure_registry_item_full_add(path, pri, label, icon_file, icon, func, NULL, NULL, NULL);
90 }
91
92 EAPI void
93 e_configure_registry_generic_item_add(const char *path, int pri, const char *label, const char *icon_file, const char *icon, void (*generic_func)(E_Container *con, const char *params))
94 {
95    _e_configure_registry_item_full_add(path, pri, label, icon_file, icon, NULL, generic_func, NULL, NULL);
96 }
97
98 EAPI void
99 e_configure_registry_item_params_add(const char *path, int pri, const char *label, const char *icon_file, const char *icon, E_Config_Dialog *(*func)(E_Container * con, const char *params), const char *params)
100 {
101    _e_configure_registry_item_full_add(path, pri, label, icon_file, icon, func, NULL, NULL, params);
102 }
103
104 /**  
105  * Delete an item  in the configuration panel.
106  * 
107  * @param path location the item to delete 
108  */
109 EAPI void
110 e_configure_registry_item_del(const char *path)
111 {
112    E_Configure_Cat *ecat;
113    Eina_List *l;
114    const char *item;
115    char *cat;
116
117    /* path is "category/item" */
118    cat = ecore_file_dir_get(path);
119    if (!cat) return;
120    item = ecore_file_file_get(path);
121
122    EINA_LIST_FOREACH(e_configure_registry, l, ecat)
123      if (!strcmp(cat, ecat->cat))
124        {
125           E_Configure_It *eci;
126           Eina_List *ll;
127
128           EINA_LIST_FOREACH(ecat->items, ll, eci)
129             if (!strcmp(item, eci->item))
130               {
131                  ecat->items = eina_list_remove_list(ecat->items, ll);
132
133                  _e_configure_registry_item_free(eci);
134                  break;
135               }
136           break;
137        }
138    free(cat);
139 }
140
141 /**  
142  * Add a category to the configuration panel.
143  *
144  * @param path location the new category 
145  * @param pri the priority for sorting the category in the category list
146  * @param label the name the user will see in configuration panel
147  * @param icon_file the edje file that holds the icon for the category.
148  * Can be null to use current theme.
149  * @param icon the name of the edje group to use as icon 
150  */
151 static int
152 _E_configure_category_pri_cb(E_Configure_Cat *ecat, E_Configure_Cat *ecat2)
153 {
154    if (ecat->pri == ecat2->pri)
155      return strcmp(ecat->label, ecat2->label);
156    return ecat->pri - ecat2->pri;
157 }
158
159 EAPI void
160 e_configure_registry_category_add(const char *path, int pri, const char *label, const char *icon_file, const char *icon)
161 {
162    E_Configure_Cat *ecat2;
163    E_Configure_Cat *ecat;
164    Eina_List *l;
165
166    /* if it exists - ignore this */
167    EINA_LIST_FOREACH(e_configure_registry, l, ecat2)
168      if (!strcmp(ecat2->cat, path)) return;
169
170    ecat = E_NEW(E_Configure_Cat, 1);
171    if (!ecat) return;
172
173    ecat->cat = eina_stringshare_add(path);
174    ecat->pri = pri;
175    ecat->label = eina_stringshare_add(label);
176    if (icon_file) ecat->icon_file = eina_stringshare_add(icon_file);
177    if (icon) ecat->icon = eina_stringshare_add(icon);
178    e_configure_registry = eina_list_sorted_insert(e_configure_registry,
179                                                   EINA_COMPARE_CB(_E_configure_category_pri_cb),
180                                                   ecat);
181 }
182
183 /**  
184  * Delete a category in the configuration panel.
185  * 
186  * @param path location the category to delete 
187  */
188 EAPI void
189 e_configure_registry_category_del(const char *path)
190 {
191    E_Configure_Cat *ecat;
192    Eina_List *l;
193    char *cat;
194
195    cat = ecore_file_dir_get(path);
196    if (!cat) return;
197    EINA_LIST_FOREACH(e_configure_registry, l, ecat)
198      if (!strcmp(cat, ecat->cat))
199        {
200           if (ecat->items) break;
201           e_configure_registry = eina_list_remove_list(e_configure_registry, l);
202           eina_stringshare_del(ecat->cat);
203           eina_stringshare_del(ecat->label);
204           if (ecat->icon) eina_stringshare_del(ecat->icon);
205           if (ecat->icon_file) eina_stringshare_del(ecat->icon_file);
206           free(ecat);
207           break;
208        }
209    free(cat);
210 }
211
212 /**  
213  * Add a item to the configuration panel.
214  *
215  * @param path location the location to place configuration item 
216  * @param pri the priority for sorting the item in the category list
217  * @param label the name the user will see in configuration panel
218  * @param icon_file the edje file that holds the icon for the category.
219  * Can be null to use current theme.
220  * @param icon the name of the edje group to use as icon
221  * @param func the callback to use when the configuration item is clicked
222  */
223
224 EAPI void
225 e_configure_registry_custom_desktop_exec_callback_set(void (*func)(const void *data, E_Container *con, const char *params, Efreet_Desktop *desktop), const void *data)
226 {
227    custom_desktop_exec.func = func;
228    custom_desktop_exec.data = data;
229 }
230
231 EAPI int
232 e_configure_registry_exists(const char *path)
233 {
234    E_Configure_Cat *ecat;
235    Eina_List *l;
236    char *cat;
237    const char *item;
238    int ret = 0;
239
240    /* path is "category/item" */
241    cat = ecore_file_dir_get(path);
242    if (!cat) return 0;
243    item = ecore_file_file_get(path);
244    EINA_LIST_FOREACH(e_configure_registry, l, ecat)
245      if (!strcmp(cat, ecat->cat))
246        {
247           E_Configure_It *eci;
248           Eina_List *ll;
249
250           if (!item)
251             {
252                ret = 1;
253                break;
254             }
255           EINA_LIST_FOREACH(ecat->items, ll, eci)
256             if (!strcmp(item, eci->item))
257               {
258                  ret = 1;
259                  break;
260               }
261           break;
262        }
263
264    free(cat);
265    return ret;
266 }
267
268 static void
269 _e_configure_menu_module_item_cb(void *data __UNUSED__, E_Menu *m, E_Menu_Item *mi __UNUSED__)
270 {
271    e_int_config_modules(m->zone->container, NULL);
272 }
273
274 static void
275 _e_configure_menu_add(void *data __UNUSED__, E_Menu *m)
276 {
277    E_Menu_Item *mi;
278
279    mi = e_menu_item_new(m);
280    e_menu_item_label_set(mi, _("Modules"));
281    e_util_menu_item_theme_icon_set(mi, "preferences-plugin");
282    e_menu_item_callback_set(mi, _e_configure_menu_module_item_cb, NULL);
283 }
284
285 static void
286 _configure_job(void *data __UNUSED__)
287 {
288    _e_configure_efreet_desktop_update();
289    update_job = NULL;
290 }
291
292 static Eina_Bool
293 _configure_init_timer(void *data __UNUSED__)
294 {
295    handlers = eina_list_append
296        (handlers, ecore_event_handler_add
297          (EFREET_EVENT_DESKTOP_CACHE_UPDATE, _e_configure_cb_efreet_desktop_cache_update, NULL));
298    if (update_job) ecore_job_del(update_job);
299    update_job = ecore_job_add(_configure_job, NULL);
300    return EINA_FALSE;
301 }
302
303 static void
304 _e_configure_efreet_desktop_cleanup(void)
305 {
306    Eina_List *l;
307    E_Configure_Cat *ecat;
308
309 //   printf("_e_configure_efreet_desktop_cleanup\n");
310 /* remove anything with a desktop entry */
311    EINA_LIST_FOREACH(e_configure_registry, l, ecat)
312      {
313         E_Configure_It *eci;
314         Eina_List *ll, *ln;
315
316         EINA_LIST_FOREACH_SAFE (ecat->items, ll, ln, eci)
317           if (eci->desktop)
318             {
319                _e_configure_registry_item_free(eci);
320                ecat->items = eina_list_remove_list(ecat->items, ll);
321             }
322      }
323 }
324
325 static void
326 _e_configure_efreet_desktop_update(void)
327 {
328    Eina_List *settings_desktops, *system_desktops;
329    Efreet_Desktop *desktop;
330    Eina_List *l;
331    char buf[1024];
332
333    /* get desktops */
334    settings_desktops = efreet_util_desktop_category_list("Settings");
335    system_desktops = efreet_util_desktop_category_list("System");
336    if ((!settings_desktops) || (!system_desktops))
337      {
338         EINA_LIST_FREE(settings_desktops, desktop)
339           efreet_desktop_free(desktop);
340         EINA_LIST_FREE(system_desktops, desktop)
341           efreet_desktop_free(desktop);
342         return;
343      }
344
345    /* get ones in BOTH lists */
346    EINA_LIST_FOREACH(settings_desktops, l, desktop)
347      {
348         char *s;
349         char *cfg_cat_name;
350         const char *cfg_cat_icon;
351         char *cfg_cat;
352         char *cfg_cat_cfg;
353         const char *cfg_icon;
354         char *label;
355         int cfg_pri;
356         int dopref;
357
358         dopref = 0;
359         cfg_cat = NULL;
360         cfg_icon = NULL;
361         cfg_cat_cfg = NULL;
362         cfg_pri = 1000;
363         cfg_cat_name = NULL;
364         cfg_cat_icon = NULL;
365         label = NULL;
366         if (!eina_list_data_find(system_desktops, desktop))
367           {
368              /* settings desktop but not in system -> put in preferences */
369              dopref = 1;
370           }
371         if (desktop->x)
372           {
373              cfg_cat_cfg = eina_hash_find(desktop->x, "X-Enlightenment-Config-Category");
374              s = eina_hash_find(desktop->x, "X-Enlightenment-Config-Priority");
375              if (s) cfg_pri = atoi(s);
376              cfg_cat_name = eina_hash_find(desktop->x, "X-Enlightenment-Config-Category-Name");
377              cfg_cat_icon = eina_hash_find(desktop->x, "X-Enlightenment-Config-Category-Icon");
378              if ((cfg_cat_icon) && (cfg_cat_icon[0] != '/'))
379                cfg_cat_icon = efreet_icon_path_find(e_config->icon_theme,
380                                                     cfg_cat_icon, 64);
381           }
382         if (desktop->icon)
383           {
384              if (desktop->icon[0] == '/')
385                cfg_icon = desktop->icon;
386              else
387                cfg_icon = efreet_icon_path_find(e_config->icon_theme,
388                                                 desktop->icon, 64);
389           }
390         if (desktop->name) label = desktop->name;
391         else if (desktop->generic_name)
392           label = desktop->generic_name;
393         else label = "???";
394         if (!cfg_cat_cfg)
395           {
396              const char *ic = cfg_cat_icon;
397
398              if (dopref)
399                {
400                   snprintf(buf, sizeof(buf), "preferences/%s", label);
401                   if (!ic) ic = "preferences-preferences";
402                   e_configure_registry_category_add("preferences", 900,
403                                                     _("Preferences"),
404                                                     NULL, ic);
405                }
406              else
407                {
408                   snprintf(buf, sizeof(buf), "system/%s", label);
409                   if (!ic) ic = "preferences-system";
410                   e_configure_registry_category_add("system", 1000,
411                                                     _("System"),
412                                                     NULL, ic);
413                }
414              cfg_cat_cfg = buf;
415           }
416         else
417           {
418              cfg_cat = ecore_file_dir_get(cfg_cat_cfg);
419              if (!cfg_cat) cfg_cat = strdup(cfg_cat_cfg);
420              if (cfg_cat)
421                {
422                   if (!cfg_cat_name) cfg_cat_name = cfg_cat;
423                   e_configure_registry_category_add(cfg_cat,
424                                                     1000, cfg_cat_name,
425                                                     NULL, cfg_cat_icon);
426                   free(cfg_cat);
427                   cfg_cat = NULL;
428                }
429           }
430         _e_configure_registry_item_full_add(cfg_cat_cfg, cfg_pri, label,
431                                             NULL, cfg_icon,
432                                             NULL, NULL, desktop, NULL);
433      }
434    EINA_LIST_FREE(settings_desktops, desktop)
435      efreet_desktop_free(desktop);
436    EINA_LIST_FREE(system_desktops, desktop)
437      efreet_desktop_free(desktop);
438 }
439
440 static Eina_Bool
441 _e_configure_cb_efreet_desktop_cache_update(void *data __UNUSED__, int type __UNUSED__, void *event __UNUSED__)
442 {
443    _e_configure_efreet_desktop_cleanup();
444    if (update_job) ecore_job_del(update_job);
445    update_job = ecore_job_add(_configure_job, NULL);
446    return 1;
447 }
448
449 static int
450 _e_configure_compare_cb(E_Configure_It *eci, E_Configure_It *eci2)
451 {
452    return e_util_strcasecmp(eci->label, eci2->label);
453 }
454
455 static int
456 _e_configure_compare_pri_cb(E_Configure_It *eci, E_Configure_It *eci2)
457 {
458    if (eci->pri == eci2->pri)
459      return strcmp(eci->label, eci2->label);
460    return eci->pri - eci2->pri;
461 }
462
463 static void
464 _e_configure_registry_item_full_add(const char *path, int pri, const char *label, const char *icon_file, const char *icon, E_Config_Dialog *(*func)(E_Container * con, const char *params), void (*generic_func)(E_Container *con, const char *params), Efreet_Desktop *desktop, const char *params)
465 {
466    Eina_List *l;
467    char *cat;
468    const char *item;
469    E_Configure_It *eci;
470    E_Configure_Cat *ecat;
471    Eina_Bool external;
472
473    /* path is "category/item" */
474    cat = ecore_file_dir_get(path);
475    if (!cat) return;
476    item = ecore_file_file_get(path);
477    eci = E_NEW(E_Configure_It, 1);
478    if (!eci) goto done;
479
480    eci->item = eina_stringshare_add(item);
481    eci->pri = pri;
482    eci->label = eina_stringshare_add(label);
483    if (icon_file) eci->icon_file = eina_stringshare_add(icon_file);
484    if (icon) eci->icon = eina_stringshare_add(icon);
485    if (params) eci->params = eina_stringshare_add(params);
486    eci->func = func;
487    eci->generic_func = generic_func;
488    eci->desktop = desktop;
489    if (eci->desktop) efreet_desktop_ref(eci->desktop);
490    external = !strncmp(path, "preferences/", sizeof("preferences/") - 1);
491    if (!external) external = !strncmp(path, "system/", sizeof("system/") - 1);
492
493    EINA_LIST_FOREACH(e_configure_registry, l, ecat)
494      if (!strcmp(cat, ecat->cat))
495        {
496           if (external)
497             {
498                ecat->items = eina_list_sorted_insert(ecat->items, EINA_COMPARE_CB(_e_configure_compare_cb), eci);
499                goto done; /* This was a break before, but sounds like it could lead to a double insert */
500             }
501           ecat->items = eina_list_sorted_insert(ecat->items, EINA_COMPARE_CB(_e_configure_compare_pri_cb), eci);
502           break;
503        }
504
505 done:
506    free(cat);
507 }
508
509 static void
510 _e_configure_registry_item_free(E_Configure_It *eci)
511 {
512    eina_stringshare_del(eci->item);
513    eina_stringshare_del(eci->label);
514    eina_stringshare_del(eci->icon);
515    if (eci->icon_file) eina_stringshare_del(eci->icon_file);
516    if (eci->desktop) efreet_desktop_free(eci->desktop);
517    if (eci->params) eina_stringshare_del(eci->params);
518    free(eci);
519 }
520