From dad9160ffa748bdf69a45ee7f1f2dfdd23225f4a Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Thu, 3 Mar 2016 09:42:11 -0500 Subject: [PATCH] add new time module with clock gadgets this is the successor to the clock module/gadget. it uses separate config files and theme groups from the "clock" module. --- configure.ac | 2 + src/bin/e_module.c | 1 + src/modules/Makefile.mk | 1 + src/modules/Makefile_time.mk | 25 ++ src/modules/time/clock.c | 507 +++++++++++++++++++++++ src/modules/time/clock.h | 93 +++++ src/modules/time/config.c | 627 +++++++++++++++++++++++++++++ src/modules/time/e-module-time.edj | Bin 0 -> 14062 bytes src/modules/time/mod.c | 142 +++++++ src/modules/time/module.desktop.in | 7 + src/modules/time/time.c | 354 ++++++++++++++++ 11 files changed, 1759 insertions(+) create mode 100644 src/modules/Makefile_time.mk create mode 100644 src/modules/time/clock.c create mode 100644 src/modules/time/clock.h create mode 100644 src/modules/time/config.c create mode 100644 src/modules/time/e-module-time.edj create mode 100644 src/modules/time/mod.c create mode 100644 src/modules/time/module.desktop.in create mode 100644 src/modules/time/time.c diff --git a/configure.ac b/configure.ac index 7b286c626..1ac583131 100644 --- a/configure.ac +++ b/configure.ac @@ -925,6 +925,7 @@ AC_E_OPTIONAL_MODULE([policy_mobile], true) AC_E_OPTIONAL_MODULE([geolocation], true) AC_E_OPTIONAL_MODULE([xwayland], $have_wayland, [CHECK_MODULE_XWAYLAND]) AC_E_OPTIONAL_MODULE([wireless], true) +AC_E_OPTIONAL_MODULE([time], true) if test "x${HAVE_WL_X11}" != "xyes" && test "x${have_wayland}" = "xyes" && test "x${HAVE_XWAYLAND}" != "xyes"; then AC_DEFINE_UNQUOTED([HAVE_WAYLAND_ONLY],[1],[enable wayland-only version of enlightenment]) @@ -1127,6 +1128,7 @@ src/modules/music-control/module.desktop src/modules/packagekit/module.desktop src/modules/wl_desktop_shell/module.desktop src/modules/wireless/module.desktop +src/modules/time/module.desktop data/xsession/enlightenment.desktop data/etc/sysactions.conf data/units/enlightenment.service diff --git a/src/bin/e_module.c b/src/bin/e_module.c index 945788de6..25ec3a7b1 100644 --- a/src/bin/e_module.c +++ b/src/bin/e_module.c @@ -1024,6 +1024,7 @@ _e_module_whitelist_check(void) "teamwork", "temperature", "tiling", + "time", "winlist", "wireless", "wizard", diff --git a/src/modules/Makefile.mk b/src/modules/Makefile.mk index bb618da1e..0962f9ee9 100644 --- a/src/modules/Makefile.mk +++ b/src/modules/Makefile.mk @@ -129,3 +129,4 @@ include src/modules/Makefile_policy_mobile.mk include src/modules/Makefile_geolocation.mk include src/modules/Makefile_wireless.mk +include src/modules/Makefile_time.mk diff --git a/src/modules/Makefile_time.mk b/src/modules/Makefile_time.mk new file mode 100644 index 000000000..14477c1b5 --- /dev/null +++ b/src/modules/Makefile_time.mk @@ -0,0 +1,25 @@ +EXTRA_DIST += src/modules/time/module.desktop.in \ +src/modules/time/e-module-time.edj +if USE_MODULE_TIME +timedir = $(MDIR)/time +time_DATA = src/modules/time/e-module-time.edj \ + src/modules/time/module.desktop + + +timepkgdir = $(MDIR)/time/$(MODULE_ARCH) +timepkg_LTLIBRARIES = src/modules/time/module.la + +src_modules_time_module_la_LIBADD = $(MOD_LIBS) +src_modules_time_module_la_CPPFLAGS = $(MOD_CPPFLAGS) +src_modules_time_module_la_LDFLAGS = $(MOD_LDFLAGS) +src_modules_time_module_la_SOURCES = \ +src/modules/time/clock.c \ +src/modules/time/clock.h \ +src/modules/time/config.c \ +src/modules/time/mod.c \ +src/modules/time/time.c + +PHONIES += time install-time +time: $(timepkg_LTLIBRARIES) $(time_DATA) +install-time: install-timeDATA install-timepkgLTLIBRARIES +endif diff --git a/src/modules/time/clock.c b/src/modules/time/clock.c new file mode 100644 index 000000000..1952413d1 --- /dev/null +++ b/src/modules/time/clock.c @@ -0,0 +1,507 @@ +#include "clock.h" + +EINTERN Config *time_config = NULL; +EINTERN Eina_List *clock_instances = NULL; +static Ecore_Timer *clock_timer; + +static void +_clock_calendar_month_update(Instance *inst) +{ + Evas_Object *od, *oi; + int x, y; + + oi = elm_layout_edje_get(inst->o_cal); + edje_object_part_text_set(oi, "e.text.month", inst->month); + edje_object_part_text_set(oi, "e.text.year", inst->year); + for (x = 0; x < 7; x++) + { + od = edje_object_part_table_child_get(oi, "e.table.daynames", x, 0); + edje_object_part_text_set(od, "e.text.label", inst->daynames[x]); + edje_object_message_signal_process(od); + if (inst->dayweekends[x][0]) + edje_object_signal_emit(od, "e,state,weekend", "e"); + else + edje_object_signal_emit(od, "e,state,weekday", "e"); + } + + for (y = 0; y < 6; y++) + { + for (x = 0; x < 7; x++) + { + char buf[32]; + + od = edje_object_part_table_child_get(oi, "e.table.days", x, y); + snprintf(buf, sizeof(buf), "%i", (int)inst->daynums[x][y]); + edje_object_part_text_set(od, "e.text.label", buf); + if (inst->dayweekends[x][y]) + edje_object_signal_emit(od, "e,state,weekend", "e"); + else + edje_object_signal_emit(od, "e,state,weekday", "e"); + if (inst->dayvalids[x][y]) + edje_object_signal_emit(od, "e,state,visible", "e"); + else + edje_object_signal_emit(od, "e,state,hidden", "e"); + if (inst->daytoday[x][y]) + edje_object_signal_emit(od, "e,state,today", "e"); + else + edje_object_signal_emit(od, "e,state,someday", "e"); + edje_object_message_signal_process(od); + } + } + edje_object_message_signal_process(oi); +} + +static void +_clock_month_prev_cb(void *data, Evas_Object *obj EINA_UNUSED, const char *emission EINA_UNUSED, const char *source EINA_UNUSED) +{ + Instance *inst = data; + inst->madj--; + time_instance_update(inst); + _clock_calendar_month_update(inst); +} + +static void +_clock_month_next_cb(void *data, Evas_Object *obj EINA_UNUSED, const char *emission EINA_UNUSED, const char *source EINA_UNUSED) +{ + Instance *inst = data; + inst->madj++; + time_instance_update(inst); + _clock_calendar_month_update(inst); +} + +static void +_clock_popup_dismissed(void *data EINA_UNUSED, Evas_Object *obj, void *info EINA_UNUSED) +{ + evas_object_del(obj); +} + +static void +_eval_instance_size(Instance *inst) +{ + Evas_Coord mw, mh; + int sw = 0, sh = 0; + Evas_Object *ed = elm_layout_edje_get(inst->o_clock); + + edje_object_size_min_get(ed, &mw, &mh); + + if ((mw < 1) || (mh < 1)) + { + if (edje_object_part_exists(ed, "e.sizer")) + { + edje_object_part_geometry_get(ed, "e.sizer", NULL, NULL, &mw, &mh); + } + else + { + Evas_Object *owner; + + owner = e_gadget_site_get(inst->o_clock); + switch (e_gadget_site_orient_get(owner)) + { + case E_GADGET_SITE_ORIENT_HORIZONTAL: + evas_object_geometry_get(owner, NULL, NULL, NULL, &sh); + break; + + case E_GADGET_SITE_ORIENT_VERTICAL: + evas_object_geometry_get(owner, NULL, NULL, &sw, NULL); + break; + + default: break; + } + + evas_object_resize(inst->o_clock, sw, sh); + edje_object_message_signal_process(ed); + + edje_object_parts_extends_calc(ed, NULL, NULL, &mw, &mh); + } + } + + if (mw < 4) mw = 4; + if (mh < 4) mh = 4; + + if (mw < sw) mw = sw; + if (mh < sh) mh = sh; + + evas_object_size_hint_aspect_set(inst->o_clock, EVAS_ASPECT_CONTROL_BOTH, mw, mh); +} + +static void +_clock_edje_init(Instance *inst, Evas_Object *o) +{ + char datestr[128]; + const char *digital[] = + { + "e/gadget/clock/digital", + "e/gadget/clock/digital/advanced", + }; + + time_datestring_format(inst, datestr, sizeof(datestr) - 1); + if (inst->cfg->digital_clock) + e_theme_edje_object_set(o, NULL, digital[inst->cfg->advanced]); + else + e_theme_edje_object_set(o, NULL, "e/gadget/clock/analog"); + if (inst->cfg->show_date) + elm_layout_signal_emit(o, "e,state,date,on", "e"); + else + elm_layout_signal_emit(o, "e,state,date,off", "e"); + if (inst->cfg->digital_24h) + elm_layout_signal_emit(o, "e,state,24h,on", "e"); + else + elm_layout_signal_emit(o, "e,state,24h,off", "e"); + if (inst->cfg->show_seconds) + elm_layout_signal_emit(o, "e,state,seconds,on", "e"); + else + elm_layout_signal_emit(o, "e,state,seconds,off", "e"); + + elm_object_part_text_set(o, "e.text.sub", datestr); + if (inst->cfg->timezone) + { + Edje_Message_String msg; + + msg.str = (char*)inst->cfg->timezone; + edje_object_message_send(elm_layout_edje_get(o), EDJE_MESSAGE_STRING, 1, &msg); + } + { + Edje_Message_String_Int msg; + msg.str = (char*)inst->cfg->colorclass[0] ?: ""; + msg.val = !!inst->cfg->colorclass[0]; + edje_object_message_send(elm_layout_edje_get(o), EDJE_MESSAGE_STRING_INT, 2, &msg); + msg.str = (char*)inst->cfg->colorclass[1] ?: ""; + msg.val = !!inst->cfg->colorclass[1]; + edje_object_message_send(elm_layout_edje_get(o), EDJE_MESSAGE_STRING_INT, 3, &msg); + } + edje_object_message_signal_process(elm_layout_edje_get(o)); +} + +static Eina_Bool +_clock_timer(void *d EINA_UNUSED) +{ + Eina_List *l; + Instance *inst; + Eina_Bool seconds = EINA_FALSE; + int sec; + char buf[128]; + + EINA_LIST_FOREACH(clock_instances, l, inst) + { + if (!inst->cfg->advanced) continue; + seconds |= inst->cfg->show_seconds; + sec = time_string_format(inst, buf, sizeof(buf)); + elm_object_part_text_set(inst->o_clock, "e.text", buf); + _eval_instance_size(inst); + } + sec = seconds ? 1 : (61 - sec); + if (clock_timer) + ecore_timer_interval_set(clock_timer, sec); + else + clock_timer = ecore_timer_add(sec, _clock_timer, NULL); + return EINA_TRUE; +} + +static void +_clock_popup_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED) +{ + Instance *inst = data; + + if (obj != inst->popup) return; + inst->popup = inst->o_table = inst->o_cal = NULL; +} + +EINTERN void +clock_popup_new(Instance *inst) +{ + Evas_Object *oi; + + if (inst->popup) return; + + inst->madj = 0; + + time_instance_update(inst); + + inst->popup = elm_ctxpopup_add(inst->o_clock); + elm_object_style_set(inst->popup, "noblock"); + evas_object_smart_callback_add(inst->popup, "dismissed", _clock_popup_dismissed, inst); + evas_object_event_callback_add(inst->popup, EVAS_CALLBACK_DEL, _clock_popup_del, inst); + + inst->o_table = elm_table_add(inst->popup); + + oi = elm_layout_add(inst->o_table); + inst->o_cal = oi; + e_theme_edje_object_set(oi, "base/theme/gadget/clock", + "e/gadget/clock/calendar"); + _clock_calendar_month_update(inst); + + elm_object_signal_callback_add(oi, "e,action,prev", "*", + _clock_month_prev_cb, inst); + elm_object_signal_callback_add(oi, "e,action,next", "*", + _clock_month_next_cb, inst); + edje_object_message_signal_process(elm_layout_edje_get(oi)); + elm_layout_sizing_eval(oi); + elm_table_pack(inst->o_table, oi, 0, 1, 1, 1); + evas_object_show(oi); + + elm_object_content_set(inst->popup, inst->o_table); + e_gadget_util_ctxpopup_place(inst->o_clock, inst->popup, NULL); + evas_object_show(inst->popup); +} + +void +clock_instances_redo(void) +{ + Eina_List *l; + Instance *inst; + + EINA_LIST_FOREACH(clock_instances, l, inst) + { + _clock_edje_init(inst, inst->o_clock); + _eval_instance_size(inst); + } +} + +static void +_clock_cb_mouse_down(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event) +{ + Instance *inst = data; + Evas_Event_Mouse_Down *ev = event; + + if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return; + if (ev->button == 1) + { + if (inst->popup) elm_ctxpopup_dismiss(inst->popup); + else clock_popup_new(inst); + } + else if (ev->button == 3) + e_gadget_configure(inst->o_clock); +} + +static void +_clock_sizing_changed_cb(void *data, Evas_Object *obj EINA_UNUSED, const char *emission EINA_UNUSED, const char *source EINA_UNUSED) +{ + _eval_instance_size(data); +} + +static void +clock_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +{ + Instance *inst = data; + Eina_List *l; + Eina_Bool advanced = EINA_FALSE, seconds = EINA_FALSE; + + clock_instances = eina_list_remove(clock_instances, inst); + evas_object_del(inst->popup); + time_daynames_clear(inst); + free(inst); + EINA_LIST_FOREACH(clock_instances, l, inst) + { + advanced |= !!inst->cfg->advanced; + seconds |= !!inst->cfg->show_seconds; + if (seconds) break; + } + if (seconds) return; //no change possible + E_FREE_FUNC(clock_timer, ecore_timer_del); + if (advanced) + _clock_timer(NULL); +} + +static Config_Item * +_conf_item_get(int *id, Eina_Bool digital) +{ + Config_Item *ci; + Eina_List *l; + + if (*id > 0) + { + EINA_LIST_FOREACH(time_config->items, l, ci) + if (*id == ci->id) return ci; + } + + ci = E_NEW(Config_Item, 1); + if (!*id) + ci->id = time_config->items ? eina_list_count(time_config->items) + 1 : 1; + else + ci->id = -1; + + ci->weekend.start = 6; + ci->weekend.len = 2; + ci->week.start = 1; + ci->digital_clock = digital; + ci->digital_24h = 0; + ci->show_seconds = 0; + ci->show_date = 0; + ci->time_str[0] = eina_stringshare_add("%I:%M"); + ci->time_str[1] = eina_stringshare_add("%F"); + + if (ci->id < 1) return ci; + time_config->items = eina_list_append(time_config->items, ci); + e_config_save_queue(); + + return ci; +} + +static Evas_Object * +_clock_gadget_configure(Evas_Object *g) +{ + Instance *inst = evas_object_data_get(g, "clock"); + return config_clock(inst->cfg); +} + +static void +_clock_gadget_removed_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info) +{ + Instance *inst = data; + + if (inst->o_clock != event_info) return; + time_config->items = eina_list_remove(time_config->items, inst->cfg); + eina_stringshare_del(inst->cfg->timezone); + eina_stringshare_del(inst->cfg->time_str[0]); + eina_stringshare_del(inst->cfg->time_str[1]); + E_FREE(inst->cfg); +} + +static void +_clock_gadget_created_cb(void *data, Evas_Object *obj, void *event_info EINA_UNUSED) +{ + Instance *inst = data; + + e_gadget_configure_cb_set(inst->o_clock, _clock_gadget_configure); + evas_object_smart_callback_del_full(obj, "gadget_created", _clock_gadget_created_cb, data); + if (inst->cfg->advanced) + { + _clock_timer(NULL); + ecore_timer_reset(clock_timer); + } + _eval_instance_size(inst); +} + +static Evas_Object * +clock_create(Evas_Object *parent, Instance *inst, E_Gadget_Site_Orient orient) +{ + Evas_Object *o; + const char *sig = NULL; + + inst->o_clock = o = elm_layout_add(parent); + elm_layout_signal_callback_add(o, "e,state,sizing,changed", "*", + _clock_sizing_changed_cb, inst); + + _clock_edje_init(inst, o); + + switch (orient) + { + case E_GADGET_SITE_ORIENT_HORIZONTAL: + sig = "e,state,horizontal"; + break; + + case E_GADGET_SITE_ORIENT_VERTICAL: + sig = "e,state,vertical"; + break; + + default: + sig = "e,state,float"; + } + + elm_layout_signal_emit(inst->o_clock, sig, "e"); + + evas_object_event_callback_add(o, EVAS_CALLBACK_DEL, clock_del, inst); + evas_object_smart_callback_add(parent, "gadget_created", _clock_gadget_created_cb, inst); + evas_object_smart_callback_add(parent, "gadget_removed", _clock_gadget_removed_cb, inst); + evas_object_data_set(o, "clock", inst); + + evas_object_event_callback_add(inst->o_clock, + EVAS_CALLBACK_MOUSE_DOWN, + _clock_cb_mouse_down, + inst); + + if (inst->cfg->id < 0) return o; + clock_instances = eina_list_append(clock_instances, inst); + + return o; +} + +EINTERN Evas_Object * +digital_clock_create(Evas_Object *parent, int *id, E_Gadget_Site_Orient orient) +{ + Instance *inst; + + inst = E_NEW(Instance, 1); + inst->cfg = _conf_item_get(id, 1); + return clock_create(parent, inst, orient); +} + +EINTERN Evas_Object * +analog_clock_create(Evas_Object *parent, int *id, E_Gadget_Site_Orient orient) +{ + Instance *inst; + + inst = E_NEW(Instance, 1); + inst->cfg = _conf_item_get(id, 0); + return clock_create(parent, inst, orient); +} + +typedef struct Wizard_Item +{ + E_Gadget_Wizard_End_Cb cb; + void *data; + int id; +} Wizard_Item; + +static void +_wizard_end(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +{ + Wizard_Item *wi = data; + + wi->cb(wi->data, wi->id); + free(wi); +} + +static void +clock_wizard(E_Gadget_Wizard_End_Cb cb, void *data, Eina_Bool digital) +{ + int id = 0; + Config_Item *ci; + Wizard_Item *wi; + + wi = E_NEW(Wizard_Item, 1); + wi->cb = cb; + wi->data = data; + + ci = _conf_item_get(&id, digital); + wi->id = ci->id; + evas_object_event_callback_add(config_clock(ci), EVAS_CALLBACK_DEL, _wizard_end, wi); +} + +EINTERN void +digital_clock_wizard(E_Gadget_Wizard_End_Cb cb, void *data) +{ + clock_wizard(cb, data, 1); +} + +EINTERN void +analog_clock_wizard(E_Gadget_Wizard_End_Cb cb, void *data) +{ + clock_wizard(cb, data, 0); +} + +EINTERN void +time_config_update(Config_Item *ci) +{ + Eina_List *l; + Instance *inst; + Eina_Bool advanced = EINA_FALSE; + + ci->week.start = (ci->weekend.start + ci->weekend.len) % 7; + EINA_LIST_FOREACH(clock_instances, l, inst) + { + if (inst->cfg != ci) continue; + _clock_edje_init(inst, inst->o_clock); + if (!advanced) + { + advanced |= inst->cfg->advanced; + if (!inst->cfg->advanced) continue; + _clock_timer(NULL); + ecore_timer_reset(clock_timer); + } + _eval_instance_size(inst); + } + if (!advanced) + E_FREE_FUNC(clock_timer, ecore_timer_del); + e_config_save_queue(); +} diff --git a/src/modules/time/clock.h b/src/modules/time/clock.h new file mode 100644 index 000000000..990d42b56 --- /dev/null +++ b/src/modules/time/clock.h @@ -0,0 +1,93 @@ +#ifndef CLOCK_H +#define CLOCK_H + +#include "e.h" + +E_API extern E_Module_Api e_modapi; + +E_API void *e_modapi_init (E_Module *m); +E_API int e_modapi_shutdown (E_Module *m); +E_API int e_modapi_save (E_Module *m); + +typedef struct _Config Config; +typedef struct _Config_Item Config_Item; +typedef struct _Instance Instance; + +typedef enum +{ + CLOCK_DATE_DISPLAY_NONE, + CLOCK_DATE_DISPLAY_FULL, + CLOCK_DATE_DISPLAY_NUMERIC, + CLOCK_DATE_DISPLAY_DATE_ONLY, + CLOCK_DATE_DISPLAY_ISO8601, + CLOCK_DATE_DISPLAY_CUSTOM, +} Clock_Date_Display; + +struct _Config +{ + Eina_List *items; + + E_Module *module; + Evas_Object *config_dialog; +}; + +struct _Config_Item +{ + int id; + struct { + int start, len; // 0->6 0 == sun, 6 == sat, number of days + } weekend; + struct { + int start; // 0->6 0 == sun, 6 == sat + } week; + Eina_Bool digital_clock; + Eina_Bool digital_24h; + Eina_Bool show_seconds; + Clock_Date_Display show_date; + Eina_Bool advanced; + Eina_Stringshare *timezone; + Eina_Stringshare *time_str[2]; + Eina_Stringshare *colorclass[2]; +}; + + +struct _Instance +{ + Evas_Object *o_clock, *o_table, *o_cal; + Evas_Object *popup; + + int madj; + + char year[8]; + char month[64]; + const char *daynames[7]; + unsigned char daynums[7][6]; + Eina_Bool dayweekends[7][6]; + Eina_Bool dayvalids[7][6]; + Eina_Bool daytoday[7][6]; + Config_Item *cfg; +}; + +EINTERN Evas_Object *config_clock(Config_Item *); +EINTERN void config_timezone_populate(Evas_Object *obj, const char *name); +void clock_instances_redo(void); + +EINTERN void time_daynames_clear(Instance *inst); +EINTERN void time_datestring_format(Instance *inst, char *buf, int bufsz); +EINTERN int time_string_format(Instance *inst, char *buf, int bufsz); +EINTERN void time_instance_update(Instance *inst); +EINTERN void time_init(void); +EINTERN void time_shutdown(void); +EINTERN void time_zoneinfo_scan(Evas_Object *obj); + +EINTERN Evas_Object *digital_clock_create(Evas_Object *parent, int *id, E_Gadget_Site_Orient orient); +EINTERN Evas_Object *analog_clock_create(Evas_Object *parent, int *id, E_Gadget_Site_Orient orient); +EINTERN void digital_clock_wizard(E_Gadget_Wizard_End_Cb cb, void *data); +EINTERN void analog_clock_wizard(E_Gadget_Wizard_End_Cb cb, void *data); +EINTERN void clock_popup_new(Instance *inst); +EINTERN void time_config_update(Config_Item *ci); + +extern Config *time_config; +extern Eina_List *clock_instances; + +#endif diff --git a/src/modules/time/config.c b/src/modules/time/config.c new file mode 100644 index 000000000..ad4c528ef --- /dev/null +++ b/src/modules/time/config.c @@ -0,0 +1,627 @@ +#include "clock.h" +#include + +static const char *datecfg[] = +{ + N_("None"), + N_("Full"), + N_("Numeric"), + N_("Date-only"), + N_("ISO 8601"), + N_("Custom"), +}; + + +static void +_config_rect_click(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info) +{ + Evas_Event_Mouse_Up *ev = event_info; + ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD; + evas_object_del(data); +} + +static Evas_Object * +_config_autoclose_rect_add(Evas_Object *obj) +{ + Evas_Object *rect; + + rect = evas_object_rectangle_add(e_comp->evas); + e_comp_object_util_fullscreen(rect); + evas_object_color_set(rect, 0, 0, 0, 0); + evas_object_layer_set(rect, E_LAYER_MENU - 1); + evas_object_show(rect); + evas_object_event_callback_add(rect, EVAS_CALLBACK_MOUSE_UP, _config_rect_click, obj); + return rect; +} + +static void +_config_close(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +{ + time_config->config_dialog = NULL; +} + +static void +_config_changed(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +{ + time_config_update(data); +} + +static void +_clock_color_dismissed(void *data EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED) +{ + evas_object_del(obj); +} + +static void +_config_color_reset(void *data, Evas_Object *obj, void *event_info EINA_UNUSED) +{ + Config_Item *ci = data; + Evas_Object *cs; + int num; + + num = !evas_object_data_get(obj, "bg_color"); + if (ci->colorclass[num]) + { + elm_config_color_overlay_unset(ci->colorclass[num]); + edje_color_class_del(ci->colorclass[num]); + } + eina_stringshare_replace(&ci->colorclass[num], NULL); + cs = evas_object_data_get(obj, "colorselector"); + elm_colorselector_color_set(cs, 0, 0, 0, 0); + elm_colorselector_palette_item_color_set(evas_object_data_get(cs, "colorselector_it"), + 0, 0, 0, 0); + time_config_update(data); +} + +static void +_config_color_change(void *data, Evas_Object *obj, void *event_info EINA_UNUSED) +{ + Config_Item *ci = data; + int r, g, b, a; + int num; + char buf[1024]; + + num = !evas_object_data_get(obj, "bg_color"); + elm_colorselector_color_get(obj, &r, &g, &b, &a); + + if (!ci->colorclass[num]) + { + snprintf(buf, sizeof(buf), "e.clock_color_%s.%d", num ? "fg" : "bg", ci->id); + eina_stringshare_replace(&ci->colorclass[num], buf); + } + elm_config_color_overlay_set(ci->colorclass[num], r, g, b, a, 0, 0, 0, 0, 0, 0, 0, 0); + edje_color_class_set(ci->colorclass[num], r, g, b, a, 0, 0, 0, 0, 0, 0, 0, 0); + elm_colorselector_palette_item_color_set(evas_object_data_get(obj, "colorselector_it"), r, g, b, a); + time_config_update(data); +} + +static void +_config_color_setup(void *data, Evas_Object *obj, void *event_info EINA_UNUSED) +{ + Config_Item *ci = data; + Evas_Object *cs, *ctx, *bx, *bt, *rect; + int r, g, b, a, x, y; + Eina_Bool bg; + const char *ccname, *ccnames[] = + { + "e.clock_color_bg", + "e.clock_color_fg", + }; + + bg = !!evas_object_data_get(obj, "bg_color"); + ccname = ci->colorclass[!bg]; + if (!ccname) ccname = ccnames[!bg]; + edje_color_class_get(ccname, &r, &g, &b, &a, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + + bx = elm_box_add(obj); + E_FILL(bx); + evas_object_show(bx); + + cs = elm_colorselector_add(obj); + evas_object_data_set(cs, "colorselector_bt", evas_object_data_get(obj, "colorselector_tt")); + evas_object_data_set(cs, "bg_color", (void*)(long)bg); + evas_object_smart_callback_add(cs, "changed,user", _config_color_change, ci); + elm_colorselector_mode_set(cs, ELM_COLORSELECTOR_COMPONENTS); + elm_colorselector_color_set(cs, r, g, b, a); + E_FILL(cs); + elm_box_pack_end(bx, cs); + evas_object_show(cs); + + bt = elm_button_add(bx); + evas_object_data_set(bt, "colorselector", cs); + evas_object_data_set(bt, "bg_color", (void*)(long)bg); + elm_object_text_set(bt, _("Reset")); + evas_object_smart_callback_add(bt, "clicked", _config_color_reset, ci); + evas_object_show(bt); + elm_box_pack_end(bx, bt); + + /* size hints: the final frontier */ + rect = evas_object_rectangle_add(e_comp->elm); + evas_object_geometry_get(time_config->config_dialog, NULL, NULL, &x, &y); + evas_object_size_hint_min_set(rect, x - 10, 1); + e_comp_object_util_del_list_append(bx, rect); + elm_box_pack_end(bx, rect); + + ctx = elm_ctxpopup_add(obj); + elm_ctxpopup_hover_parent_set(ctx, e_comp->elm); + evas_object_layer_set(ctx, E_LAYER_MENU); + elm_object_style_set(ctx, "noblock"); + e_comp_object_util_del_list_append(ctx, _config_autoclose_rect_add(ctx)); + evas_object_smart_callback_add(ctx, "dismissed", _clock_color_dismissed, NULL); + elm_object_content_set(ctx, bx); + evas_pointer_canvas_xy_get(e_comp->evas, &x, &y); + evas_object_move(ctx, x, y); + evas_object_show(ctx); +} + +static void +_config_digital_timestr_update(Config_Item *ci, Evas_Object *obj, int idx) +{ + const char *str, *p; + char seconds[] = + { + 'S', + 's', + 'r', + 'T', + }; + unsigned int i; + + str = elm_entry_entry_get(obj); + eina_stringshare_replace(&ci->time_str[idx], str); + ci->show_seconds = 0; + for (p = strchr(str, '%'); p; p = strchr(p + 1, '%')) + { + for (i = 0; i < EINA_C_ARRAY_LENGTH(seconds); i++) + if (p[1] == seconds[i]) + { + ci->show_seconds = 1; + time_config_update(ci); + return; + } + } + + time_config_update(ci); +} + +static void +_config_digital_datestr_changed(void *data, Evas_Object *obj, void *event_info EINA_UNUSED) +{ + _config_digital_timestr_update(data, obj, 1); +} + +static Evas_Object * +_config_date_custom(Config_Item *ci, Evas_Object *bx) +{ + Evas_Object *o; + + o = elm_entry_add(bx); + elm_entry_single_line_set(o, 1); + elm_object_tooltip_text_set(o, _("strftime() format string")); + elm_entry_entry_set(o, ci->time_str[1]); + evas_object_smart_callback_add(o, "changed,user", _config_digital_datestr_changed, ci); + E_FILL(o); + E_EXPAND(o); + evas_object_show(o); + elm_box_pack_end(bx, o); + return o; +} + +static void +_config_date_changed(void *data, Evas_Object *obj, void *event_info) +{ + Config_Item *ci = data; + Evas_Object *bx = elm_object_parent_widget_get(obj); + Eina_Bool custom; + + custom = ci->show_date == CLOCK_DATE_DISPLAY_CUSTOM; + ci->show_date = (intptr_t)elm_object_item_data_get(event_info); + if (custom) + { + elm_box_unpack(bx, obj); + elm_box_clear(bx); + E_FILL(obj); + E_EXPAND(obj); + elm_box_pack_end(bx, obj); + } + else if (ci->show_date == CLOCK_DATE_DISPLAY_CUSTOM) + { + E_WEIGHT(obj, 0, 0); + E_ALIGN(obj, 0, 0.5); + elm_object_focus_set(_config_date_custom(ci, bx), 1); + } + time_config_update(ci); +} + +static void +_config_weekend_changed(void *data, Evas_Object *obj EINA_UNUSED, void *event_info) +{ + Config_Item *ci = data; + + ci->weekend.start = (intptr_t)elm_object_item_data_get(event_info); + time_config_update(ci); +} + +static void +_config_weekend_end_changed(void *data, Evas_Object *obj EINA_UNUSED, void *event_info) +{ + Config_Item *ci = data; + int end; + + end = (intptr_t)elm_object_item_data_get(event_info); + if (end < ci->weekend.start) end += 7; + ci->weekend.len = end - ci->weekend.start + 1; + time_config_update(ci); +} + +static void +_config_date_populate(void *data, Evas_Object *obj, void *event_info EINA_UNUSED) +{ + Config_Item *ci = data; + unsigned int i; + + elm_hoversel_clear(obj); + for (i = 0; i <= 5; i++) + if (ci->show_date != i) + elm_hoversel_item_add(obj, datecfg[i], NULL, ELM_ICON_NONE, NULL, (uintptr_t*)(unsigned long)i); +} + +static void +_config_weekend_populate(void *data, Evas_Object *obj, void *event_info EINA_UNUSED) +{ + Config_Item *ci = data; + char daynames[7][64]; + struct tm tm; + int i; + + memset(&tm, 0, sizeof(struct tm)); + for (i = 0; i < 7; i++) + { + tm.tm_wday = i; + strftime(daynames[i], sizeof(daynames[i]), "%A", &tm); + } + + elm_hoversel_clear(obj); + for (i = ci->weekend.start + 1; i <= 6; i++) + if (ci->weekend.start != i) + elm_hoversel_item_add(obj, daynames[i], NULL, ELM_ICON_NONE, NULL, (intptr_t*)(long)i); + for (i = 0; i < ci->weekend.start; i++) + elm_hoversel_item_add(obj, daynames[i], NULL, ELM_ICON_NONE, NULL, (intptr_t*)(long)i); +} + +static void +_config_weekend_end_populate(void *data, Evas_Object *obj, void *event_info EINA_UNUSED) +{ + Config_Item *ci = data; + char daynames[7][64]; + struct tm tm; + int i, end; + + memset(&tm, 0, sizeof(struct tm)); + for (i = 0; i < 7; i++) + { + tm.tm_wday = i; + strftime(daynames[i], sizeof(daynames[i]), "%A", &tm); + } + + elm_hoversel_clear(obj); + end = (ci->weekend.start + ci->weekend.len - 1) % 7; + for (i = end + 1; i <= 6; i++) + if (end != i) + elm_hoversel_item_add(obj, daynames[i], NULL, ELM_ICON_NONE, NULL, (intptr_t*)(long)i); + for (i = 0; i < end; i++) + elm_hoversel_item_add(obj, daynames[i], NULL, ELM_ICON_NONE, NULL, (intptr_t*)(long)i); +} + +static void +_config_timezone_setup(void *data, Evas_Object *obj, void *event_info EINA_UNUSED) +{ + Evas_Object *hover, *gl; + + hover = elm_hover_add(e_comp->elm); + evas_object_layer_set(hover, E_LAYER_MENU); + elm_hover_parent_set(hover, elm_object_parent_widget_get(obj)); + elm_hover_target_set(hover, elm_object_parent_widget_get(obj)); + + gl = elm_genlist_add(hover); + evas_object_layer_set(gl, E_LAYER_MENU); + evas_object_data_set(gl, "config_item", data); + evas_object_data_set(gl, "button", obj); + elm_genlist_mode_set(gl, ELM_LIST_COMPRESS); + elm_genlist_homogeneous_set(gl, 1); + elm_scroller_bounce_set(gl, 0, 0); + evas_object_show(gl); + elm_object_part_content_set(hover, "middle", gl); + time_zoneinfo_scan(gl); + e_comp_object_util_del_list_append(gl, hover); + e_comp_object_util_del_list_append(gl, _config_autoclose_rect_add(gl)); + evas_object_show(hover); +} + +static void +_config_digital_timestr_changed(void *data, Evas_Object *obj, void *event_info EINA_UNUSED) +{ + _config_digital_timestr_update(data, obj, 0); +} + +static void +_config_label_add(Evas_Object *tb, const char *txt, int row) +{ + Evas_Object *o; + + o = elm_label_add(tb); + E_ALIGN(o, 0, 0.5); + elm_object_text_set(o, txt); + evas_object_show(o); + elm_table_pack(tb, o, 0, row, 1, 1); +} + +static void +_config_digital_rows_setup(Config_Item *ci, Evas_Object *tb) +{ + int row = 1; + Evas_Object *o; + + evas_object_del(elm_table_child_get(tb, 0, 1)); + evas_object_del(elm_table_child_get(tb, 1, 1)); + evas_object_del(elm_table_child_get(tb, 0, 2)); + evas_object_del(elm_table_child_get(tb, 1, 2)); + if (ci->advanced) + { + _config_label_add(tb, _("Time string:"), row); + o = elm_entry_add(tb); + E_FILL(o); + evas_object_show(o); + elm_entry_single_line_set(o, 1); + elm_entry_entry_set(o, ci->time_str[0]); + elm_object_focus_set(o, 1); + evas_object_smart_callback_add(o, "changed,user", _config_digital_timestr_changed, ci); + elm_table_pack(tb, o, 1, row++, 1, 1); + + o = elm_separator_add(tb); + E_EXPAND(o); + E_FILL(o); + elm_separator_horizontal_set(o, 1); + evas_object_show(o); + elm_table_pack(tb, o, 0, row++, 2, 1); + return; + } + if (ci->digital_clock) + { + _config_label_add(tb, _("24-hour Display:"), row); + o = elm_check_add(tb); + E_FILL(o); + evas_object_show(o); + elm_object_style_set(o, "toggle"); + elm_object_part_text_set(o, "on", "On"); + elm_object_part_text_set(o, "off", "Off"); + elm_check_state_pointer_set(o, &ci->digital_24h); + evas_object_smart_callback_add(o, "changed", _config_changed, ci); + elm_table_pack(tb, o, 1, row++, 1, 1); + } + + _config_label_add(tb, _("Show Seconds:"), row); + o = elm_check_add(tb); + E_FILL(o); + evas_object_show(o); + elm_object_style_set(o, "toggle"); + elm_object_part_text_set(o, "on", _("On")); + elm_object_part_text_set(o, "off", _("Off")); + elm_check_state_pointer_set(o, &ci->show_seconds); + evas_object_smart_callback_add(o, "changed", _config_changed, ci); + elm_table_pack(tb, o, 1, row++, 1, 1); +} + +static void +_config_advanced_changed(void *data, Evas_Object *obj, void *event_info EINA_UNUSED) +{ + Config_Item *ci = data; + + _config_digital_rows_setup(data, evas_object_data_get(obj, "table")); + time_config_update(ci); +} + +EINTERN Evas_Object * +config_clock(Config_Item *ci) +{ + Evas_Object *popup, *tb, *o, *bx; + int i, row = 0; + char daynames[7][64]; + struct tm tm; + + memset(&tm, 0, sizeof(struct tm)); + for (i = 0; i < 7; i++) + { + tm.tm_wday = i; + strftime(daynames[i], sizeof(daynames[i]), "%A", &tm); + } + popup = elm_popup_add(e_comp->elm); + E_EXPAND(popup); + evas_object_layer_set(popup, E_LAYER_POPUP); + elm_popup_allow_events_set(popup, 1); + elm_popup_scrollable_set(popup, 1); + + tb = elm_table_add(popup); + E_EXPAND(tb); + evas_object_show(tb); + elm_object_content_set(popup, tb); + + if (ci->digital_clock) + { + _config_label_add(tb, _("Mode"), row); + o = elm_check_add(tb); + E_FILL(o); + evas_object_show(o); + elm_object_style_set(o, "toggle"); + elm_object_part_text_set(o, "on", _("Advanced")); + elm_object_part_text_set(o, "off", _("Simple")); + elm_check_state_pointer_set(o, &ci->advanced); + evas_object_smart_callback_add(o, "changed", _config_advanced_changed, ci); + evas_object_data_set(o, "table", tb); + elm_table_pack(tb, o, 1, row++, 1, 1); + } + _config_digital_rows_setup(ci, tb); + row = 3; + + _config_label_add(tb, _("Date Display:"), row); + bx = elm_box_add(tb); + elm_box_horizontal_set(bx, 1); + evas_object_show(bx); + elm_table_pack(tb, bx, 1, row++, 1, 1); + E_FILL(bx); + E_EXPAND(bx); + o = elm_hoversel_add(tb); + elm_box_pack_end(bx, o); + elm_hoversel_hover_parent_set(o, popup); + elm_hoversel_auto_update_set(o, 1); + evas_object_show(o); + evas_object_smart_callback_add(o, "clicked", _config_date_populate, ci); + evas_object_smart_callback_add(o, "selected", _config_date_changed, ci); + elm_object_text_set(o, datecfg[ci->show_date]); + if (ci->show_date == CLOCK_DATE_DISPLAY_CUSTOM) + { + E_ALIGN(o, 0, 0.5); + E_WEIGHT(o, 0, 0); + o = _config_date_custom(ci, bx); + } + else + { + E_FILL(o); + E_EXPAND(o); + } + + _config_label_add(tb, _("Weekend Start:"), row); + o = elm_hoversel_add(tb); + E_FILL(o); + elm_hoversel_hover_parent_set(o, popup); + elm_hoversel_auto_update_set(o, 1); + evas_object_show(o); + elm_table_pack(tb, o, 1, row++, 1, 1); + elm_object_text_set(o, daynames[ci->weekend.start]); + evas_object_smart_callback_add(o, "clicked", _config_weekend_populate, ci); + evas_object_smart_callback_add(o, "selected", _config_weekend_changed, ci); + + _config_label_add(tb, _("Weekend End:"), row); + o = elm_hoversel_add(tb); + E_FILL(o); + elm_hoversel_hover_parent_set(o, popup); + elm_hoversel_auto_update_set(o, 1); + evas_object_show(o); + elm_table_pack(tb, o, 1, row++, 1, 1); + elm_object_text_set(o, daynames[(ci->weekend.start + ci->weekend.len - 1) % 7]); + evas_object_smart_callback_add(o, "clicked", _config_weekend_end_populate, ci); + evas_object_smart_callback_add(o, "selected", _config_weekend_end_changed, ci); + + _config_label_add(tb, _("Timezone:"), row); + o = elm_button_add(tb); + E_FILL(o); + elm_object_text_set(o, ci->timezone ?: _("System")); + evas_object_show(o); + evas_object_smart_callback_add(o, "clicked", _config_timezone_setup, ci); + elm_table_pack(tb, o, 1, row++, 1, 1); + + for (i = 0; i <= 1; i++) + { + const char *ccname, *names[] = + { + N_("Background"), + N_("Foreground"), + }; + const char *ccnames[] = + { + "e.clock_color_bg", + "e.clock_color_fg", + }; + Evas_Object *cs; + Elm_Object_Item *it; + int r, g, b, a; + + cs = elm_colorselector_add(tb); + elm_colorselector_mode_set(cs, ELM_COLORSELECTOR_PALETTE); + ccname = ci->colorclass[i]; + if (!ccname) ccname = ccnames[i]; + edje_color_class_get(ccname, &r, &g, &b, &a, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + + it = elm_colorselector_palette_color_add(cs, r, g, b, a); + o = elm_button_add(tb); + elm_object_text_set(o, names[i]); + elm_object_content_set(o, cs); + E_FILL(o); + if (!i) + evas_object_data_set(o, "bg_color", (void*)1L); + evas_object_data_set(o, "colorselector_it", it); + evas_object_smart_callback_add(o, "clicked", _config_color_setup, ci); + evas_object_show(o); + elm_table_pack(tb, o, i, row, 1, 1); + } + + popup = e_comp_object_util_add(popup, E_COMP_OBJECT_TYPE_NONE); + evas_object_layer_set(popup, E_LAYER_POPUP); + evas_object_resize(popup, e_zone_current_get()->w / 4, e_zone_current_get()->h / 3); + e_comp_object_util_center(popup); + evas_object_show(popup); + e_comp_object_util_autoclose(popup, NULL, e_comp_object_util_autoclose_on_escape, NULL); + evas_object_event_callback_add(popup, EVAS_CALLBACK_DEL, _config_close, NULL); + + return time_config->config_dialog = popup; +} + + +static char * +_config_timezone_text_get(const char *str, Evas_Object *obj EINA_UNUSED, const char *part EINA_UNUSED) +{ + return strdup(str); +} + +static void +_config_timezone_text_del(void *d, Evas_Object *obj EINA_UNUSED) +{ + free(d); +} + +static int +_config_timezone_sort(void *ita, void *itb) +{ + const char *a, *b; + a = elm_object_item_data_get(ita); + b = elm_object_item_data_get(itb); + return strcmp(a, b); +} + +static void +_config_timezone_set(void *data EINA_UNUSED, Evas_Object *obj, void *event_info) +{ + char *tz = elm_object_item_data_get(event_info); + Config_Item *ci; + Evas_Object *bt; + + ci = evas_object_data_get(obj, "config_item"); + bt = evas_object_data_get(obj, "button"); + eina_stringshare_replace(&ci->timezone, tz); + elm_object_text_set(bt, tz); + time_config_update(ci); + evas_object_del(obj); +} + +EINTERN void +config_timezone_populate(Evas_Object *obj, const char *name) +{ + static const Elm_Genlist_Item_Class itc = + { + .item_style = "default", + .func = { + .text_get = (Elm_Genlist_Item_Text_Get_Cb)_config_timezone_text_get, + .del = _config_timezone_text_del, + }, + .version = ELM_GENLIST_ITEM_CLASS_VERSION + }; + Config_Item *ci; + Elm_Object_Item *it; + + it = elm_genlist_item_sorted_insert(obj, &itc, strdup(name), NULL, 0, (Eina_Compare_Cb)_config_timezone_sort, _config_timezone_set, NULL); + ci = evas_object_data_get(obj, "config_item"); + if (eina_streq(name, ci->timezone)) + elm_genlist_item_bring_in(it, ELM_GENLIST_ITEM_SCROLLTO_MIDDLE); +} diff --git a/src/modules/time/e-module-time.edj b/src/modules/time/e-module-time.edj new file mode 100644 index 0000000000000000000000000000000000000000..75666988824ef37f7ecee23f6adeee718a9c4c8d GIT binary patch literal 14062 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 HF^&HR`v#_9 literal 0 HcmV?d00001 diff --git a/src/modules/time/mod.c b/src/modules/time/mod.c new file mode 100644 index 000000000..4552f199a --- /dev/null +++ b/src/modules/time/mod.c @@ -0,0 +1,142 @@ +#include "clock.h" +static E_Config_DD *conf_edd = NULL; +static E_Config_DD *conf_item_edd = NULL; +static E_Action *act = NULL; + +static void +_e_mod_action_cb(E_Object *obj EINA_UNUSED, const char *params, ...) +{ + Eina_List *l; + Instance *inst; + + if (!eina_streq(params, "show_calendar")) return; + + EINA_LIST_FOREACH(clock_instances, l, inst) + if (inst->popup) + { + elm_ctxpopup_dismiss(inst->popup); + inst->popup = NULL; + } + else + clock_popup_new(inst); +} + +EINTERN void +clock_init(void) +{ + conf_item_edd = E_CONFIG_DD_NEW("Config_Item", Config_Item); +#undef T +#undef D +#define T Config_Item +#define D conf_item_edd + E_CONFIG_VAL(D, T, id, INT); + E_CONFIG_VAL(D, T, weekend.start, INT); + E_CONFIG_VAL(D, T, weekend.len, INT); + E_CONFIG_VAL(D, T, week.start, INT); + E_CONFIG_VAL(D, T, digital_clock, INT); + E_CONFIG_VAL(D, T, digital_24h, INT); + E_CONFIG_VAL(D, T, show_seconds, INT); + E_CONFIG_VAL(D, T, show_date, INT); + E_CONFIG_VAL(D, T, advanced, UCHAR); + E_CONFIG_VAL(D, T, timezone, STR); + E_CONFIG_VAL(D, T, time_str[0], STR); + E_CONFIG_VAL(D, T, time_str[1], STR); + E_CONFIG_VAL(D, T, colorclass[0], STR); + E_CONFIG_VAL(D, T, colorclass[1], STR); + + conf_edd = E_CONFIG_DD_NEW("Config", Config); +#undef T +#undef D +#define T Config +#define D conf_edd + E_CONFIG_LIST(D, T, items, conf_item_edd); + + time_config = e_config_domain_load("module.time", conf_edd); + + if (!time_config) + time_config = E_NEW(Config, 1); + + act = e_action_add("clock"); + if (act) + { + act->func.go = (void*)_e_mod_action_cb; + act->func.go_key = (void*)_e_mod_action_cb; + act->func.go_mouse = (void*)_e_mod_action_cb; + act->func.go_edge = (void*)_e_mod_action_cb; + + e_action_predef_name_set(N_("Clock"), N_("Toggle calendar"), "clock", "show_calendar", NULL, 0); + } + + e_gadget_type_add("Digital Clock", digital_clock_create, digital_clock_wizard); + e_gadget_type_add("Analog Clock", analog_clock_create, analog_clock_wizard); + time_init(); +} + +EINTERN void +clock_shutdown(void) +{ + if (act) + { + e_action_predef_name_del("Clock", "Toggle calendar"); + e_action_del("clock"); + act = NULL; + } + if (time_config) + { + Config_Item *ci; + + if (time_config->config_dialog) + { + evas_object_hide(time_config->config_dialog); + evas_object_del(time_config->config_dialog); + } + + EINA_LIST_FREE(time_config->items, ci) + { + eina_stringshare_del(ci->timezone); + eina_stringshare_del(ci->time_str[0]); + eina_stringshare_del(ci->time_str[1]); + eina_stringshare_del(ci->colorclass[0]); + eina_stringshare_del(ci->colorclass[1]); + free(ci); + } + + E_FREE(time_config); + } + E_CONFIG_DD_FREE(conf_edd); + E_CONFIG_DD_FREE(conf_item_edd); + + e_gadget_type_del("Digital Clock"); + e_gadget_type_del("Analog Clock"); + time_shutdown(); +} + +/* module setup */ +E_API E_Module_Api e_modapi = +{ + E_MODULE_API_VERSION, + "Time" +}; + +E_API void * +e_modapi_init(E_Module *m) +{ + clock_init(); + + time_config->module = m; + return m; +} + +E_API int +e_modapi_shutdown(E_Module *m EINA_UNUSED) +{ + clock_shutdown(); + return 1; +} + +E_API int +e_modapi_save(E_Module *m EINA_UNUSED) +{ + e_config_domain_save("module.time", conf_edd, time_config); + return 1; +} diff --git a/src/modules/time/module.desktop.in b/src/modules/time/module.desktop.in new file mode 100644 index 000000000..e5784010d --- /dev/null +++ b/src/modules/time/module.desktop.in @@ -0,0 +1,7 @@ +[Desktop Entry] +Encoding=UTF-8 +Type=Link +Name=Time +Comment=Time-related gadgets and utilities +Icon=e-module-time +X-Enlightenment-ModuleType=utils diff --git a/src/modules/time/time.c b/src/modules/time/time.c new file mode 100644 index 000000000..b3f93d628 --- /dev/null +++ b/src/modules/time/time.c @@ -0,0 +1,354 @@ +#include "clock.h" + +#include +#include + +static Eio_Monitor *clock_te_monitor = NULL; +static Eio_Monitor *clock_tz2_monitor = NULL; +static Eio_Monitor *clock_tzetc_monitor = NULL; +static Eina_List *clock_eio_handlers = NULL; + +static Ecore_Timer *update_today = NULL; + +#define ZONEINFO_DIR "/usr/share/zoneinfo/posix" +#define ZONEINFO_DIR_LEN sizeof(ZONEINFO_DIR) - 1 + +#define TE_DECL \ + const char *tzenv; \ + char prevtz[128] = {0} + +#define TZSET(inst) \ + tzenv = getenv("TZ"); \ + if (tzenv) \ + strncpy(prevtz, tzenv, sizeof(prevtz) - 1); \ + if (inst->cfg->timezone) \ + setenv("TZ", inst->cfg->timezone, 1); \ + tzset() + +#define TZUNSET() \ + if (prevtz[0]) \ + setenv("TZ", prevtz, 1); \ + else \ + unsetenv("TZ"); \ + tzset() + +static void +_zoneinfo_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +{ + eio_file_cancel(data); +} + +static void +_zoneinfo_done(void *data, Eio_File *handler EINA_UNUSED) +{ + evas_object_event_callback_del(data, EVAS_CALLBACK_DEL, _zoneinfo_del); +} + +static void +_zoneinfo_error(void *data, Eio_File *handler EINA_UNUSED, int error EINA_UNUSED) +{ + evas_object_event_callback_del(data, EVAS_CALLBACK_DEL, _zoneinfo_del); +} + +static Eina_Bool +_zoneinfo_filter(void *data EINA_UNUSED, Eio_File *handler EINA_UNUSED, const Eina_File_Direct_Info *info) +{ + return (info->type == EINA_FILE_REG) || (info->type == EINA_FILE_DIR); +} + +static void +_zoneinfo_main(void *data, Eio_File *handler EINA_UNUSED, const Eina_File_Direct_Info *info) +{ + if (info->type == EINA_FILE_REG) + config_timezone_populate(data, &info->path[ZONEINFO_DIR_LEN + 1]); + else + { + Eio_File *ls; + + ls = eio_file_direct_ls(info->path, _zoneinfo_filter, _zoneinfo_main, _zoneinfo_done, _zoneinfo_error, data); + evas_object_event_callback_add(data, EVAS_CALLBACK_DEL, _zoneinfo_del, ls); + } +} + +EINTERN void +time_zoneinfo_scan(Evas_Object *obj) +{ + Eio_File *ls; + + ls = eio_file_direct_ls(ZONEINFO_DIR, _zoneinfo_filter, _zoneinfo_main, _zoneinfo_done, _zoneinfo_error, obj); + evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, _zoneinfo_del, ls); +} + +EINTERN void +time_daynames_clear(Instance *inst) +{ + int x; + + for (x = 0; x < 7; x++) + eina_stringshare_replace(&inst->daynames[x], NULL); +} + +EINTERN void +time_datestring_format(Instance *inst, char *buf, int bufsz) +{ + struct timeval timev; + struct tm *tm; + time_t tt; + const char *default_str = "%F"; + TE_DECL; + + buf[0] = 0; + if (!inst->cfg->show_date) return; + TZSET(inst); + gettimeofday(&timev, NULL); + tt = (time_t)(timev.tv_sec); + tm = localtime(&tt); + TZUNSET(); + switch (inst->cfg->show_date) + { + case CLOCK_DATE_DISPLAY_FULL: + strftime(buf, bufsz, _("%a, %e %b, %Y"), (const struct tm *)tm); + break; + case CLOCK_DATE_DISPLAY_NUMERIC: + strftime(buf, bufsz, _("%a, %x"), (const struct tm *)tm); + break; + case CLOCK_DATE_DISPLAY_DATE_ONLY: + strftime(buf, bufsz, "%x", (const struct tm *)tm); + break; + case CLOCK_DATE_DISPLAY_ISO8601: + strftime(buf, bufsz, "%F", (const struct tm *)tm); + break; + case CLOCK_DATE_DISPLAY_CUSTOM: + if (!strftime(buf, bufsz, inst->cfg->time_str[1] ?: default_str, (const struct tm *)tm)) + strncpy(buf, "ERROR", bufsz - 1); + break; + default: break; + } +} + +EINTERN int +time_string_format(Instance *inst, char *buf, int bufsz) +{ + struct timeval timev; + struct tm *tm; + time_t tt; + const char *default_fmt = "%R"; + TE_DECL; + + buf[0] = 0; + TZSET(inst); + gettimeofday(&timev, NULL); + tt = (time_t)(timev.tv_sec); + tm = localtime(&tt); + TZUNSET(); + if (!strftime(buf, bufsz, inst->cfg->time_str[0] ?: default_fmt, (const struct tm *)tm)) + strncpy(buf, "ERROR", bufsz - 1); + return tm->tm_sec; +} + +EINTERN void +time_instance_update(Instance *inst) +{ + struct timeval timev; + struct tm *tm, tms, tmm, tm2; + time_t tt; + int started = 0, num, i; + int day; + + tzset(); + gettimeofday(&timev, NULL); + tt = (time_t)(timev.tv_sec); + tm = localtime(&tt); + + time_daynames_clear(inst); + if (!tm) return; + + // tms == current date time "saved" + // tm2 == date to look at adjusting for madj + // tm2 == month baseline @ 1st + memcpy(&tms, tm, sizeof(struct tm)); + num = 0; + for (day = (0 - 6); day < (31 + 16); day++) + { + memcpy(&tmm, &tms, sizeof(struct tm)); + tmm.tm_sec = 0; + tmm.tm_min = 0; + tmm.tm_hour = 10; + tmm.tm_mon += inst->madj; + tmm.tm_mday = 1; // start at the 1st of the month + tmm.tm_wday = 0; // ignored by mktime + tmm.tm_yday = 0; // ignored by mktime + tmm.tm_isdst = 0; // ignored by mktime + tt = mktime(&tmm); + tm = localtime(&tt); + memcpy(&tm2, tm, sizeof(struct tm)); + + tt = mktime(&tmm); + tt += (day * 60 * 60 * 24); + tm = localtime(&tt); + memcpy(&tmm, tm, sizeof(struct tm)); + if (!started) + { + if (tm->tm_wday == inst->cfg->week.start) + { + char buf[32]; + + for (i = 0; i < 7; i++, tm->tm_wday = (tm->tm_wday + 1) % 7) + { + strftime(buf, sizeof(buf), "%a", tm); + inst->daynames[i] = eina_stringshare_add(buf); + } + started = 1; + } + } + if (started) + { + int y = num / 7; + int x = num % 7; + + if (y < 6) + { + inst->daynums[x][y] = tmm.tm_mday; + + inst->dayvalids[x][y] = 0; + if (tmm.tm_mon == tm2.tm_mon) inst->dayvalids[x][y] = 1; + + inst->daytoday[x][y] = 0; + if ((tmm.tm_mon == tms.tm_mon) && + (tmm.tm_year == tms.tm_year) && + (tmm.tm_mday == tms.tm_mday)) + inst->daytoday[x][y] = 1; + + inst->dayweekends[x][y] = 0; + for (i = inst->cfg->weekend.start; + i < (inst->cfg->weekend.start + inst->cfg->weekend.len); + i++) + { + if (tmm.tm_wday == (i % 7)) + { + inst->dayweekends[x][y] = 1; + break; + } + } + } + num++; + } + } + + memcpy(&tmm, &tms, sizeof(struct tm)); + tmm.tm_sec = 0; + tmm.tm_min = 0; + tmm.tm_hour = 10; + tmm.tm_mon += inst->madj; + tmm.tm_mday = 1; // start at the 1st of the month + tmm.tm_wday = 0; // ignored by mktime + tmm.tm_yday = 0; // ignored by mktime + tmm.tm_isdst = 0; // ignored by mktime + tt = mktime(&tmm); + tm = localtime(&tt); + memcpy(&tm2, tm, sizeof(struct tm)); + inst->year[sizeof(inst->year) - 1] = 0; + strftime(inst->year, sizeof(inst->year) - 1, "%Y", (const struct tm *)&tm2); + inst->month[sizeof(inst->month) - 1] = 0; + strftime(inst->month, sizeof(inst->month) - 1, "%B", (const struct tm *)&tm2); // %b for short month +} + + +static Eina_Bool +_update_today_timer(void *data EINA_UNUSED) +{ + time_t t, t_tomorrow; + const struct tm *now; + struct tm today; + + t = time(NULL); + now = localtime(&t); + memcpy(&today, now, sizeof(today)); + today.tm_sec = 1; + today.tm_min = 0; + today.tm_hour = 0; + + t_tomorrow = mktime(&today) + 24 * 60 * 60; + if (update_today) ecore_timer_interval_set(update_today, t_tomorrow - t); + else update_today = ecore_timer_add(t_tomorrow - t, _update_today_timer, NULL); + return EINA_TRUE; +} + + +static Eina_Bool +_clock_eio_update(void *d EINA_UNUSED, int type EINA_UNUSED, void *event) +{ + Eio_Monitor_Event *ev = event; + + if ((ev->monitor == clock_te_monitor) || + (ev->monitor == clock_tz2_monitor) || + (ev->monitor == clock_tzetc_monitor)) + { + if (eina_streq(ev->filename, "/etc/localtime") || + eina_streq(ev->filename, "/etc/timezone")) + clock_instances_redo(); + } + return ECORE_CALLBACK_PASS_ON; +} + +static Eina_Bool +_clock_time_update(void *d EINA_UNUSED, int type EINA_UNUSED, void *event EINA_UNUSED) +{ + clock_instances_redo(); + return ECORE_CALLBACK_PASS_ON; +} + +static Eina_Bool +_clock_eio_error(void *d EINA_UNUSED, int type EINA_UNUSED, void *event) +{ + Eio_Monitor_Event *ev = event; + + if ((ev->monitor == clock_te_monitor) || + (ev->monitor == clock_tz2_monitor) || + (ev->monitor == clock_tzetc_monitor)) + { + E_FREE_FUNC(clock_te_monitor, eio_monitor_del); + if (ecore_file_exists("/etc/localtime")) + clock_te_monitor = eio_monitor_add("/etc/localtime"); + + E_FREE_FUNC(clock_tz2_monitor, eio_monitor_del); + if (ecore_file_exists("/etc/timezone")) + clock_tz2_monitor = eio_monitor_add("/etc/timezone"); + + E_FREE_FUNC(clock_tzetc_monitor, eio_monitor_del); + if (ecore_file_is_dir("/etc")) + clock_tzetc_monitor = eio_monitor_add("/etc"); + } + + return ECORE_CALLBACK_PASS_ON; +} + +EINTERN void +time_init(void) +{ + if (ecore_file_exists("/etc/localtime")) + clock_te_monitor = eio_monitor_add("/etc/localtime"); + if (ecore_file_exists("/etc/timezone")) + clock_tz2_monitor = eio_monitor_add("/etc/timezone"); + if (ecore_file_is_dir("/etc")) + clock_tzetc_monitor = eio_monitor_add("/etc"); + + E_LIST_HANDLER_APPEND(clock_eio_handlers, EIO_MONITOR_ERROR, _clock_eio_error, NULL); + E_LIST_HANDLER_APPEND(clock_eio_handlers, EIO_MONITOR_FILE_CREATED, _clock_eio_update, NULL); + E_LIST_HANDLER_APPEND(clock_eio_handlers, EIO_MONITOR_FILE_MODIFIED, _clock_eio_update, NULL); + E_LIST_HANDLER_APPEND(clock_eio_handlers, EIO_MONITOR_FILE_DELETED, _clock_eio_update, NULL); + E_LIST_HANDLER_APPEND(clock_eio_handlers, EIO_MONITOR_SELF_DELETED, _clock_eio_update, NULL); + E_LIST_HANDLER_APPEND(clock_eio_handlers, EIO_MONITOR_SELF_RENAME, _clock_eio_update, NULL); + E_LIST_HANDLER_APPEND(clock_eio_handlers, E_EVENT_SYS_RESUME, _clock_time_update, NULL); + E_LIST_HANDLER_APPEND(clock_eio_handlers, ECORE_EVENT_SYSTEM_TIMEDATE_CHANGED, _clock_time_update, NULL); + _update_today_timer(NULL); +} + +EINTERN void +time_shutdown(void) +{ + E_FREE_FUNC(update_today, ecore_timer_del); + E_FREE_FUNC(clock_te_monitor, eio_monitor_del); + E_FREE_FUNC(clock_tz2_monitor, eio_monitor_del); + E_FREE_FUNC(clock_tzetc_monitor, eio_monitor_del); +}