Hello,
Please find attached a patch which will add an "Advanced" dialog to the
Theme configuration panel.
The advanced dialog will allow a user to associate individual themed
elements of E with any theme installed on the machine. For example,
your borders could come from Codito, your menus from Gant, your icons
from Kor, your winlist from carbon-14, and your pager from Blue-eyed.
Example:
http://www.ravenlock.us/pics/adv_theme.png
Notice in the above image there are many elements from many different
themes.
Given this functionality you can "roll your own" theme. Note that this
is *not* new functionality. This has always been available
(enlightenment_remote), just not very obvious or easy to use. This gui
will make it easier for the average user to customize their E
environment a little more.
For what its worth (a little speculation here)... it may be possible for
themers to actually make "themes" that only consist of a particular
element, say a menu, or a set of icons, or just borders, or maybe a
fancy winlist.... and people could then pick and choose whichever they
like. You could have a library of theme elements, and simply pick what
you need.
I'm hoping a few people will patch their systems and give it a spin, and
then provide feedback.
I'll be out of town this weekend... most likely will be completely
unplugged. I'll catch up on any feedback as soon as I return (monday
evening).
--
Regards,
Ravenlock
Index: e17/apps/e/src/bin/e_int_config_theme.c
===================================================================
RCS file: /cvs/e/e17/apps/e/src/bin/e_int_config_theme.c,v
retrieving revision 1.50
diff -u -r1.50 e_int_config_theme.c
--- e17/apps/e/src/bin/e_int_config_theme.c 2 May 2007 18:38:23 -0000
1.50
+++ e17/apps/e/src/bin/e_int_config_theme.c 26 May 2007 03:33:23 -0000
@@ -9,10 +9,15 @@
static void _fill_data (E_Config_Dialog_Data *cfdata);
static int _basic_apply_data (E_Config_Dialog *cfd,
E_Config_Dialog_Data *cfdata);
static Evas_Object *_basic_create_widgets (E_Config_Dialog *cfd, Evas *evas,
E_Config_Dialog_Data *cfdata);
+static int _advanced_apply_data (E_Config_Dialog *cfd,
E_Config_Dialog_Data *cfdata);
+static Evas_Object *_advanced_create_widgets (E_Config_Dialog *cfd, Evas
*evas, E_Config_Dialog_Data *cfdata);
+static Evas_List *_get_theme_categories_list();
struct _E_Config_Dialog_Data
{
E_Config_Dialog *cfd;
+
+ /* Basic */
Evas_Object *o_frame;
Evas_Object *o_fm;
Evas_Object *o_up_button;
@@ -20,8 +25,13 @@
Evas_Object *o_personal;
Evas_Object *o_system;
int fmdir;
-
char *theme;
+
+ /* Advanced */
+ Evas_Object *o_categories_ilist;
+ Evas_Object *o_files_ilist;
+ int personal_file_count;
+ Evas_List *theme_list;
/* Dialog */
E_Win *win_import;
@@ -40,6 +50,8 @@
v->free_cfdata = _free_data;
v->basic.apply_cfdata = _basic_apply_data;
v->basic.create_widgets = _basic_create_widgets;
+ v->advanced.apply_cfdata = _advanced_apply_data;
+ v->advanced.create_widgets = _advanced_create_widgets;
v->override_auto_apply = 1;
cfd = e_config_dialog_new(con,
_("Theme Selector"),
@@ -306,7 +318,9 @@
}
}
}
-
+
+ cfdata->theme_list = _get_theme_categories_list();
+
snprintf(path, sizeof(path), "%s/data/themes", e_prefix_data_get());
if (!strncmp(cfdata->theme, path, strlen(path)))
cfdata->fmdir = 1;
@@ -330,6 +344,7 @@
if (cfdata->win_import)
e_int_config_theme_del(cfdata->win_import);
+ evas_list_free(cfdata->theme_list);
E_FREE(cfdata->theme);
E_FREE(cfdata);
}
@@ -374,8 +389,8 @@
else
snprintf(path, sizeof(path), "%s/.e/e/themes", homedir);
+ cfdata->o_fm = NULL;
o = e_fm2_add(evas);
- cfdata->o_fm = o;
memset(&fmc, 0, sizeof(E_Fm2_Config));
fmc.view.mode = E_FM2_VIEW_MODE_LIST;
fmc.view.open_dirs_in_place = 1;
@@ -413,6 +428,7 @@
e_fm2_pan_get,
e_fm2_pan_max_get,
e_fm2_pan_child_size_get);
+ cfdata->o_fm = o;
cfdata->o_frame = of;
e_widget_min_size_set(of, 160, 160);
e_widget_table_object_append(ol, of, 0, 2, 1, 1, 1, 1, 1, 1);
@@ -463,4 +479,586 @@
a = e_action_find("restart");
if ((a) && (a->func.go)) a->func.go(NULL, NULL);
return 1; /* Apply was OK */
+}
+
+/*
+ * --------------------------------------
+ * --- A D V A N C E D S U P P O R T ---
+ * --------------------------------------
+ */
+
+static int
+_cb_sort(void *data1, void *data2)
+{
+ const char *d1, *d2;
+
+ d1 = data1;
+ d2 = data2;
+ if (!d1) return 1;
+ if (!d2) return -1;
+
+ return strcmp(d1, d2);
+}
+
+static Evas_List *
+_get_theme_categories_list()
+{
+ Evas_List *themes, *tcl = NULL;
+ Evas_List *cats = NULL, *g = NULL, *cats2 = NULL;
+ const char *category;
+ Evas_List *all_parts;
+ char theme_dir[1024];
+
+ /* Setup some default theme categories */
+ cats = evas_list_append(cats, strdup("base/theme/about"));
+ cats = evas_list_append(cats, strdup("base/theme/borders"));
+ cats = evas_list_append(cats, strdup("base/theme/background"));
+ cats = evas_list_append(cats, strdup("base/theme/configure"));
+ cats = evas_list_append(cats, strdup("base/theme/dialog"));
+ cats = evas_list_append(cats, strdup("base/theme/dnd"));
+ cats = evas_list_append(cats, strdup("base/theme/error"));
+ cats = evas_list_append(cats, strdup("base/theme/exebuf"));
+ cats = evas_list_append(cats, strdup("base/theme/fileman"));
+ cats = evas_list_append(cats, strdup("base/theme/gadman"));
+ cats = evas_list_append(cats, strdup("base/theme/icons"));
+ cats = evas_list_append(cats, strdup("base/theme/menus"));
+ cats = evas_list_append(cats, strdup("base/theme/modules"));
+ cats = evas_list_append(cats, strdup("base/theme/modules/pager"));
+ cats = evas_list_append(cats, strdup("base/theme/modules/ibar"));
+ cats = evas_list_append(cats, strdup("base/theme/modules/ibox"));
+ cats = evas_list_append(cats, strdup("base/theme/modules/clock"));
+ cats = evas_list_append(cats, strdup("base/theme/modules/battery"));
+ cats = evas_list_append(cats, strdup("base/theme/modules/cpufreq"));
+ cats = evas_list_append(cats, strdup("base/theme/modules/start"));
+ cats = evas_list_append(cats, strdup("base/theme/modules/temperature"));
+ cats = evas_list_append(cats, strdup("base/theme/pointer"));
+ cats = evas_list_append(cats, strdup("base/theme/shelf"));
+ cats = evas_list_append(cats, strdup("base/theme/transitions"));
+ cats = evas_list_append(cats, strdup("base/theme/widgets"));
+ cats = evas_list_append(cats, strdup("base/theme/winlist"));
+
+ /*
+ * Get a list of registered themes.
+ * Add those which are not in the above list
+ */
+ for (g = e_theme_category_list(); g; g = g->next)
+ {
+ const char *c;
+ c = g->data;
+ if (!c) continue;
+
+ cats2 = cats;
+ while (cats2)
+ {
+ if (!strcmp(c, cats2->data))
+ break;
+ cats2 = cats2->next;
+ }
+ if (!cats2)
+ cats = evas_list_append(cats, strdup(c));
+ }
+ cats = evas_list_sort(cats, -1, _cb_sort);
+
+ while (cats)
+ {
+ E_Config_Theme *theme, *newtheme = NULL;
+
+ category = cats->data;
+ /* Not interested in adding "base" and "base/theme" */
+ if (strcmp(category, "base") && strcmp(category, "base/theme"))
+ {
+ newtheme = (E_Config_Theme *)malloc(sizeof(E_Config_Theme));
+ if (!newtheme) break;
+ newtheme->category = strdup(category);
+ newtheme->file = NULL;
+
+ for (themes = e_config->themes; themes; themes = themes->next)
+ {
+ theme = themes->data;
+ if (!strcmp(category + 5, theme->category))
+ {
+ newtheme->file = strdup(theme->file);
+ }
+ }
+ tcl = evas_list_append(tcl, newtheme);
+ }
+ cats = cats->next;
+ }
+ cats = evas_list_free(cats);
+
+ return tcl;
+}
+
+static void
+_cb_adv_categories_change(void *data, Evas_Object *obj)
+{
+ E_Config_Dialog_Data *cfdata;
+ const char *label = NULL;
+ const char *file = NULL;
+ char category[256];
+ Evas_List *themes = NULL, *l;
+ Evas_Object *ic = NULL;
+ int n;
+
+ cfdata = data;
+ if (!cfdata) return;
+
+ label = e_widget_ilist_selected_label_get(cfdata->o_categories_ilist);
+ if (!label) return;
+
+ n = e_widget_ilist_selected_get(cfdata->o_categories_ilist);
+ ic = e_widget_ilist_nth_icon_get(cfdata->o_categories_ilist, n);
+ if (!ic) return;
+
+ snprintf(category, sizeof(category), "base/theme/%s", label);
+ for (themes = cfdata->theme_list; themes; themes = themes->next)
+ {
+ E_Config_Theme *t;
+
+ t = themes->data;
+ if (!strcmp(category, t->category) && (t->file))
+ {
+ file = strdup(t->file);
+ break;
+ }
+ }
+ if (!file) return;
+
+ for (n = 0, l = e_widget_ilist_items_get(cfdata->o_files_ilist); l; l =
l->next, n++)
+ {
+ if (strstr(file, e_widget_ilist_nth_label_get(cfdata->o_files_ilist,
n)))
+ {
+ e_widget_ilist_selected_set(cfdata->o_files_ilist, n);
+ break;
+ }
+ }
+
+ free((void *)file);
+ free((void *)label);
+}
+
+static void
+_cb_adv_theme_change(void *data, Evas_Object *obj)
+{
+ E_Config_Dialog_Data *cfdata;
+ const char *label = NULL;
+ char theme[4096];
+ int n;
+
+ cfdata = data;
+ if (!cfdata) return;
+
+ n = e_widget_ilist_selected_get(cfdata->o_files_ilist);
+ label = e_widget_ilist_selected_label_get(cfdata->o_files_ilist);
+ if (label)
+ {
+ if (n > cfdata->personal_file_count)
+ snprintf(theme, sizeof(theme), "%s/data/themes/%s.edj",
+ e_prefix_data_get(), label);
+ else
+ snprintf(theme, sizeof(theme), "%s/.e/e/themes/%s.edj",
+ e_user_homedir_get(), label);
+ e_widget_preview_edje_set(cfdata->o_preview, theme,
+ "e/desktop/background");
+ }
+ free((void *)label);
+}
+
+static int
+_theme_file_used(Evas_List *tlist, const char *filename)
+{
+ E_Config_Theme *theme;
+
+ while (tlist)
+ {
+ theme = tlist->data;
+ if (theme->file && strstr(theme->file, filename))
+ {
+ return 1;
+ }
+ tlist = tlist->next;
+ }
+
+ return 0;
+}
+
+static int
+_ilist_files_add(E_Config_Dialog_Data *cfdata, const char *header, const char
*dir)
+{
+ DIR *d = NULL;
+ struct dirent *dentry = NULL;
+ Evas_List *themefiles = NULL;
+ int count;
+ char themename[256];
+ Evas_Object *o;
+ Evas *evas;
+
+ o = cfdata->o_files_ilist;
+ e_widget_ilist_header_append(o, NULL, header);
+ evas = evas_object_evas_get(o);
+
+ d = opendir(dir);
+ if (d)
+ {
+ while ((dentry = readdir(d)) != NULL)
+ {
+ if (strstr(dentry->d_name,".edj") != NULL)
+ {
+ strncpy(themename, dentry->d_name, strlen(dentry->d_name)-3);
+ themename[strlen(dentry->d_name)-4] = '\0';
+ themefiles = evas_list_append(themefiles, strdup(themename));
+ }
+ }
+ closedir(d);
+ }
+
+ if (themefiles)
+ {
+ themefiles = evas_list_sort(themefiles, -1, _cb_sort);
+ count = evas_list_count(themefiles);
+
+ while (themefiles)
+ {
+ Evas_Object *ic = NULL;
+ if (_theme_file_used(cfdata->theme_list, themefiles->data))
+ {
+ ic = edje_object_add(evas);
+ e_util_edje_icon_set(ic, "enlightenment/themes");
+ }
+ e_widget_ilist_append(o, ic, themefiles->data, NULL, NULL, NULL);
+
+ themefiles = themefiles->next;
+ }
+ }
+
+ return count;
+}
+
+static void
+_fill_files_ilist(E_Config_Dialog_Data *cfdata)
+{
+ Evas *evas;
+ Evas_Object *o;
+ char theme_dir[4096], theme[256];
+
+ o = cfdata->o_files_ilist;
+ if (!o) return;
+
+ evas = evas_object_evas_get(o);
+ evas_event_freeze(evas);
+ edje_freeze();
+ e_widget_ilist_freeze(o);
+ e_widget_ilist_clear(o);
+
+ /* Grab the "Personal" themes. */
+ snprintf(theme_dir, sizeof(theme_dir), "%s/.e/e/themes",
+ e_user_homedir_get());
+ cfdata->personal_file_count = _ilist_files_add(cfdata, _("Personal"),
+ theme_dir);
+
+ /* Grab the "System" themes. */
+ snprintf(theme_dir, sizeof(theme_dir),
+ "%s/data/themes", e_prefix_data_get());
+ _ilist_files_add(cfdata, _("System"), theme_dir);
+
+ e_widget_ilist_go(o);
+ e_widget_ilist_thaw(o);
+ edje_thaw();
+ evas_event_thaw(evas);
+}
+
+static void
+_fill_categories_ilist(E_Config_Dialog_Data *cfdata)
+{
+ Evas *evas;
+ Evas_List *themes;
+ E_Config_Theme *theme;
+ Evas_Object *o;
+
+ o = cfdata->o_categories_ilist;
+ if (!o) return;
+
+ evas = evas_object_evas_get(o);
+ evas_event_freeze(evas);
+ edje_freeze();
+ e_widget_ilist_freeze(o);
+ e_widget_ilist_clear(o);
+
+ themes = cfdata->theme_list;
+ while (themes)
+ {
+ Evas_Object *ic = NULL;
+
+ theme = themes->data;
+ if (theme->file)
+ {
+ ic = edje_object_add(evas);
+ e_util_edje_icon_set(ic, "enlightenment/e");
+ }
+ e_widget_ilist_append(o, ic, theme->category + 11, NULL, NULL, NULL);
+ themes = themes->next;
+ }
+
+ e_widget_ilist_go(o);
+ e_widget_ilist_thaw(o);
+ edje_thaw();
+ evas_event_thaw(evas);
+}
+
+static void
+_cb_adv_btn_assign(void *data1, void *data2)
+{
+ Evas *evas;
+ E_Config_Dialog_Data *cfdata;
+ E_Config_Theme *newtheme, *t;
+ Evas_List *themes;
+ Evas_Object *ic = NULL, *oc = NULL, *of = NULL;
+ char buf[1024];
+ const char *label;
+ int n;
+
+ cfdata = data1;
+ if (!cfdata) return;
+
+ oc = cfdata->o_categories_ilist;
+ if (!oc) return;
+ of = cfdata->o_files_ilist;
+ if (!of) return;
+
+ evas = evas_object_evas_get(oc);
+ n = e_widget_ilist_selected_get(oc);
+ ic = edje_object_add(evas);
+ e_util_edje_icon_set(ic, "enlightenment/e");
+ e_widget_ilist_nth_icon_set(oc, n, ic);
+
+ newtheme = malloc(sizeof(E_Config_Theme));
+ if (!newtheme) return;
+
+ label = e_widget_ilist_selected_label_get(oc);
+ snprintf(buf, sizeof(buf), "base/theme/%s", label);
+ newtheme->category = strdup(buf);
+
+ n = e_widget_ilist_selected_get(of);
+ ic = edje_object_add(evas);
+ e_util_edje_icon_set(ic, "enlightenment/themes");
+ e_widget_ilist_nth_icon_set(of, n, ic);
+ label = e_widget_ilist_selected_label_get(of);
+ if (n > cfdata->personal_file_count)
+ snprintf(buf, sizeof(buf), "%s/data/themes/%s.edj",
+ e_prefix_data_get(), label);
+ else
+ snprintf(buf, sizeof(buf), "%s/.e/e/themes/%s.edj",
+ e_user_homedir_get(), label);
+ newtheme->file = strdup(buf);
+ free((void *)label);
+
+ for (themes = cfdata->theme_list; themes; themes = themes->next)
+ {
+ char * filename;
+
+ t = themes->data;
+ if (!strcmp(t->category, newtheme->category))
+ {
+ if (t->file)
+ {
+ filename = strdup(t->file);
+ free((void *)(t->file));
+ t->file = NULL;
+ if (!_theme_file_used(cfdata->theme_list, filename))
+ {
+ for (n = 0; n < e_widget_ilist_count(of); n++)
+ if (strstr(filename, e_widget_ilist_nth_label_get(of,
n)))
+ e_widget_ilist_nth_icon_set(of, n, NULL);
+ }
+ free(filename);
+ }
+ t->file = strdup(newtheme->file);
+ break;
+ }
+ }
+ if (!themes)
+ cfdata->theme_list = evas_list_append(cfdata->theme_list, newtheme);
+
+ return;
+}
+
+static void
+_cb_adv_btn_clear(void *data1, void *data2)
+{
+ E_Config_Dialog_Data *cfdata;
+ E_Config_Theme *t;
+ Evas_List *themes;
+ Evas_Object *oc = NULL, *of = NULL;
+ char cat[1024];
+ const char *label;
+ int n;
+
+ cfdata = data1;
+ if (!cfdata) return;
+
+ oc = cfdata->o_categories_ilist;
+ if (!oc) return;
+ of = cfdata->o_files_ilist;
+ if (!of) return;
+
+ n = e_widget_ilist_selected_get(oc);
+ e_widget_ilist_nth_icon_set(oc, n, NULL);
+
+ label = e_widget_ilist_selected_label_get(oc);
+ snprintf(cat, sizeof(cat), "base/theme/%s", label);
+ free((void *)label);
+
+ for (themes = cfdata->theme_list; themes; themes = themes->next)
+ {
+ t = themes->data;
+ if (!strcmp(t->category, cat))
+ {
+ if (t->file)
+ {
+ free((void *)(t->file));
+ t->file = NULL;
+ }
+ break;
+ }
+ }
+
+ if (!_theme_file_used(cfdata->theme_list,
e_widget_ilist_selected_label_get(of)))
+ {
+ n = e_widget_ilist_selected_get(of);
+ e_widget_ilist_nth_icon_set(of, n, NULL);
+ }
+
+ return;
+}
+
+static void
+_cb_adv_btn_clearall(void *data1, void *data2)
+{
+ E_Config_Dialog_Data *cfdata;
+ E_Config_Theme *t;
+ Evas_List *themes;
+ Evas_Object *oc = NULL, *of = NULL;
+ int n;
+
+ cfdata = data1;
+ if (!cfdata) return;
+
+ oc = cfdata->o_categories_ilist;
+ if (!oc) return;
+ of = cfdata->o_files_ilist;
+ if (!of) return;
+
+ for (n = 0; n < e_widget_ilist_count(oc); n++)
+ e_widget_ilist_nth_icon_set(oc, n, NULL);
+ for (n = 0; n < e_widget_ilist_count(of); n++)
+ e_widget_ilist_nth_icon_set(of, n, NULL);
+
+ for (themes = cfdata->theme_list; themes; themes = themes->next)
+ {
+ t = themes->data;
+ if (t->file)
+ {
+ free((void *)(t->file));
+ t->file = NULL;
+ }
+ }
+
+ return;
+}
+
+static Evas_Object *
+_advanced_create_widgets(E_Config_Dialog *cfd, Evas *evas,
E_Config_Dialog_Data *cfdata)
+{
+ Evas_Object *ot, *of, *ob, *oa, *ol;
+ int mw, mh;
+ E_Zone *zone;
+
+ zone = e_zone_current_get(cfd->con);
+ ot = e_widget_table_add(evas, 0);
+
+ of = e_widget_framelist_add(evas, _("Theme Categories"), 0);
+ ob = e_widget_ilist_add(evas, 16, 16, NULL);
+ e_widget_on_change_hook_set(ob, _cb_adv_categories_change, cfdata);
+ cfdata->o_categories_ilist = ob;
+ e_widget_ilist_multi_select_set(ob, 0);
+ e_widget_min_size_set(ob, 150, 250);
+ e_widget_framelist_object_append(of, ob);
+ e_widget_table_object_append(ot, of, 0, 0, 1, 1, 1, 1, 1, 1);
+
+ of = e_widget_framelist_add(evas, _("Themes"), 0);
+ ob = e_widget_ilist_add(evas, 16, 16, NULL);
+ e_widget_on_change_hook_set(ob, _cb_adv_theme_change, cfdata);
+ cfdata->o_files_ilist = ob;
+ e_widget_ilist_multi_select_set(ob, 0);
+ e_widget_min_size_set(ob, 150, 250);
+ e_widget_framelist_object_append(of, ob);
+ e_widget_table_object_append(ot, of, 1, 0, 1, 1, 1, 1, 1, 1);
+
+ ol = e_widget_list_add(evas, 1, 1);
+ ob = e_widget_button_add(evas, _("Assign"), NULL, _cb_adv_btn_assign,
cfdata, NULL);
+ e_widget_list_object_append(ol, ob, 1, 0, 0.5);
+ ob = e_widget_button_add(evas, _("Clear"), NULL, _cb_adv_btn_clear, cfdata,
NULL);
+ e_widget_list_object_append(ol, ob, 1, 0, 0.5);
+ ob = e_widget_button_add(evas, _("Clear All"), NULL, _cb_adv_btn_clearall,
cfdata, NULL);
+ e_widget_list_object_append(ol, ob, 1, 0, 0.5);
+ e_widget_table_object_append(ot, ol, 0, 1, 1, 1, 1, 0, 1, 0);
+
+ of = e_widget_framelist_add(evas, _("Preview"), 0);
+ mw = 320;
+ mh = (mw * zone->h) / zone->w;
+ oa = e_widget_aspect_add(evas, mw, mh);
+ ob = e_widget_preview_add(evas, mw, mh);
+ cfdata->o_preview = ob;
+ if (cfdata->theme)
+ e_widget_preview_edje_set(ob, cfdata->theme, "e/desktop/background");
+ e_widget_aspect_child_set(oa, ob);
+ e_widget_framelist_object_append(of, oa);
+ e_widget_table_object_append(ot, of, 2, 0, 1, 1, 1, 1, 1, 1);
+
+ _fill_files_ilist(cfdata);
+ _fill_categories_ilist(cfdata);
+
+ e_widget_ilist_selected_set(cfdata->o_files_ilist, 1);
+ e_widget_ilist_selected_set(cfdata->o_categories_ilist, 0);
+
+ e_dialog_resizable_set(cfd->dia, 1);
+ return ot;
+}
+
+static int
+_advanced_apply_data(E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata)
+{
+ Evas_List *themes, *ec_themes;
+ E_Action *a;
+
+ themes = cfdata->theme_list;
+ while (themes)
+ {
+ E_Config_Theme *theme, *ec_theme;
+
+ theme = themes->data;
+ for (ec_themes = e_config->themes; ec_themes; ec_themes =
ec_themes->next)
+ {
+ ec_theme = ec_themes->data;
+ if (!strcmp(theme->category + 5, ec_theme->category))
+ {
+ if (theme->file)
+ e_theme_config_set(theme->category + 5, theme->file);
+ else
+ e_theme_config_remove(theme->category + 5);
+ break;
+ }
+ }
+ if ((!ec_themes) && (theme->file))
+ e_theme_config_set(theme->category + 5, theme->file);
+
+ themes = themes->next;
+ }
+
+ e_config_save_queue();
+
+ a = e_action_find("restart");
+ if ((a) && (a->func.go)) a->func.go(NULL, NULL);
+
+ return 1;
}
-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
enlightenment-devel mailing list
enlightenment-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/enlightenment-devel