4 typedef struct _CFModule CFModule;
5 typedef struct _CFType CFType;
6 typedef struct _CFTypes CFTypes;
10 const char *short_name, *name, *comment;
11 const char *icon, *orig_path;
15 Eina_Bool enabled : 1;
20 const char *key, *name, *icon;
21 Eina_Hash *modules_hash; /* just used before constructing list */
22 Eina_List *modules; /* sorted and ready to be used */
25 struct _E_Config_Dialog_Data
28 Evas_Object *l_modules;
29 Evas_Object *o_toolbar;
30 Evas_Object *b_load, *b_unload;
35 Eina_List *loaded, *unloaded;
42 const char *key, *name, *icon;
45 /* pre defined types (used to specify icon and i18n name) */
46 static const CFTypes _types[] =
48 #define _CFT(k, n, i) \
49 {sizeof(k) - 1, k, n, i}
50 _CFT("utils", N_("Utilities"), "modules-utils"),
51 _CFT("system", N_("System"), "modules-system"),
52 _CFT("look", N_("Look"), "modules-look"),
53 _CFT("files", N_("Files"), "modules-files"),
54 _CFT("launcher", N_("Launcher"), "modules-launcher"),
55 _CFT("core", N_("Core"), "modules-core"),
56 _CFT("mobile", N_("Mobile"), "modules-mobile"),
57 _CFT("settings", N_("Settings"), "modules-settings"),
62 /* local function protos */
63 static void _cftype_free(CFType *cft);
65 static void _widget_list_selection_changed(void *data, Evas_Object *obj __UNUSED__);
67 static void *_create_data(E_Config_Dialog *cfd);
68 static void _free_data(E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata);
69 static Evas_Object *_basic_create(E_Config_Dialog *cfd, Evas *evas, E_Config_Dialog_Data *cfdata);
70 static void _fill_cat_list(E_Config_Dialog_Data *cfdata);
71 static void _module_end_state_apply(CFModule *cfm);
73 static void _toolbar_select_cb(void *data, void *data2);
75 static CFType *_cftype_find(E_Config_Dialog_Data *cfdata, const char *key, const char *name, const char *icon);
76 static CFType *_cftype_new(const char *key, const char *name, const char *icon);
77 static void _load_modules(const char *dir, Eina_Hash *types_hash);
78 static Eina_Bool _types_list_create_foreach_cb(const Eina_Hash *hash __UNUSED__, const void *key __UNUSED__, void *data, void *fdata);
79 static int _types_list_sort(const void *data1, const void *data2);
81 static void _btn_cb_unload(void *data, void *data2);
82 static void _btn_cb_load(void *data, void *data2);
84 EAPI E_Config_Dialog *
85 e_int_config_modules(E_Container *con, const char *params __UNUSED__)
87 E_Config_Dialog *cfd = NULL;
88 E_Config_Dialog_View *v = NULL;
90 if (e_config_dialog_find("E", "_config_modules_dialog")) return NULL;
92 v = E_NEW(E_Config_Dialog_View, 1);
93 v->create_cfdata = _create_data;
94 v->free_cfdata = _free_data;
95 v->basic.create_widgets = _basic_create;
97 cfd = e_config_dialog_new(con, _("Module Settings"),
98 "E", "_config_modules_dialog",
99 "preferences-plugin", 0, v, NULL);
104 _create_data(E_Config_Dialog *cfd __UNUSED__)
106 Eina_Hash *types_hash;
107 Eina_List *modules_paths, *l;
109 E_Config_Dialog_Data *cfdata = E_NEW(E_Config_Dialog_Data, 1);
111 types_hash = eina_hash_string_superfast_new(NULL);
112 if (!types_hash) return cfdata;
114 modules_paths = e_path_dir_list_get(path_modules);
117 eina_hash_free(types_hash);
121 EINA_LIST_FOREACH(modules_paths, l, epd)
123 if (ecore_file_is_dir(epd->dir))
124 _load_modules(epd->dir, types_hash);
127 e_path_dir_list_free(modules_paths);
129 eina_hash_foreach(types_hash, _types_list_create_foreach_cb, cfdata);
130 eina_hash_free(types_hash);
131 cfdata->types = eina_list_sort(cfdata->types, -1, _types_list_sort);
137 _free_data(E_Config_Dialog *cfd __UNUSED__, E_Config_Dialog_Data *cfdata)
141 EINA_LIST_FREE(cfdata->types, cft)
144 eina_list_free(cfdata->selected.loaded);
145 eina_list_free(cfdata->selected.unloaded);
150 _basic_create(E_Config_Dialog *cfd, Evas *evas, E_Config_Dialog_Data *cfdata)
153 Evas_Object *of, *ol;
155 cfdata->evas = e_win_evas_get(cfd->dia->win);
157 of = e_widget_table_add(evas, 0);
159 cfdata->o_toolbar = e_widget_toolbar_add(evas, 32 * e_scale, 32 * e_scale);
160 e_widget_toolbar_scrollable_set(cfdata->o_toolbar, 1);
161 _fill_cat_list(cfdata);
162 e_widget_table_object_append(of, cfdata->o_toolbar, 0, 0, 2, 1, 1, 1, 1, 0);
164 cfdata->l_modules = e_widget_ilist_add(evas, 32 * e_scale, 32 * e_scale, NULL);
165 e_widget_ilist_multi_select_set(cfdata->l_modules, EINA_TRUE);
166 e_widget_ilist_go(cfdata->l_modules);
167 e_widget_size_min_get(cfdata->l_modules, &mw, &mh);
168 if (mw < (200 * e_scale)) mw = 200 * e_scale;
169 if (mh < (100 * e_scale)) mh = 100 * e_scale;
170 e_widget_size_min_set(cfdata->l_modules, mw, mh);
171 e_widget_on_change_hook_set(cfdata->l_modules,
172 _widget_list_selection_changed, cfdata);
173 e_widget_table_object_append(of, cfdata->l_modules, 0, 1, 2, 1, 1, 1, 1, 1);
175 ol = e_widget_button_add(evas, _("Load"), NULL, _btn_cb_load, cfdata, NULL);
177 e_widget_disabled_set(ol, 1);
178 e_widget_table_object_append(of, ol, 0, 2, 1, 1, 1, 1, 1, 0);
180 ol = e_widget_button_add(evas, _("Unload"), NULL, _btn_cb_unload, cfdata, NULL);
181 cfdata->b_unload = ol;
182 e_widget_disabled_set(ol, 1);
183 e_widget_table_object_append(of, ol, 1, 2, 1, 1, 1, 1, 1, 0);
185 ol = e_widget_textblock_add(evas);
186 e_widget_size_min_set(ol, (200 * e_scale), 40 * e_scale);
188 e_widget_table_object_append(of, ol, 0, 3, 2, 1, 1, 0, 1, 0);
190 e_dialog_resizable_set(cfd->dia, 1);
191 e_util_win_auto_resize_fill(cfd->dia->win);
192 e_win_centered_set(cfd->dia->win, 1);
194 e_widget_focus_set(cfdata->o_toolbar, 1);
195 e_widget_toolbar_item_select(cfdata->o_toolbar, 0);
201 _fill_cat_list(E_Config_Dialog_Data *cfdata)
208 evas_event_freeze(cfdata->evas);
211 for (itr = _types; itr->key_len > 0; itr++)
213 cft = _cftype_find(cfdata, itr->key, itr->name, itr->icon);
216 WRN("CFT MISSING!!! key(%s) name(%s) icon(%s)", itr->key, itr->name, itr->icon);
219 icon = e_icon_add(cfdata->evas);
222 if (!e_util_icon_theme_set(icon, cft->icon))
224 evas_object_del(icon);
229 e_widget_toolbar_item_append(cfdata->o_toolbar, icon, _(cft->name),
230 _toolbar_select_cb, cfdata, cft);
233 e_widget_size_min_get(cfdata->o_toolbar, &w, &h);
234 e_widget_size_min_set(cfdata->o_toolbar, w, h);
237 evas_event_thaw(cfdata->evas);
241 _list_item_append(E_Config_Dialog_Data *cfdata, CFModule *cfm)
243 Evas_Object *icon, *end;
249 icon = e_icon_add(cfdata->evas);
252 if (!e_util_icon_theme_set(icon, cfm->icon))
256 char *dir = ecore_file_dir_get(cfm->orig_path);
259 snprintf(buf, sizeof(buf), "%s/%s.edj", dir, cfm->icon);
262 e_icon_file_edje_set(icon, buf, "icon");
266 evas_object_del(icon);
273 end = edje_object_add(cfdata->evas);
276 if (e_theme_edje_object_set(end, "base/theme/widgets",
277 "e/widgets/ilist/toggle_end"))
280 _module_end_state_apply(cfm);
284 EINA_LOG_ERR("your theme is missing 'e/widgets/ilist/toggle_end'!");
285 evas_object_del(end);
290 e_widget_ilist_append_full(cfdata->l_modules, icon, end,
291 cfm->name, NULL, cfm, NULL);
295 _toolbar_select_cb(void *data, void *data2)
297 CFType *cft, *cft_cat;
298 E_Config_Dialog_Data *cfdata;
304 if (!cfdata || !cft_cat) return;
306 eina_list_free(cfdata->selected.loaded);
307 eina_list_free(cfdata->selected.unloaded);
308 cfdata->selected.loaded = NULL;
309 cfdata->selected.unloaded = NULL;
310 e_widget_disabled_set(cfdata->b_load, EINA_TRUE);
311 e_widget_disabled_set(cfdata->b_unload, EINA_TRUE);
312 e_widget_textblock_markup_set(cfdata->o_desc, _("No modules selected."));
314 evas_event_freeze(evas_object_evas_get(cfdata->l_modules));
316 e_widget_ilist_freeze(cfdata->l_modules);
317 e_widget_ilist_clear(cfdata->l_modules);
319 EINA_LIST_FOREACH(cfdata->types, l_type, cft)
324 if (strcmp(cft->key, cft_cat->key))
327 EINA_LIST_FOREACH(cft->modules, l_module, cfm)
328 _list_item_append(cfdata, cfm);
331 e_widget_ilist_go(cfdata->l_modules);
332 e_widget_size_min_get(cfdata->l_modules, &w, &h);
333 e_widget_size_min_set(cfdata->l_modules, w, h);
334 e_widget_ilist_thaw(cfdata->l_modules);
336 evas_event_thaw(evas_object_evas_get(cfdata->l_modules));
340 _module_new(const char *short_name, const Efreet_Desktop *desk)
342 CFModule *cfm = E_NEW(CFModule, 1);
344 if (!cfm) return NULL;
345 cfm->short_name = eina_stringshare_add(short_name);
348 cfm->name = eina_stringshare_add(desk->name);
350 cfm->name = eina_stringshare_ref(cfm->short_name);
352 cfm->icon = eina_stringshare_add(desk->icon);
353 cfm->comment = eina_stringshare_add(desk->comment);
354 cfm->orig_path = eina_stringshare_add(desk->orig_path);
359 _module_free(CFModule *cfm)
361 eina_stringshare_del(cfm->short_name);
362 eina_stringshare_del(cfm->name);
363 eina_stringshare_del(cfm->icon);
364 eina_stringshare_del(cfm->comment);
365 eina_stringshare_del(cfm->orig_path);
370 _module_end_state_apply(CFModule *cfm)
374 if (!cfm->end) return;
375 sig = cfm->enabled ? "e,state,checked" : "e,state,unchecked";
376 edje_object_signal_emit(cfm->end, sig, "e");
380 _cftype_find(E_Config_Dialog_Data *cfdata, const char *key, const char *name, const char *icon)
385 EINA_LIST_FOREACH(cfdata->types, l, cft)
386 if ((!strcmp(cft->key, key)) && (!strcmp(cft->name, name)) && (!strcmp(cft->icon, icon))) return cft;
391 _cftype_new(const char *key, const char *name, const char *icon)
393 CFType *cft = E_NEW(CFType, 1);
395 if (!cft) return NULL;
396 cft->key = eina_stringshare_add(key);
397 cft->name = eina_stringshare_add(name);
398 cft->icon = eina_stringshare_add(icon);
399 //INF("CFT NEW: key(%s) name(%s) icon(%s)", key, name, icon);
404 _cftype_free(CFType *cft)
408 assert(cft->modules_hash == NULL); // must do it before calling this function
409 EINA_LIST_FREE(cft->modules, cfm)
412 eina_stringshare_del(cft->key);
413 eina_stringshare_del(cft->name);
414 eina_stringshare_del(cft->icon);
419 _cftype_new_from_key(const char *key)
422 char name[1024], icon[1024];
425 if (!key) return NULL;
427 key_len = strlen(key);
428 for (itr = _types; itr->key_len > 0; itr++)
430 if (key_len != itr->key_len) continue;
431 if (strcmp(itr->key, key) != 0) continue;
432 return _cftype_new(itr->key, itr->name, itr->icon);
435 if ((key_len + 1) >= sizeof(name)) return NULL;
436 if ((key_len + sizeof("enlightenment/")) >= sizeof(icon)) return NULL;
438 memcpy(name, key, key_len + 1);
439 name[0] = toupper(name[0]);
441 memcpy(icon, "enlightenment/", sizeof("enlightenment/") - 1);
442 memcpy(icon + sizeof("enlightenment/") - 1, key, key_len + 1);
444 return _cftype_new(key, name, icon);
448 _load_modules(const char *dir, Eina_Hash *types_hash)
451 char modpath[PATH_MAX];
455 modpathlen = snprintf(modpath, sizeof(modpath), "%s/", dir);
456 if (modpathlen >= (int)sizeof(modpath)) return;
458 files = ecore_file_ls(dir);
459 EINA_LIST_FREE(files, mod)
461 Efreet_Desktop *desk;
467 snprintf(modpath + modpathlen, sizeof(modpath) - modpathlen,
468 "%s/module.desktop", mod);
469 if (!ecore_file_exists(modpath)) goto end_mod;
470 if (!(desk = efreet_desktop_new(modpath))) goto end_mod;
473 type = eina_hash_find(desk->x, "X-Enlightenment-ModuleType");
476 if (!type) type = "utils"; // todo: warn?
478 cft = eina_hash_find(types_hash, type);
481 new_type = EINA_FALSE;
482 if ((cft->modules_hash) &&
483 (eina_hash_find(cft->modules_hash, mod)))
488 cft = _cftype_new_from_key(type);
489 if (cft) new_type = EINA_TRUE;
490 else goto end_desktop;
493 cfm = _module_new(mod, desk);
496 if (new_type) _cftype_free(cft);
500 if (!cft->modules_hash)
501 cft->modules_hash = eina_hash_string_superfast_new(NULL);
502 if (!cft->modules_hash)
504 if (new_type) _cftype_free(cft);
508 eina_hash_direct_add(cft->modules_hash, cfm->short_name, cfm);
509 // TODO be paranoid about hash add failure, otherwise it will leak
511 cft->modules = eina_list_append(cft->modules, cfm);
512 // TODO be paranoid about list append failure, otherwise it will leak
513 cfm->module = e_module_find(mod);
515 cfm->enabled = e_module_enabled_get(cfm->module);
520 eina_hash_direct_add(types_hash, cft->key, cft);
521 // TODO be paranoid about hash add failure, otherwise it will leak
524 efreet_desktop_free(desk);
531 _modules_list_sort(const void *data1, const void *data2)
533 const CFModule *m1 = data1, *m2 = data2;
534 return strcmp(m1->name, m2->name);
538 _types_list_create_foreach_cb(const Eina_Hash *hash __UNUSED__, const void *key __UNUSED__, void *data, void *fdata)
540 E_Config_Dialog_Data *cfdata = fdata;
543 // otherwise it should not be here
544 assert(cft->modules);
545 assert(cft->modules_hash);
547 eina_hash_free(cft->modules_hash);
548 cft->modules_hash = NULL;
550 cft->modules = eina_list_sort(cft->modules, -1, _modules_list_sort);
551 cfdata->types = eina_list_append(cfdata->types, cft);
552 // TODO be paranoid about list append failure, otherwise leaks memory
557 _types_list_sort(const void *data1, const void *data2)
559 const CFType *t1 = data1, *t2 = data2;
560 return strcmp(t1->name, t2->name);
564 _widget_list_selection_changed(void *data, Evas_Object *obj __UNUSED__)
566 E_Config_Dialog_Data *cfdata = data;
568 const E_Ilist_Item *it;
569 CFModule *cfm = NULL;
570 const char *description;
572 cfdata->selected.loaded = eina_list_free(cfdata->selected.loaded);
573 cfdata->selected.unloaded = eina_list_free(cfdata->selected.unloaded);
575 EINA_LIST_FOREACH(e_widget_ilist_selected_items_get(cfdata->l_modules), l, it)
577 cfm = e_widget_ilist_item_data_get(it);
581 cfdata->selected.loaded =
582 eina_list_append(cfdata->selected.loaded, cfm);
583 e_widget_disabled_set(cfdata->b_unload, 0);
584 e_widget_disabled_set(cfdata->b_load, 1);
588 cfdata->selected.unloaded =
589 eina_list_append(cfdata->selected.unloaded, cfm);
590 e_widget_disabled_set(cfdata->b_load, 0);
591 e_widget_disabled_set(cfdata->b_unload, 1);
596 if ((cfm) && (eina_list_count(cfdata->selected.loaded) + eina_list_count(cfdata->selected.unloaded) == 1))
597 description = cfm->comment;
598 else if (eina_list_count(cfdata->selected.loaded) + eina_list_count(cfdata->selected.unloaded) > 1)
599 description = _("More than one module selected.");
601 description = _("No modules selected.");
603 e_widget_textblock_markup_set(cfdata->o_desc, description);
607 _btn_cb_unload(void *data, void *data2 __UNUSED__)
609 E_Config_Dialog_Data *cfdata = data;
612 EINA_LIST_FREE(cfdata->selected.loaded, cfm)
615 cfm->module = e_module_find(cfm->short_name);
619 e_module_disable(cfm->module);
620 cfm->enabled = e_module_enabled_get(cfm->module);
623 _module_end_state_apply(cfm);
624 cfdata->selected.unloaded = eina_list_append(cfdata->selected.unloaded, cfm);
627 e_widget_disabled_set(cfdata->b_unload, 1);
628 e_widget_disabled_set(cfdata->b_load, 0);
632 _btn_cb_load(void *data, void *data2 __UNUSED__)
634 E_Config_Dialog_Data *cfdata = data;
637 EINA_LIST_FREE(cfdata->selected.unloaded, cfm)
640 cfm->module = e_module_find(cfm->short_name);
642 cfm->module = e_module_new(cfm->short_name);
646 e_module_enable(cfm->module);
647 cfm->enabled = e_module_enabled_get(cfm->module);
650 _module_end_state_apply(cfm);
651 cfdata->selected.loaded = eina_list_append(cfdata->selected.loaded, cfm);
654 e_widget_disabled_set(cfdata->b_load, 1);
655 e_widget_disabled_set(cfdata->b_unload, 0);