summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichaël Bouchaud (yoz) <yoz@efl.so>2017-01-07 11:19:10 +0100
committerMichael Bouchaud(yoz) <yoz@efl.so>2017-03-16 11:27:11 +0100
commit51124fb3965abd4a1358e55da3302ea334cee3e3 (patch)
treecf9ca7214152f9f731dbc6983f2ea90632a8d52e
parent9745890a37036091d5dec320fecda7ed4c6bdb6c (diff)
downloadenlightenment-devs/yoz/weather.tar.gz
weather: Add a new weather widgetdevs/yoz/weather
-rw-r--r--configure.ac15
-rw-r--r--src/bin/e_module.c1
-rw-r--r--src/modules/Makefile.mk2
-rw-r--r--src/modules/Makefile_weather.mk29
-rw-r--r--src/modules/weather/config.c197
-rw-r--r--src/modules/weather/e-module-weather.edjbin0 -> 1186281 bytes
-rw-r--r--src/modules/weather/mod.c104
-rw-r--r--src/modules/weather/module.desktop.in7
-rw-r--r--src/modules/weather/plugin.c234
-rw-r--r--src/modules/weather/plugin.h33
-rw-r--r--src/modules/weather/plugin_openweathermap.c540
-rw-r--r--src/modules/weather/plugin_openweathermap.h6
-rw-r--r--src/modules/weather/theme.edjbin0 -> 1151169 bytes
-rw-r--r--src/modules/weather/weather.c811
-rw-r--r--src/modules/weather/weather.h190
15 files changed, 2169 insertions, 0 deletions
diff --git a/configure.ac b/configure.ac
index 672e8e89ce..463e763dec 100644
--- a/configure.ac
+++ b/configure.ac
@@ -457,6 +457,19 @@ AC_ARG_ENABLE([wayland],
AC_MSG_CHECKING([whether wayland support is enabled])
AC_MSG_RESULT([${e_cv_want_wayland_only}])
+# define the openweathermap api key
+
+AC_ARG_WITH([openweathermap-api-key],
+ [AC_HELP_STRING([--with-openweathermap-api-key=OPENWEATHERMAP_API_KEY], [specify a custom openweathermap api key])],
+ [
+ v=$withval;
+ openweathermap_api_key=$v
+ echo " Enlightenment openweathermap api key explicitly set to "$openweathermap_api_key;
+ ],
+ [openweathermap_api_key=81947d7198f4efa1cc88080be5cc039a])
+AC_SUBST(openweathermap_api_key)
+
+
# doxygen program for documentation building
EFL_CHECK_DOXYGEN([build_doc="yes"], [build_doc="no"])
@@ -915,6 +928,7 @@ AC_E_OPTIONAL_MODULE([xwayland], $have_wayland_dep, [CHECK_MODULE_XWAYLAND])
AC_E_OPTIONAL_MODULE([wireless], true)
AC_E_OPTIONAL_MODULE([time], true)
AC_E_OPTIONAL_MODULE([sysinfo], true)
+AC_E_OPTIONAL_MODULE([weather], 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])
@@ -1145,6 +1159,7 @@ src/modules/packagekit/module.desktop
src/modules/wl_desktop_shell/module.desktop
src/modules/wireless/module.desktop
src/modules/time/module.desktop
+src/modules/weather/module.desktop
src/modules/luncher/module.desktop
src/modules/sysinfo/module.desktop
data/xsession/enlightenment.desktop
diff --git a/src/bin/e_module.c b/src/bin/e_module.c
index 8af6458184..fe55a353f6 100644
--- a/src/bin/e_module.c
+++ b/src/bin/e_module.c
@@ -1058,6 +1058,7 @@ _e_module_whitelist_check(void)
"policy_mobile",
"geolocation",
"xwayland",
+ "weather",
NULL // end marker
};
diff --git a/src/modules/Makefile.mk b/src/modules/Makefile.mk
index bb2a65ffe1..1b7573279e 100644
--- a/src/modules/Makefile.mk
+++ b/src/modules/Makefile.mk
@@ -138,3 +138,5 @@ include src/modules/Makefile_sysinfo.mk
include src/modules/Makefile_wireless.mk
include src/modules/Makefile_time.mk
+
+include src/modules/Makefile_weather.mk
diff --git a/src/modules/Makefile_weather.mk b/src/modules/Makefile_weather.mk
new file mode 100644
index 0000000000..c61c68d4f5
--- /dev/null
+++ b/src/modules/Makefile_weather.mk
@@ -0,0 +1,29 @@
+EXTRA_DIST += src/modules/weather/module.desktop.in \
+src/modules/weather/e-module-weather.edj
+
+if USE_MODULE_WEATHER
+weatherdir = $(MDIR)/weather
+weather_DATA = src/modules/weather/e-module-weather.edj \
+ src/modules/weather/module.desktop
+
+
+weatherpkgdir = $(MDIR)/weather/$(MODULE_ARCH)
+weatherpkg_LTLIBRARIES = src/modules/weather/module.la
+
+src_modules_weather_module_la_LIBADD = $(MOD_LIBS)
+src_modules_weather_module_la_CPPFLAGS = $(MOD_CPPFLAGS) -DOPENWEATHERMAP_API_KEY=\"@openweathermap_api_key@\"
+src_modules_weather_module_la_LDFLAGS = $(MOD_LDFLAGS)
+src_modules_weather_module_la_SOURCES = \
+src/modules/weather/config.c \
+src/modules/weather/mod.c \
+src/modules/weather/weather.c \
+src/modules/weather/weather.h \
+src/modules/weather/plugin.c \
+src/modules/weather/plugin.h \
+src/modules/weather/plugin_openweathermap.c \
+src/modules/weather/plugin_openweathermap.h
+
+PHONIES += weather install-weather
+weather: $(weatherpkg_LTLIBRARIES) $(weather_DATA)
+install-weather: install-weatherDATA install-weatherpkgLTLIBRARIES
+endif
diff --git a/src/modules/weather/config.c b/src/modules/weather/config.c
new file mode 100644
index 0000000000..302d440dfb
--- /dev/null
+++ b/src/modules/weather/config.c
@@ -0,0 +1,197 @@
+#include "weather.h"
+#include "plugin.h"
+#include <e.h>
+
+static Weather *_tmp_weather = NULL;
+
+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_close(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+ weather_config->config_dialog = NULL;
+ eina_stringshare_del(_tmp_weather->city);
+ eina_stringshare_del(_tmp_weather->country);
+ E_FREE(_tmp_weather);
+}
+
+static void
+_config_weather_request(Config_Item *ci)
+{
+ if (!_tmp_weather)
+ _tmp_weather = E_NEW(Weather, 1);
+ eina_stringshare_replace(&_tmp_weather->city, ci->city);
+ eina_stringshare_replace(&_tmp_weather->country, ci->country);
+ weather_plugin_request(_tmp_weather);
+}
+
+static void
+_config_weather_city_changed(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+ const char *city;
+ Config_Item *ci;
+
+ ci = data;
+
+ city = elm_entry_entry_get(obj);
+ eina_stringshare_replace(&ci->city, city);
+ _config_weather_request(ci);
+}
+
+static void
+_config_weather_country_changed(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+ const char *country;
+ Config_Item *ci;
+
+ ci = data;
+
+ country = elm_entry_entry_get(obj);
+ eina_stringshare_replace(&ci->country, country);
+}
+
+
+static void
+_config_weather_temperature_unit_changed(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+ Config_Item *ci;
+
+ ci = data;
+
+ ci->use_celcius = elm_check_state_get(obj);
+}
+
+static void
+_config_weather_speed_unit_changed(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+ Config_Item *ci;
+
+ ci = data;
+
+ ci->use_metric = elm_check_state_get(obj);
+}
+
+static void
+_config_weather_24h_format_changed(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+ Config_Item *ci;
+
+ ci = data;
+
+ ci->use_24h = elm_check_state_get(obj);
+}
+
+EINTERN Evas_Object *
+config_weather(Config_Item *ci, E_Zone *zone)
+{
+ Evas_Object *popup, *tb, *fr, *o;
+ int row = 0;
+
+ if (!zone) zone = e_zone_current_get();
+
+ 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);
+
+ _config_label_add(tb, _("City name:"), row++);
+
+ fr = elm_frame_add(tb);
+ elm_object_style_set(fr, "pad_medium");
+ E_FILL(fr);
+ E_EXPAND(fr);
+ elm_table_pack(tb, fr, 0, row++, 2, 1);
+ evas_object_show(fr);
+
+ o = elm_entry_add(tb);
+ elm_entry_single_line_set(o, EINA_TRUE);
+ elm_entry_scrollable_set(o, EINA_TRUE);
+ E_FILL(o);
+ evas_object_show(o);
+ elm_object_focus_set(o, EINA_TRUE);
+ evas_object_smart_callback_add(o, "changed,user", _config_weather_city_changed, ci);
+ elm_object_part_text_set(o, "guide", _("Your city"));
+ elm_object_content_set(fr, o);
+ evas_object_show(o);
+
+ _config_label_add(tb, _("Country name:"), row++);
+
+ fr = elm_frame_add(tb);
+ elm_object_style_set(fr, "pad_medium");
+ E_FILL(fr);
+ E_EXPAND(fr);
+ elm_table_pack(tb, fr, 0, row++, 2, 1);
+ evas_object_show(fr);
+
+ o = elm_entry_add(tb);
+ elm_entry_single_line_set(o, EINA_TRUE);
+ elm_entry_scrollable_set(o, EINA_TRUE);
+ E_FILL(o);
+ evas_object_show(o);
+ elm_object_focus_set(o, EINA_TRUE);
+ evas_object_smart_callback_add(o, "changed,user", _config_weather_country_changed, ci);
+ elm_object_part_text_set(o, "guide", _("Your country"));
+ elm_object_content_set(fr, o);
+ evas_object_show(o);
+
+
+ _config_label_add(tb, _("Temperature unit:"), row);
+ o = elm_check_add(tb);
+ E_FILL(o);
+ elm_object_style_set(o, "toggle");
+ elm_object_part_text_set(o, "off", _("Farhenheit"));
+ elm_object_part_text_set(o, "on", _("Celcius"));
+ elm_table_pack(tb, o, 1, row++, 1, 1);
+ evas_object_smart_callback_add(o, "changed", _config_weather_temperature_unit_changed, ci);
+ evas_object_show(o);
+
+ _config_label_add(tb, _("Speed unit:"), row);
+ o = elm_check_add(tb);
+ E_FILL(o);
+ elm_object_style_set(o, "toggle");
+ elm_object_part_text_set(o, "off", _("Imperial (mph)"));
+ elm_object_part_text_set(o, "on", _("Metric (kmh)"));
+ elm_table_pack(tb, o, 1, row++, 1, 1);
+ evas_object_smart_callback_add(o, "changed", _config_weather_speed_unit_changed, ci);
+ evas_object_show(o);
+
+ _config_label_add(tb, _("24 hour format:"), row);
+ o = elm_check_add(tb);
+ E_FILL(o);
+ elm_object_style_set(o, "toggle");
+ elm_object_part_text_set(o, "off", _("Disabled"));
+ elm_object_part_text_set(o, "on", _("Enabled"));
+ elm_table_pack(tb, o, 1, row++, 1, 1);
+ evas_object_smart_callback_add(o, "changed", _config_weather_24h_format_changed, ci);
+ evas_object_show(o);
+
+
+ popup = e_comp_object_util_add(popup, E_COMP_OBJECT_TYPE_NONE);
+ evas_object_layer_set(popup, E_LAYER_POPUP);
+ evas_object_move(popup, zone->x, zone->y);
+ evas_object_resize(popup, zone->w / 4, zone->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 weather_config->config_dialog = popup;
+}
+
+
diff --git a/src/modules/weather/e-module-weather.edj b/src/modules/weather/e-module-weather.edj
new file mode 100644
index 0000000000..72973357fa
--- /dev/null
+++ b/src/modules/weather/e-module-weather.edj
Binary files differ
diff --git a/src/modules/weather/mod.c b/src/modules/weather/mod.c
new file mode 100644
index 0000000000..cd7b323e9b
--- /dev/null
+++ b/src/modules/weather/mod.c
@@ -0,0 +1,104 @@
+#include <e.h>
+#include "weather.h"
+#include "plugin.h"
+
+static E_Config_DD *conf_edd = NULL;
+static E_Config_DD *conf_item_edd = NULL;
+
+EINTERN void
+weather_init(E_Module *m)
+{
+ 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, city, STR);
+ E_CONFIG_VAL(D, T, country, STR);
+ E_CONFIG_VAL(D, T, geo_id, STR);
+ E_CONFIG_VAL(D, T, use_celcius, UCHAR);
+ E_CONFIG_VAL(D, T, use_metric, UCHAR);
+ E_CONFIG_VAL(D, T, use_24h, UCHAR);
+
+ 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);
+
+ weather_config = e_config_domain_load("module.weather", conf_edd);
+
+ if (!weather_config)
+ weather_config = E_NEW(Config, 1);
+ weather_plugin_init();
+
+ weather_config->module = m;
+
+ e_gadget_type_add("Weather small", weather_small_create, weather_small_wizard);
+ e_gadget_type_add("Weather big", weather_big_create, weather_big_wizard);
+
+}
+
+EINTERN void
+weather_shutdown(void)
+{
+ weather_plugin_shutdown();
+ if (weather_config)
+ {
+ Config_Item *ci;
+#if 0
+ if (weather_config->config_dialog)
+ {
+ evas_object_hide(time_config->config_dialog);
+ evas_object_del(weather_config->config_dialog);
+ }
+#endif
+
+ EINA_LIST_FREE(weather_config->items, ci)
+ {
+ eina_stringshare_del(ci->city);
+ eina_stringshare_del(ci->country);
+ eina_stringshare_del(ci->geo_id);
+ free(ci);
+ }
+
+ E_FREE(weather_config);
+ }
+ E_CONFIG_DD_FREE(conf_edd);
+ E_CONFIG_DD_FREE(conf_item_edd);
+
+ e_gadget_type_del("Weather small");
+ e_gadget_type_del("Weather big");
+}
+
+/* module setup */
+E_API E_Module_Api e_modapi =
+{
+ E_MODULE_API_VERSION,
+ "Weather"
+};
+
+E_API void *
+e_modapi_init(E_Module *m)
+{
+ if (!E_EFL_VERSION_MINIMUM(1, 17, 99)) return NULL;
+ weather_init(m);
+ return m;
+}
+
+E_API int
+e_modapi_shutdown(E_Module *m EINA_UNUSED)
+{
+ weather_shutdown();
+ return 1;
+}
+
+E_API int
+e_modapi_save(E_Module *m EINA_UNUSED)
+{
+ e_config_domain_save("module.weather", conf_edd, weather_config);
+ return 1;
+}
+
diff --git a/src/modules/weather/module.desktop.in b/src/modules/weather/module.desktop.in
new file mode 100644
index 0000000000..244cecace9
--- /dev/null
+++ b/src/modules/weather/module.desktop.in
@@ -0,0 +1,7 @@
+[Desktop Entry]
+Encoding=UTF-8
+Type=Link
+Name=Weather
+Comment=Displaying current weather and prevision about it
+Icon=e-module-weather
+X-Enlightenment-ModuleType=utils
diff --git a/src/modules/weather/plugin.c b/src/modules/weather/plugin.c
new file mode 100644
index 0000000000..abe6dd8818
--- /dev/null
+++ b/src/modules/weather/plugin.c
@@ -0,0 +1,234 @@
+#include <e.h>
+#include "weather.h"
+#include "plugin.h"
+#include "plugin_openweathermap.h"
+
+static Eina_Bool _gather_weather_all(void *data);
+
+static Eina_List *plugins = NULL;
+static Eina_List *weathers = NULL;
+static Ecore_Timer *timer = NULL;
+static Eina_Binbuf *buffer = NULL;
+static Eina_List *handlers = NULL;
+static Eina_List *_cur_weather = NULL;
+static Eina_List *_cur_plugin = NULL;
+static Weather *_cur_request = NULL;
+
+static void
+_gather_current_plugin(void)
+{
+ Weather_Plugin *wp;
+ const char *uri;
+ Ecore_Con_Url *url_con;
+ Weather *w;
+
+ wp = eina_list_data_get(_cur_plugin);
+ w = (_cur_request ? _cur_request : eina_list_data_get(_cur_weather));
+ fprintf(stderr, "gather info for %s\n", w->city);
+ if (!w || !wp) return;
+ uri = wp->func.uri_get(w);
+ fprintf(stderr, "gather info from %s\n", uri);
+ url_con = ecore_con_url_new(uri);
+ ecore_con_url_get(url_con);
+ eina_stringshare_del(uri);
+}
+
+static Eina_Bool
+_gather_weather(void *data EINA_UNUSED)
+{
+ Weather *w;
+ timer = NULL;
+ _cur_plugin = plugins;
+ w = (_cur_request ? _cur_request : eina_list_data_get(_cur_weather));
+ fprintf(stderr, "gather %x data %s %d\n", _cur_weather, w->city, w->translated);
+ _gather_current_plugin();
+ return ECORE_CALLBACK_CANCEL;
+}
+
+static Eina_Bool
+_gather_weather_all(void *data EINA_UNUSED)
+{
+ timer = NULL;
+ fprintf(stderr, "Gather weather data %d %d\n",
+ eina_list_count(weathers), eina_list_count(plugins));
+ _cur_weather = weathers;
+ _gather_weather(NULL);
+
+ return ECORE_CALLBACK_CANCEL;
+}
+
+static Eina_Bool
+_url_complete(void *data, int type EINA_UNUSED, void *event EINA_UNUSED)
+{
+ const unsigned char *buf;
+ size_t size;
+ Eina_List *l;
+ Instance *inst;
+ Weather_Plugin *wp;
+ Weather *w;
+
+ if (data != buffer) return ECORE_CALLBACK_PASS_ON;
+
+ buf = eina_binbuf_string_get(buffer);
+ size = eina_binbuf_length_get(buffer);
+
+ wp = eina_list_data_get(_cur_plugin);
+ w = (_cur_request ? _cur_request : eina_list_data_get(_cur_weather));
+ if (!wp || !w) return ECORE_CALLBACK_DONE;
+ fprintf(stderr, "gather complete %s %d\n", w->city, w->translated);
+ wp->func.parse(w, buf, size);
+ eina_binbuf_reset(buffer);
+
+ EINA_LIST_FOREACH(weather_instances, l, inst)
+ {
+ if (inst->weather == w)
+ weather_gadget_update(inst);
+ }
+ _cur_plugin = eina_list_next(_cur_plugin);
+ if (!_cur_plugin)
+ {
+ if (_cur_request)
+ _cur_request = NULL;
+ _cur_weather = eina_list_next(_cur_weather);
+ if (!_cur_weather)
+ {
+ if (timer)
+ ecore_timer_del(timer);
+ timer = ecore_timer_add(36.0, _gather_weather_all, NULL);
+ }
+ else
+ {
+ if (timer)
+ ecore_timer_del(timer);
+ timer = ecore_timer_add(5.0, _gather_weather, NULL);
+ }
+ }
+ else
+ {
+ _gather_current_plugin();
+ }
+
+ return ECORE_CALLBACK_DONE;
+}
+
+static Eina_Bool
+_url_data(void *data, int type EINA_UNUSED, void *event)
+{
+ Ecore_Con_Event_Url_Data *ev;
+
+ if (data != buffer) return ECORE_CALLBACK_PASS_ON;
+ ev = event;
+
+ if (ev->size > 0)
+ {
+ eina_binbuf_append_length(buffer, ev->data, ev->size);
+ }
+
+ return ECORE_CALLBACK_DONE;
+}
+
+EINTERN void
+weather_plugin_request(Weather *w)
+{
+ _cur_plugin = plugins;
+ _cur_request = w;
+ _gather_weather(NULL);
+}
+
+
+EINTERN void
+weather_plugin_init(void)
+{
+ Weather_Plugin *wp;
+
+ buffer = eina_binbuf_new();
+ E_LIST_HANDLER_APPEND(handlers, ECORE_CON_EVENT_URL_COMPLETE,
+ _url_complete, buffer);
+ E_LIST_HANDLER_APPEND(handlers, ECORE_CON_EVENT_URL_DATA,
+ _url_data, buffer);
+
+ wp = plugin_openweathermap_create();
+ plugins = eina_list_append(plugins, wp);
+}
+
+EINTERN void
+weather_plugin_shutdown(void)
+{
+ Weather_Plugin *wp;
+
+ EINA_LIST_FREE(plugins, wp)
+ {
+ eina_stringshare_del(wp->name);
+ free(wp);
+ }
+
+ E_FREE_LIST(handlers, ecore_event_handler_del);
+ eina_binbuf_free(buffer);
+}
+
+EINTERN void
+weather_plugin_weather_add(Instance *inst)
+{
+ Weather *wl;
+ Eina_List *l;
+
+ if ((!inst->cfg->city) && (!inst->cfg->country) && (!inst->cfg->geo_id))
+ return;
+ EINA_LIST_FOREACH(weathers, l, wl)
+ {
+ if ((inst->cfg->geo_id) && (inst->cfg->geo_id == wl->geo_id))
+ break;
+ if ((inst->cfg->city && inst->cfg->country)
+ && ((inst->cfg->city == wl->city)
+ && (inst->cfg->country == wl->country)))
+ break;
+ if ((inst->cfg->city) && (inst->cfg->city == wl->city))
+ break;
+ }
+ if (l)
+ {
+ fprintf(stderr, "found weather %s %s %s\n",
+ inst->weather->geo_id, inst->weather->city, inst->weather->country);
+ inst->weather = wl;
+ if (timer)
+ {
+ ecore_timer_del(timer);
+ timer = NULL;
+ }
+ timer = ecore_timer_add(1.0, _gather_weather_all, NULL);
+
+ return;
+ }
+ fprintf(stderr, "create a new weather %s %s %s\n",
+ inst->cfg->geo_id, inst->cfg->city, inst->cfg->country);
+ inst->weather = E_NEW(Weather, 1);
+ inst->weather->geo_id = eina_stringshare_add(inst->cfg->geo_id);
+ inst->weather->city = eina_stringshare_add(inst->cfg->city);
+ inst->weather->country = eina_stringshare_add(inst->cfg->country);
+ weathers = eina_list_append(weathers, inst->weather);
+ if (timer)
+ {
+ ecore_timer_del(timer);
+ }
+ timer = ecore_timer_add(1.0, _gather_weather_all, NULL);
+}
+
+EINTERN void
+weather_plugin_weather_remove(Instance *inst)
+{
+ Instance *inst_search;
+ Eina_List *l;
+
+ if (!inst->weather) return;
+ EINA_LIST_FOREACH(weather_instances, l, inst_search)
+ {
+ if (inst_search->weather == inst->weather)
+ break;
+ }
+ if (!l)
+ {
+ weather_free(inst->weather);
+ weathers = eina_list_remove(weathers, inst->weather);
+ }
+}
+
diff --git a/src/modules/weather/plugin.h b/src/modules/weather/plugin.h
new file mode 100644
index 0000000000..2906c4200d
--- /dev/null
+++ b/src/modules/weather/plugin.h
@@ -0,0 +1,33 @@
+#ifndef WEATHER_PLUGIN_H
+#define WEATHER_PLUGIN_H
+
+typedef const char *(*Weather_Plugin_Uri) (Weather *wd);
+typedef Eina_Bool (*Weather_Plugin_Parse) (Weather *wd, const unsigned char *parse, size_t size);
+
+typedef enum _Weather_Plugin_Type
+{
+ WEATHER_PLUGIN_GEOLOC,
+ WEATHER_PLUGIN_WEATHER_DAY,
+ WEATHER_PLUGIN_WEATHER_HOUR,
+} Weather_Plugin_Type;
+
+typedef struct _Weather_Plugin
+{
+ const char *name;
+ Weather_Plugin_Type type;
+ Eina_Binbuf *buf;
+ struct {
+ Weather_Plugin_Uri uri_get;
+ Weather_Plugin_Parse parse;
+ } func;
+} Weather_Plugin;
+
+EINTERN void weather_plugin_init(void);
+EINTERN void weather_plugin_shutdown(void);
+EINTERN void weather_plugin_weather_add(Instance *inst);
+EINTERN void weather_plugin_request(Weather *w);
+EINTERN void weather_plugin_weather_remove(Instance *inst);
+
+
+
+#endif /* WEATHER_PLUGIN_H */
diff --git a/src/modules/weather/plugin_openweathermap.c b/src/modules/weather/plugin_openweathermap.c
new file mode 100644
index 0000000000..cfb7adfb0c
--- /dev/null
+++ b/src/modules/weather/plugin_openweathermap.c
@@ -0,0 +1,540 @@
+#define _GNU_SOURCE 1
+#include <time.h>
+#include <e.h>
+#include "weather.h"
+#include "plugin.h"
+
+
+#define WEATHER_URL "api.openweathermap.org/data/2.5/forecast/"
+#define WEATHER_CITY "weather?q=%s"
+#define WEATHER_CITY_COUNTRY "weather?q=%s,%s"
+#define WEATHER_ID "weather?id=%s"
+#define WEATHER_PARAMS "&units=metric&mode=xml"
+#define WEATHER_API_KEY "&APPID=" OPENWEATHERMAP_API_KEY
+
+typedef enum Weather_Tag_
+{
+ WEATHER_TAG_NONE = 0,
+ WEATHER_TAG_CITY = (1 << 0),
+ WEATHER_TAG_COUNTRY = (1 << 1),
+ WEATHER_TAG_LOCATION = (1 << 2)
+} Weather_Tag;
+
+static Weather_Tag _xml_tag = 0;
+static Weather_Data *_current_wd = NULL;
+
+static Eina_Bool
+_location_attr(void *data, const char *key, const char *value)
+{
+ Weather *weather;
+
+ weather = data;
+
+ if (!strncmp(key, "altitude", strlen("altitude")))
+ weather->altitude = atoi(value);
+ else if (!strncmp(key, "latitude", strlen("latitude")))
+ weather->latitude = atof(value);
+ else if (!strncmp(key, "longitude", strlen("longitude")))
+ weather->longitude = atof(value);
+
+ return EINA_TRUE;
+
+}
+
+static Eina_Bool
+_sun_attr(void *data, const char *key, const char *value)
+{
+ Weather *weather;
+
+ weather = data;
+
+ if (!strncmp(key, "rise", strlen("rise")))
+ strptime(value, "%Y-%m-%dT%H:%M:%S", &weather->sunrise);
+ if (!strncmp(key, "set", strlen("set")))
+ strptime(value, "%Y-%m-%dT%H:%M:%S", &weather->sunset);
+
+ return EINA_TRUE;
+}
+
+static Eina_Bool
+_time_attr(void *data, const char *key, const char *value)
+{
+ Weather *weather;
+ Weather_Data *wd = NULL;
+ struct tm time_start;
+ Eina_List *l;
+
+ weather = data;
+
+ if (!strncmp(key, "from", strlen("from")))
+ {
+ strptime(value, "%Y-%m-%dT%H:%M:%S", &time_start);
+ EINA_LIST_FOREACH(weather->datas, l, wd)
+ {
+ if ((wd->time_start.tm_hour == time_start.tm_hour)
+ && (wd->time_start.tm_yday == time_start.tm_yday)
+ && (wd->time_start.tm_year == time_start.tm_year))
+ break;
+ }
+ if (!wd)
+ {
+ wd = E_NEW(Weather_Data, 1);
+ memcpy(&wd->time_start, &time_start, sizeof(struct tm));
+ weather->datas = eina_list_append(weather->datas, wd);
+ }
+ _current_wd = wd;
+ wd->updated = EINA_TRUE;
+ }
+ if (!strncmp(key, "to", strlen("to")))
+ strptime(value, "%Y-%m-%dT%H:%M:%S", &_current_wd->time_end);
+
+
+ return EINA_TRUE;
+}
+
+static Eina_Bool
+_symbol_attr(void *data EINA_UNUSED, const char *key, const char *value)
+{
+ Weather_Data *wd;
+ int type;
+
+ wd = _current_wd;
+
+ if (!strncmp(key, "name", strlen("name")))
+ eina_stringshare_replace(&wd->state_name, value);
+ if (!strncmp(key, "number", strlen("number")))
+ {
+ type = atoi(value);
+ switch (type)
+ {
+ case 200: wd->state = WEATHER_STATE_THUNDERSTORM_RAIN_LIGHT; break;
+ case 201: wd->state = WEATHER_STATE_THUNDERSTORM_RAIN; break;
+ case 202: wd->state = WEATHER_STATE_THUNDERSTORM_RAIN_HEAVY; break;
+ case 210: wd->state = WEATHER_STATE_THUNDERSTORM_LIGHT; break;
+ case 211: wd->state = WEATHER_STATE_THUNDERSTORM; break;
+ case 212: wd->state = WEATHER_STATE_THUNDERSTORM_HEAVY; break;
+ case 221: wd->state = WEATHER_STATE_THUNDERSTORM_RAGGED; break;
+ case 230: wd->state = WEATHER_STATE_THUNDERSTORM_DRIZZLE_LIGHT; break;
+ case 231: wd->state = WEATHER_STATE_THUNDERSTORM_DRIZZLE; break;
+ case 232: wd->state = WEATHER_STATE_THUNDERSTORM_DRIZZLE_HEAVY; break;
+ case 300: wd->state = WEATHER_STATE_DRIZZLE_LIGHT; break;
+ case 301: wd->state = WEATHER_STATE_DRIZZLE; break;
+ case 302: wd->state = WEATHER_STATE_DRIZZLE_HEAVY; break;
+ case 310: wd->state = WEATHER_STATE_DRIZZLE_RAIN_LIGHT; break;
+ case 311: wd->state = WEATHER_STATE_DRIZZLE_RAIN; break;
+ case 312: wd->state = WEATHER_STATE_DRIZZLE_RAIN_HEAVY; break;
+ case 313: wd->state = WEATHER_STATE_DRIZZLE_RAIN_SHOWER; break;
+ case 314: wd->state = WEATHER_STATE_DRIZZLE_RAIN_SHOWER_HEAVY; break;
+ case 321: wd->state = WEATHER_STATE_DRIZZLE_SHOWER; break;
+ case 500: wd->state = WEATHER_STATE_RAIN_LIGHT; break;
+ case 501: wd->state = WEATHER_STATE_RAIN; break;
+ case 502: wd->state = WEATHER_STATE_RAIN_HEAVY; break;
+ case 503: wd->state = WEATHER_STATE_RAIN_VERY_HEAVY; break;
+ case 504: wd->state = WEATHER_STATE_RAIN_EXTREME; break;
+ case 511: wd->state = WEATHER_STATE_RAIN_FREEZING; break;
+ case 520: wd->state = WEATHER_STATE_RAIN_SHOWER_LIGHT; break;
+ case 521: wd->state = WEATHER_STATE_RAIN_SHOWER; break;
+ case 522: wd->state = WEATHER_STATE_RAIN_SHOWER_HEAVY; break;
+ case 531: wd->state = WEATHER_STATE_RAIN_RAGGED; break;
+ case 600: wd->state = WEATHER_STATE_SNOW_LIGHT; break;
+ case 601: wd->state = WEATHER_STATE_SNOW; break;
+ case 602: wd->state = WEATHER_STATE_SNOW_HEAVY; break;
+ case 611: wd->state = WEATHER_STATE_SLEET; break;
+ case 612: wd->state = WEATHER_STATE_SLEET_SHOWER; break;
+ case 615: wd->state = WEATHER_STATE_SNOW_RAIN_LIGHT; break;
+ case 616: wd->state = WEATHER_STATE_SNOW_RAIN; break;
+ case 620: wd->state = WEATHER_STATE_SNOW_SHOWER_LIGHT; break;
+ case 621: wd->state = WEATHER_STATE_SNOW_SHOWER; break;
+ case 622: wd->state = WEATHER_STATE_SNOW_SHOWER_HEAVY; break;
+ case 701: wd->state = WEATHER_STATE_MIST; break;
+ case 711: wd->state = WEATHER_STATE_SMOKE; break;
+ case 721: wd->state = WEATHER_STATE_HAZE; break;
+ case 731: wd->state = WEATHER_STATE_DUST_WHIRLS; break;
+ case 741: wd->state = WEATHER_STATE_FOG; break;
+ case 751: wd->state = WEATHER_STATE_SAND; break;
+ case 761: wd->state = WEATHER_STATE_DUST; break;
+ case 762: wd->state = WEATHER_STATE_VOLCANIC_ASH; break;
+ case 771: wd->state = WEATHER_STATE_SQUALLS; break;
+ case 900:
+ case 781: wd->state = WEATHER_STATE_TORNADO; break;
+ case 800: wd->state = WEATHER_STATE_CLEAR_SKY; break;
+ case 801: wd->state = WEATHER_STATE_FEW_CLOUDS; break;
+ case 802: wd->state = WEATHER_STATE_SCATTERED_CLOUDS; break;
+ case 803: wd->state = WEATHER_STATE_BROKEN_CLOUDS; break;
+ case 804: wd->state = WEATHER_STATE_OVERCAST_CLOUDS; break;
+ case 901: wd->state = WEATHER_STATE_TROPICAL_STORM; break;
+ case 902: wd->state = WEATHER_STATE_HURRICANE; break;
+ case 903: wd->state = WEATHER_STATE_COLD; break;
+ case 904: wd->state = WEATHER_STATE_HOT; break;
+ case 905: wd->state = WEATHER_STATE_WINDY; break;
+ case 906: wd->state = WEATHER_STATE_HAIL; break;
+ }
+ }
+
+ return EINA_TRUE;
+}
+
+static Eina_Bool
+_precipitation_attr(void *data EINA_UNUSED, const char *key, const char *value)
+{
+ Weather_Data *wd;
+
+ wd = _current_wd;
+
+ if (!strncmp(key, "type", strlen("type")))
+ eina_stringshare_replace(&wd->precipitation.type, value);
+ if (!strncmp(key, "value", strlen("value")))
+ wd->precipitation.value = atof(value);
+
+ return EINA_TRUE;
+}
+
+static Eina_Bool
+_wind_direction_attr(void *data EINA_UNUSED, const char *key, const char *value)
+{
+ Weather_Data *wd;
+
+ wd = _current_wd;
+
+ if (!strncmp(key, "deg", strlen("deg")))
+ wd->wind.direction_value = atof(value);
+ else if (!strncmp(key, "code", strlen("code")))
+ eina_stringshare_replace(&wd->wind.direction, value);
+ else if (!strncmp(key, "name", strlen("name")))
+ eina_stringshare_replace(&wd->wind.direction_name, value);
+
+ return EINA_TRUE;
+}
+
+static Eina_Bool
+_wind_speed_attr(void *data EINA_UNUSED, const char *key, const char *value)
+{
+ Weather_Data *wd;
+
+ wd = _current_wd;
+
+ if (!strncmp(key, "mps", strlen("mps")))
+ wd->wind.speed = atof(value);
+ else if (!strncmp(key, "name", strlen("name")))
+ eina_stringshare_replace(&wd->wind.name, value);
+
+ return EINA_TRUE;
+}
+
+static Eina_Bool
+_temperature_attr(void *data EINA_UNUSED, const char *key, const char *value)
+{
+ Weather_Data *wd;
+
+ wd = _current_wd;
+
+ if (!strncmp(key, "unit", strlen("unit")))
+ eina_stringshare_replace(&wd->temperature.unit, value);
+ else if (!strncmp(key, "value", strlen("value")))
+ wd->temperature.value = atof(value);
+ else if (!strncmp(key, "min", strlen("min")))
+ wd->temperature.value_min = atof(value);
+ else if (!strncmp(key, "max", strlen("max")))
+ wd->temperature.value_max = atof(value);
+
+ return EINA_TRUE;
+}
+
+static Eina_Bool
+_pressure_attr(void *data EINA_UNUSED, const char *key, const char *value)
+{
+ Weather_Data *wd;
+
+ wd = _current_wd;
+
+ if (!strncmp(key, "unit", strlen("unit")))
+ eina_stringshare_replace(&wd->pressure.unit, value);
+ else if (!strncmp(key, "value", strlen("value")))
+ wd->pressure.value = atof(value);
+
+ return EINA_TRUE;
+}
+
+static Eina_Bool
+_humidity_attr(void *data EINA_UNUSED, const char *key, const char *value)
+{
+ Weather_Data *wd;
+
+ wd = _current_wd;
+
+ if (!strncmp(key, "unit", strlen("unit")))
+ eina_stringshare_replace(&wd->humidity.unit, value);
+ else if (!strncmp(key, "value", strlen("value")))
+ wd->humidity.value = atof(value);
+
+ return EINA_TRUE;
+}
+
+static Eina_Bool
+_clouds_attr(void *data EINA_UNUSED, const char *key, const char *value)
+{
+ Weather_Data *wd;
+
+ wd = _current_wd;
+
+ if (!strncmp(key, "unit", strlen("unit")))
+ eina_stringshare_replace(&wd->cloud.unit, value);
+ if (!strncmp(key, "all", strlen("all")))
+ wd->cloud.value = atoi(value);
+ else if (!strncmp(key, "value", strlen("value")))
+ eina_stringshare_replace(&wd->cloud.name, value);
+
+ return EINA_TRUE;
+}
+
+
+static Eina_Bool
+_tag_cb(void *data, Eina_Simple_XML_Type type, const char *content, unsigned int offset EINA_UNUSED, unsigned int length)
+{
+ char buf[4096];
+ const char *tags;
+ Weather *weather;
+
+ weather = data;
+
+ if (type == EINA_SIMPLE_XML_OPEN)
+ {
+ if (!strncmp(content, "name", strlen("name")))
+ _xml_tag = WEATHER_TAG_CITY;
+ else if (!strncmp(content, "country", strlen("country")))
+ _xml_tag = WEATHER_TAG_COUNTRY;
+ else if (!strncmp(content, "location", strlen("location")))
+ {
+ if (weather->plugin_error) weather->plugin_error = EINA_FALSE;
+ tags = eina_simple_xml_tag_attributes_find(content, length);
+ eina_simple_xml_attributes_parse(tags,
+ length - (tags - content),
+ _location_attr, weather);
+ }
+ else if (!strncmp(content, "sun", strlen("sun")))
+ {
+ tags = eina_simple_xml_tag_attributes_find(content, length);
+ eina_simple_xml_attributes_parse(tags,
+ length - (tags - content),
+ _sun_attr, weather);
+ }
+ else if (!strncmp(content, "timezone", strlen("timezone")))
+ {
+ }
+ else if (!strncmp(content, "time", strlen("time")))
+ {
+ tags = eina_simple_xml_tag_attributes_find(content, length);
+ eina_simple_xml_attributes_parse(tags,
+ length - (tags - content),
+ _time_attr, weather);
+ }
+ else if (!strncmp(content, "symbol", strlen("symbol")))
+ {
+ tags = eina_simple_xml_tag_attributes_find(content, length);
+ eina_simple_xml_attributes_parse(tags,
+ length - (tags - content),
+ _symbol_attr, weather);
+ }
+ else if (!strncmp(content, "precipitation", strlen("precipitation")))
+ {
+ tags = eina_simple_xml_tag_attributes_find(content, length);
+ eina_simple_xml_attributes_parse(tags,
+ length - (tags - content),
+ _precipitation_attr, weather);
+ }
+ else if (!strncmp(content, "windDirection", strlen("windDirection")))
+ {
+ tags = eina_simple_xml_tag_attributes_find(content, length);
+ eina_simple_xml_attributes_parse(tags,
+ length - (tags - content),
+ _wind_direction_attr, weather);
+ }
+ else if (!strncmp(content, "windSpeed", strlen("windSpeed")))
+ {
+ tags = eina_simple_xml_tag_attributes_find(content, length);
+ eina_simple_xml_attributes_parse(tags,
+ length - (tags - content),
+ _wind_speed_attr, weather);
+ }
+ else if (!strncmp(content, "temperature", strlen("temperature")))
+ {
+ tags = eina_simple_xml_tag_attributes_find(content, length);
+ eina_simple_xml_attributes_parse(tags,
+ length - (tags - content),
+ _temperature_attr, weather);
+ }
+ else if (!strncmp(content, "pressure", strlen("pressure")))
+ {
+ tags = eina_simple_xml_tag_attributes_find(content, length);
+ eina_simple_xml_attributes_parse(tags,
+ length - (tags - content),
+ _pressure_attr, weather);
+ }
+ else if (!strncmp(content, "humidity", strlen("humidity")))
+ {
+ tags = eina_simple_xml_tag_attributes_find(content, length);
+ eina_simple_xml_attributes_parse(tags,
+ length - (tags - content),
+ _humidity_attr, weather);
+ }
+ else if (!strncmp(content, "clouds", strlen("clouds")))
+ {
+ tags = eina_simple_xml_tag_attributes_find(content, length);
+ eina_simple_xml_attributes_parse(tags,
+ length - (tags - content),
+ _clouds_attr, weather);
+ }
+ }
+ else if (type == EINA_SIMPLE_XML_DATA)
+ {
+ snprintf(buf, length + 1, "%s", content);
+ // fprintf(stderr, "Type %s\n", buf);
+ switch (_xml_tag)
+ {
+ case WEATHER_TAG_CITY:
+ if (!weather->city)
+ eina_stringshare_replace(&weather->city, buf);
+ break;
+ case WEATHER_TAG_COUNTRY:
+ if (!weather->country)
+ eina_stringshare_replace(&weather->country, buf);
+ break;
+ case WEATHER_TAG_LOCATION:
+ case WEATHER_TAG_NONE:
+ break;
+ }
+ _xml_tag = WEATHER_TAG_NONE;
+ }
+
+ return EINA_TRUE;
+}
+
+static Eina_Bool
+_plugin_openweathermap_parse(Weather *weather, const unsigned char *buf, size_t size)
+{
+ Weather_Data *wd;
+ Eina_List *l, *ll;
+
+ printf("%s\n", buf);
+
+ weather->plugin_error = EINA_TRUE;
+ EINA_LIST_FOREACH(weather->datas, l, wd)
+ {
+ wd->updated = EINA_FALSE;
+ }
+ eina_simple_xml_parse((const char *)buf, size, EINA_TRUE, _tag_cb, weather);
+ if (!weather->plugin_error)
+ {
+ fprintf(stderr, "Openweather error %s\n", weather->city);
+ EINA_LIST_FOREACH_SAFE(weather->datas, l, ll, wd)
+ {
+ if (!wd->updated)
+ weather->datas = eina_list_remove_list(weather->datas, l);
+ }
+ }
+
+
+
+#if 0
+ fprintf(stderr, "City %s\nCountry %s\n", weather->city, weather->country);
+ fprintf(stderr, "Location alt %d geo %.5f %.5f\n", weather->altitude, weather->latitude, weather->longitude);
+ fprintf(stderr, "Sun %s %s\n", weather->sunrise, weather->sunset);
+ EINA_LIST_FOREACH(weather->datas, l, wd)
+ {
+ fprintf(stderr, "Time %02d:%02d:%02d ", wd->time_start.tm_hour, wd->time_start.tm_min, wd->time_start.tm_sec);
+// fprintf(stderr, "Value %s\n", wd->state);
+ fprintf(stderr, "\t%f min %f max %f unit %s\n", wd->temperature.value, wd->temperature.value_min, wd->temperature.value_max, wd->temperature.unit);
+ fprintf(stderr, "\t%s %f\n", wd->precipitation.type, wd->precipitation.value);
+ fprintf(stderr, "\t%s %s %s %f %f\n", wd->wind.name, wd->wind.direction_name, wd->wind.direction, wd->wind.speed);
+ fprintf(stderr, "\t%s %d %s\n", wd->cloud.name, wd->cloud.value, wd->cloud.unit);
+ fprintf(stderr, "\t%d %s\n", wd->humidity.value, wd->humidity.unit);
+ fprintf(stderr, "\t%f %s\n", wd->pressure.value, wd->pressure.unit);
+ }
+#endif
+ return weather->plugin_error;
+}
+
+static const char *
+_plugin_openweathermap_uri_get(Weather *w)
+{
+ char buf[4096];
+ char buf_lang[1024];
+ const char *lang;
+ E_Locale_Parts *lang_part = NULL;
+
+ lang = e_intl_language_get();
+ if (lang)
+ {
+ lang_part = e_intl_locale_parts_get(lang);
+ }
+
+ if (lang_part)
+ {
+ if ((!strcmp(lang_part->lang, "en"))
+ || (!strcmp(lang_part->lang, "ru"))
+ || (!strcmp(lang_part->lang, "it"))
+ || (!strcmp(lang_part->lang, "es"))
+ || (!strcmp(lang_part->lang, "uk"))
+ || (!strcmp(lang_part->lang, "de"))
+ || (!strcmp(lang_part->lang, "pt"))
+ || (!strcmp(lang_part->lang, "ro"))
+ || (!strcmp(lang_part->lang, "pl"))
+ || (!strcmp(lang_part->lang, "fi"))
+ || (!strcmp(lang_part->lang, "nl"))
+ || (!strcmp(lang_part->lang, "fr"))
+ || (!strcmp(lang_part->lang, "bg"))
+ || (!strcmp(lang_part->lang, "sv"))
+ || (!strcmp(lang_part->lang, "zh"))
+ || (!strcmp(lang_part->lang, "tr"))
+ || (!strcmp(lang_part->lang, "hr"))
+ || (!strcmp(lang_part->lang, "ca")))
+ {
+ snprintf(buf_lang, sizeof(buf_lang), "&lang=%s", lang_part->lang);
+ w->translated = EINA_TRUE;
+ }
+ else
+ *buf_lang = 0;
+ }
+ else
+ *buf_lang = 0;
+
+ if (w->geo_id)
+ snprintf(buf, sizeof(buf),
+ WEATHER_URL WEATHER_ID
+ "%s"
+ WEATHER_PARAMS WEATHER_API_KEY,
+ w->geo_id, buf_lang);
+ else if (w->country && w->city)
+ snprintf(buf, sizeof(buf),
+ WEATHER_URL WEATHER_CITY_COUNTRY
+ "%s"
+ WEATHER_PARAMS WEATHER_API_KEY,
+ w->city, w->country, buf_lang);
+ else if (w->city)
+ snprintf(buf, sizeof(buf),
+ WEATHER_URL WEATHER_CITY
+ "%s"
+ WEATHER_PARAMS WEATHER_API_KEY,
+ w->city, buf_lang);
+ else
+ *buf = 0;
+
+ if (lang_part) e_intl_locale_parts_free(lang_part);
+
+ return eina_stringshare_add(buf);
+}
+
+
+EINTERN Weather_Plugin *
+plugin_openweathermap_create(void)
+{
+ Weather_Plugin *wp;
+
+ wp = E_NEW(Weather_Plugin, 1);
+ wp->name = eina_stringshare_add("Openweathermap");
+ wp->type = WEATHER_PLUGIN_WEATHER_HOUR;
+ wp->func.uri_get = _plugin_openweathermap_uri_get;
+ wp->func.parse = _plugin_openweathermap_parse;
+
+ return wp;
+}
diff --git a/src/modules/weather/plugin_openweathermap.h b/src/modules/weather/plugin_openweathermap.h
new file mode 100644
index 0000000000..f07c4ff5f3
--- /dev/null
+++ b/src/modules/weather/plugin_openweathermap.h
@@ -0,0 +1,6 @@
+#ifndef PLUGIN_OPENWEATHERMAP_H
+#define PLUGIN_OPENWEATHERMAP_H
+
+EINTERN Weather_Plugin *plugin_openweathermap_create(void);
+
+#endif /* PLUGIN_OPENWEATHERMAP_H */
diff --git a/src/modules/weather/theme.edj b/src/modules/weather/theme.edj
new file mode 100644
index 0000000000..895763ecf4
--- /dev/null
+++ b/src/modules/weather/theme.edj
Binary files differ
diff --git a/src/modules/weather/weather.c b/src/modules/weather/weather.c
new file mode 100644
index 0000000000..ad925145b2
--- /dev/null
+++ b/src/modules/weather/weather.c
@@ -0,0 +1,811 @@
+#include "weather.h"
+#include "plugin.h"
+
+EINTERN Config *weather_config = NULL;
+EINTERN Eina_List *weather_instances = NULL;
+
+
+typedef enum _Weather_Gadget_Type
+{
+ WEATHER_GADGET_SMALL,
+ WEATHER_GADGET_BIG
+} Weather_Gadget_Type;
+
+typedef struct _Wizard_Item
+{
+ E_Gadget_Wizard_End_Cb cb;
+ void *data;
+ int id;
+} Wizard_Item;
+
+typedef struct _Weather_State_Info
+{
+ Weather_State state;
+ const char *sig_day_small;
+ const char *sig_night_small;
+ const char *sig_day_big;
+} Weather_State_Info;
+
+static void _weather_gadget_removed(void *data, Evas_Object *obj, void *event_info);
+
+static Evas_Object *_weather_create(Evas_Object *parent, Instance *inst, E_Gadget_Site_Orient orient);
+static void _weather_del(void *data, Evas *e, Evas_Object *obj, void *event);
+static void _weather_mouse_down(void *data, Evas *e, Evas_Object *obj, void *event);
+static void _weather_popup_new(Instance *inst);
+static void _weather_popup_day_segment_changed(void *data, Evas_Object *obj, void *event);
+static void _weather_popup_day_part_segment_changed(void *data, Evas_Object *obj, void *event);
+static void _weather_popup_dismissed(void *data, Evas_Object *obj, void *event);
+static void _weather_popup_del(void *data, Evas *e, Evas_Object *obj, void *event_info);
+static void _weather_update_object(Instance *inst, Evas_Object *obj, Weather_Data *wd, Eina_Bool big);
+static void _weather_wizard(E_Gadget_Wizard_End_Cb cb, void *data);
+static void _weather_wizard_end(void *data, Evas *e, Evas_Object *obj, void *event);
+static Config_Item *_conf_item_get(int *id);
+
+static Weather_State_Info _signal_table[] =
+{
+ { WEATHER_STATE_THUNDERSTORM_RAIN_LIGHT, "thunderstorm", "night_thunderstorm", "right,day_heavyrain,sun,tstorm,rain" },
+ { WEATHER_STATE_THUNDERSTORM_RAIN, "thunderstorm", "night_thunderstorm", "right,day_heavyrain,sun,tstorm,rain" },
+ { WEATHER_STATE_THUNDERSTORM_RAIN_HEAVY, "thunderstorm", "night_thunderstorm", "right,day_heavyrain,sun,tstorm,rain" },
+ { WEATHER_STATE_THUNDERSTORM_LIGHT, "thunderstorm", "night_thunderstorm", "right,day_heavyrain,sun,tstorm,rain" },
+ { WEATHER_STATE_THUNDERSTORM, "thunderstorm", "night_thunderstorm", "right,day_heavyrain,sun,tstorm,rain" },
+ { WEATHER_STATE_THUNDERSTORM_HEAVY, "thunderstorm", "night_thunderstorm", "right,day_heavyrain,sun,tstorm,rain" },
+ { WEATHER_STATE_THUNDERSTORM_RAGGED, "thunderstorm", "night_thunderstorm", "right,day_heavyrain,sun,tstorm,rain" },
+ { WEATHER_STATE_THUNDERSTORM_DRIZZLE_LIGHT, "thunderstorm", "night_thunderstorm", "right,day_heavyrain,sun,tstorm,rain" },
+ { WEATHER_STATE_THUNDERSTORM_DRIZZLE, "thunderstorm", "night_thunderstorm", "right,day_heavyrain,sun,tstorm,rain" },
+ { WEATHER_STATE_THUNDERSTORM_DRIZZLE_HEAVY, "thunderstorm", "night_thunderstorm", "right,day_heavyrain,sun,tstorm,rain" },
+ { WEATHER_STATE_DRIZZLE_LIGHT, "rain", "night_rain", "right,day_rain,sun,rain,rain" },
+ { WEATHER_STATE_DRIZZLE, "rain", "night_rain", "right,day_rain,sun,rain,rain" },
+ { WEATHER_STATE_DRIZZLE_HEAVY, "rain", "night_rain", "right,day_rain,sun,rain,rain" },
+ { WEATHER_STATE_DRIZZLE_RAIN_LIGHT, "rain", "night_rain", "right,day_rain,sun,rain,rain" },
+ { WEATHER_STATE_DRIZZLE_RAIN, "rain", "night_rain", "right,day_rain,sun,rain,rain" },
+ { WEATHER_STATE_DRIZZLE_RAIN_HEAVY, "rain", "night_rain", "right,day_rain,sun,rain,rain" },
+ { WEATHER_STATE_DRIZZLE_RAIN_SHOWER, "rain", "night_rain", "right,day_rain,sun,rain,rain" },
+ { WEATHER_STATE_DRIZZLE_RAIN_SHOWER_HEAVY, "rain", "night_rain", "right,day_rain,sun,rain,rain" },
+ { WEATHER_STATE_DRIZZLE_SHOWER, "rain", "night_rain", "right,day_rain,sun,rain,rain" },
+ { WEATHER_STATE_RAIN_LIGHT, "rain", "night_rain", "right,day_rain,sun,rain,rain" },
+ { WEATHER_STATE_RAIN, "rain", "night_rain", "right,day_rain,sun,rain,rain" },
+ { WEATHER_STATE_RAIN_HEAVY, "rain", "night_rain", "right,day_rain,sun,rain,rain" },
+ { WEATHER_STATE_RAIN_VERY_HEAVY, "rain", "night_rain", "right,day_rain,sun,rain,rain" },
+ { WEATHER_STATE_RAIN_FREEZING, "rain", "night_rain", "right,day_rain,sun,rain,rain" },
+ { WEATHER_STATE_RAIN_SHOWER_LIGHT, "rain", "night_rain", "right,day_rain,sun,rain,rain" },
+ { WEATHER_STATE_RAIN_SHOWER, "rain", "night_rain", "right,day_rain,sun,rain,rain" },
+ { WEATHER_STATE_RAIN_SHOWER_HEAVY, "rain", "night_rain", "right,day_rain,sun,rain,rain" },
+ { WEATHER_STATE_RAIN_RAGGED, "rain", "night_rain", "right,day_rain,sun,rain,rain" },
+ { WEATHER_STATE_SNOW_LIGHT, "snow", "night_snow", "right,day_rain,sun,rain,snow" },
+ { WEATHER_STATE_SNOW, "snow", "night_snow", "right,day_rain,sun,rain,snow" },
+ { WEATHER_STATE_SNOW_HEAVY, "snow", "night_snow", "right,day_rain,sun,rain,snow" },
+ { WEATHER_STATE_SLEET, "snow", "night_snow", "right,day_rain,sun,rain,rain_snow" },
+ { WEATHER_STATE_SLEET_SHOWER, "snow", "night_snow", "right,day_rain,sun,rain,rain_snow" },
+ { WEATHER_STATE_SNOW_RAIN_LIGHT, "snow", "night_snow", "right,day_rain,sun,rain,rain_snow" },
+ { WEATHER_STATE_SNOW_RAIN, "snow", "night_snow", "right,day_rain,sun,rain,rain_snow" },
+ { WEATHER_STATE_SNOW_SHOWER_LIGHT, "snow", "night_snow", "right,day_rain,sun,rain,rain_snow" },
+ { WEATHER_STATE_SNOW_SHOWER, "snow", "night_snow", "right,day_rain,sun,rain,rain_snow" },
+ { WEATHER_STATE_SNOW_SHOWER_HEAVY, "snow", "night_snow", "right,day_rain,sun,rain,rain_snow" },
+ { WEATHER_STATE_MIST, "mist", "mist", "right,day_rain,sun,cloud,foggy" },
+ { WEATHER_STATE_SMOKE, "mist", "mist", "right,day_rain,sun,cloud,foggy" },
+ { WEATHER_STATE_HAZE, "mist", "mist", "right,day_rain,sun,cloud,foggy" },
+ { WEATHER_STATE_DUST_WHIRLS, "mist", "mist", "right,day_clear,sun,isolated_cloud,windy" },
+ { WEATHER_STATE_FOG, "mist", "mist", "right,day_rain,sun,cloud,foggy" },
+ { WEATHER_STATE_DUST, "mist", "mist", "right,day_clear,sun,isolated_cloud,windy" },
+ { WEATHER_STATE_VOLCANIC_ASH, "mist", "mist", "right,day_clear,sun,isolated_cloud,windy" },
+ { WEATHER_STATE_SQUALLS, "mist", "mist", "right,day_clear,sun,isolated_cloud,windy" },
+ { WEATHER_STATE_TORNADO, "rain", "night_rain", "right,day_clear,sun,isolated_cloud,windy" },
+ { WEATHER_STATE_CLEAR_SKY, "clear", "night_clear", "right,day_clear,sun,nothing," },
+ { WEATHER_STATE_FEW_CLOUDS, "few_clouds", "night_few_clouds", "right,day_clear,sun,isolated_cloud," },
+ { WEATHER_STATE_SCATTERED_CLOUDS, "scattered_clouds", "night_scattered_clouds", "right,day_clear,sun,cloud," },
+ { WEATHER_STATE_BROKEN_CLOUDS, "broken_clouds", "night_broken_clouds", "right,day_clear,sun,cloud," },
+ { WEATHER_STATE_OVERCAST_CLOUDS, "broken_clouds", "night_broken_clouds", "right,day_clear,sun,cloud," },
+ { WEATHER_STATE_TROPICAL_STORM, "thunderstorm", "night_thunderstorm", "right,day_heavyrain,sun,tstorm,rain" },
+ { WEATHER_STATE_HURRICANE, "thunderstorm", "night_thunderstorm", "right,day_heavyrain,sun,tstorm,rain" },
+ { WEATHER_STATE_COLD, "clear", "night_clear", "right,day_clear,sun,nothing," },
+ { WEATHER_STATE_HOT, "clear", "night_clear", "right,day_clear,sun,nothing," },
+ { WEATHER_STATE_WINDY, "clear", "night_clear", "right,day_clear,sun,isolated_cloud,windy" },
+ { WEATHER_STATE_HAIL, "clear", "night_clear", "right,day_rain,sun,rain,snow" }
+};
+
+
+
+static Config_Item *
+_conf_item_get(int *id)
+{
+ Config_Item *ci;
+ Eina_List *l;
+
+ if (*id > 0)
+ {
+ EINA_LIST_FOREACH(weather_config->items, l, ci)
+ {
+ if (ci->id == *id) return ci;
+ }
+ }
+
+ ci = E_NEW(Config_Item, 1);
+ if (!*id)
+ ci->id = eina_list_count(weather_config->items) + 1;
+ else
+ ci->id = -1;
+
+ if (ci->id < 1) return ci;
+ weather_config->items = eina_list_append(weather_config->items, ci);
+ e_config_save_queue();
+
+ return ci;
+}
+
+static void
+_weather_gadget_removed(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+ Instance *inst;
+ Config_Item *ci;
+ Eina_List *l;
+
+ inst = data;
+ evas_object_smart_callback_del_full(inst->obj, "gadget_created",
+ _weather_gadget_removed, inst);
+ EINA_LIST_FOREACH(weather_config->items, l, ci)
+ {
+ if (ci->id == inst->cfg->id)
+ {
+ eina_stringshare_del(ci->geo_id);
+ eina_stringshare_del(ci->city);
+ eina_stringshare_del(ci->country);
+ weather_config->items =
+ eina_list_remove_list(weather_config->items, l);
+ break;
+ }
+ }
+}
+
+static void
+_weather_wizard(E_Gadget_Wizard_End_Cb cb, void *data)
+{
+ Config_Item *ci;
+ Wizard_Item *wi;
+ int id = 0;
+
+ wi = E_NEW(Wizard_Item, 1);
+ wi->cb = cb;
+ wi->data = data;
+ ci = _conf_item_get(&id);
+ wi->id = ci->id;
+ evas_object_event_callback_add(config_weather(ci, NULL), EVAS_CALLBACK_DEL,
+ _weather_wizard_end, wi);
+}
+
+static void
+_weather_wizard_end(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
+{
+ Wizard_Item *wi;
+
+ wi = data;
+
+ wi->cb(wi->data, wi->id);
+ free(wi);
+}
+
+static Evas_Object *
+_weather_create(Evas_Object *parent, Instance *inst, E_Gadget_Site_Orient orient EINA_UNUSED)
+{
+ Evas_Object *o;
+ char buf[PATH_MAX];
+
+
+ o = elm_layout_add(parent);
+ inst->obj = o;
+ snprintf(buf, sizeof(buf), "%s/e-module-weather.edj", e_module_dir_get(weather_config->module));
+ elm_layout_file_set(o, buf, "e/gadget/weather/small");
+ evas_object_size_hint_aspect_set(o, EVAS_ASPECT_CONTROL_BOTH, 1.0, 1.0);
+ evas_object_size_hint_min_set(o, 32, 32);
+ evas_object_size_hint_max_set(o, 32, 32);
+
+ evas_object_event_callback_add(o, EVAS_CALLBACK_DEL, _weather_del, inst);
+ evas_object_smart_callback_add(o, "gadget_removed",
+ _weather_gadget_removed, inst);
+ evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_DOWN,
+ _weather_mouse_down, inst);
+
+ weather_instances = eina_list_append(weather_instances, inst);
+ weather_plugin_weather_add(inst);
+
+ return o;
+}
+
+static void
+_weather_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
+{
+ Instance *inst;
+
+ inst = data;
+
+ weather_instances = eina_list_remove(weather_instances, inst);
+ weather_plugin_weather_remove(inst);
+ free(inst);
+}
+
+static void
+_weather_mouse_down(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event)
+{
+ Instance *inst;
+ Evas_Event_Mouse_Down *ev;
+
+ inst = data;
+ ev = event;
+
+ if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
+ ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+ if (ev->button == 1)
+ {
+ if (inst->popup) elm_ctxpopup_dismiss(inst->popup);
+ else _weather_popup_new(inst);
+ }
+}
+
+static void
+_weather_popup_new(Instance *inst)
+{
+ Evas_Object *o;
+ Evas_Object *vbx;
+ Evas_Object *seg;
+ Eina_List *l;
+ Weather_Data *wd;
+ char buf[4096];
+ int last_day = -1;
+ Elm_Object_Item *it;
+ time_t tt;
+ const struct tm *now;
+
+ tt = time(NULL);
+ now = localtime(&tt);
+
+ if (inst->popup) return;
+ if (!inst->weather) return;
+ inst->popup = elm_ctxpopup_add(inst->obj);
+ elm_object_style_set(inst->popup, "noblock");
+
+ evas_object_smart_callback_add(inst->popup, "dismissed", _weather_popup_dismissed, inst);
+ evas_object_event_callback_add(inst->popup, EVAS_CALLBACK_DEL, _weather_popup_del, inst);
+
+ vbx = elm_box_add(inst->popup);
+ elm_box_horizontal_set(vbx, EINA_FALSE);
+ seg = elm_segment_control_add(vbx);
+ evas_object_size_hint_weight_set(seg, EVAS_HINT_EXPAND, 0.0);
+ evas_object_size_hint_align_set(seg, EVAS_HINT_FILL, EVAS_HINT_FILL);
+ evas_object_size_hint_min_set(seg, 320, 0);
+ EINA_LIST_FOREACH(inst->weather->datas, l, wd)
+ {
+ if (last_day != wd->time_start.tm_mday)
+ {
+ last_day = wd->time_start.tm_mday;
+ if (now->tm_mday == wd->time_start.tm_mday)
+ snprintf(buf, sizeof(buf), _("Today"));
+ else
+ strftime(buf, sizeof(buf), "%A", &wd->time_start);
+ it = elm_segment_control_item_add(seg, NULL, buf);
+ elm_object_item_data_set(it, wd);
+ }
+ }
+ evas_object_smart_callback_add(seg, "changed",
+ _weather_popup_day_segment_changed, inst);
+ it = elm_segment_control_item_get(seg, 0);
+ elm_box_pack_end(vbx, seg);
+ evas_object_show(seg);
+
+ seg = elm_segment_control_add(vbx);
+ inst->popup_segment = seg;
+ evas_object_size_hint_weight_set(seg, EVAS_HINT_EXPAND, 0.0);
+ evas_object_size_hint_align_set(seg, EVAS_HINT_FILL, EVAS_HINT_FILL);
+ elm_box_pack_end(vbx, seg);
+ evas_object_smart_callback_add(seg, "changed",
+ _weather_popup_day_part_segment_changed, inst);
+ evas_object_show(seg);
+
+ o = elm_layout_add(vbx);
+ inst->popup_weather = o;
+ evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ evas_object_size_hint_align_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL);
+ snprintf(buf, sizeof(buf), "%s/e-module-weather.edj",
+ e_module_dir_get(weather_config->module));
+ elm_layout_file_set(o, buf, "e/gadget/weather/big");
+ elm_box_pack_end(vbx, o);
+ evas_object_show(o);
+ evas_object_show(vbx);
+ evas_object_size_hint_min_set(inst->popup, 0, 360);
+ elm_object_content_set(inst->popup, vbx);
+ e_gadget_util_ctxpopup_place(inst->obj, inst->popup, NULL);
+ evas_object_show(inst->popup);
+
+ if (it)
+ elm_segment_control_item_selected_set(it, EINA_TRUE);
+}
+
+
+static void
+_weather_format_time(char *buf, size_t size, const struct tm *tm, Eina_Bool use_24h)
+{
+ if (!use_24h)
+ {
+ if (tm->tm_hour > 12)
+ {
+ snprintf(buf, size, "%d PM", (tm->tm_hour - 12));
+ }
+ else
+ {
+ if (tm->tm_hour != 0)
+ snprintf(buf, size, "%d AM", tm->tm_hour);
+ else
+ snprintf(buf, size, "12 PM");
+ }
+ }
+ else
+ strftime(buf, size, "%H h", tm);
+}
+
+static void
+_weather_popup_day_segment_changed(void *data, Evas_Object *obj EINA_UNUSED, void *event)
+{
+ Elm_Object_Item *it;
+ Instance *inst;
+ Weather_Data *wd, *it_wd;
+ Eina_List *l;
+ int idx;
+ char buf[4096];
+
+ it = event;
+ inst = data;
+ it_wd = elm_object_item_data_get(it);
+
+ idx = elm_segment_control_item_count_get(inst->popup_segment);
+ for (--idx; idx >= 0; --idx)
+ {
+ elm_segment_control_item_del_at(inst->popup_segment, idx);
+ }
+
+
+ EINA_LIST_FOREACH(inst->weather->datas, l, wd)
+ {
+ if ((((wd->time_start.tm_mday == it_wd->time_start.tm_mday)
+ && (wd->time_start.tm_hour != 0)))
+ || ((wd->time_start.tm_mday == (it_wd->time_start.tm_mday + 1)
+ && (wd->time_start.tm_hour == 0))))
+ {
+ _weather_format_time(buf, sizeof(buf),
+ &wd->time_start, inst->cfg->use_24h);
+ it = elm_segment_control_item_add(inst->popup_segment, NULL, buf);
+ elm_object_item_data_set(it, wd);
+ }
+ }
+ it = elm_segment_control_item_get(inst->popup_segment, 0);
+ if (it)
+ elm_segment_control_item_selected_set(it, EINA_TRUE);
+}
+
+static void
+_weather_popup_day_part_segment_changed(void *data, Evas_Object *obj EINA_UNUSED, void *event)
+{
+ Elm_Object_Item *it;
+ Instance *inst;
+ Weather_Data *wd;
+
+ it = event;
+ inst = data;
+ wd = elm_object_item_data_get(it);
+
+ _weather_update_object(inst, inst->popup_weather, wd, EINA_TRUE);
+}
+
+static void
+_weather_popup_dismissed(void *data EINA_UNUSED, Evas_Object *obj, void *event EINA_UNUSED)
+{
+ evas_object_del(obj);
+}
+
+
+static void
+_weather_popup_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+ Instance *inst;
+
+ inst = data;
+
+ inst->popup = NULL;
+ inst->popup_segment = NULL;
+ inst->popup_weather = NULL;
+}
+
+static double
+_weather_convert_celcius_to_farhenheit(double celcius)
+{
+ return ((celcius * 9.) / 5.) + 32.;
+}
+
+
+static void
+_weather_update_object(Instance *inst, Evas_Object *obj, Weather_Data *wd, Eina_Bool big)
+{
+ Eina_Bool night = EINA_FALSE;
+ const char *condition = "";
+ char buf[4096];
+ char buf_time[4096];
+ char buf_time2[4096];
+ unsigned int i;
+ time_t tt;
+ const struct tm *now;
+
+
+ if (wd->time_start.tm_hour <= inst->weather->sunrise.tm_hour)
+ {
+ night = EINA_TRUE;
+ }
+ else if (wd->time_start.tm_hour >= inst->weather->sunset.tm_hour)
+ {
+ night = EINA_TRUE;
+ }
+
+
+
+ if (!inst->weather->translated)
+ {
+ switch (wd->state)
+ {
+ case WEATHER_STATE_THUNDERSTORM_RAIN_LIGHT:
+ condition = _("thunderstorm with light rain");
+ break;
+ case WEATHER_STATE_THUNDERSTORM_RAIN:
+ condition = _("thunderstorm with rain");
+ break;
+ case WEATHER_STATE_THUNDERSTORM_RAIN_HEAVY:
+ condition = _("thunderstorm with heavy rain");
+ break;
+ case WEATHER_STATE_THUNDERSTORM_LIGHT:
+ condition = _("light thunderstorm");
+ break;
+ case WEATHER_STATE_THUNDERSTORM:
+ condition = _("Thunderstorm");
+ break;
+ case WEATHER_STATE_THUNDERSTORM_HEAVY:
+ condition = _("Heavy thunderstorm");
+ break;
+ case WEATHER_STATE_THUNDERSTORM_RAGGED:
+ condition = _("Ragged thunderstorm");
+ break;
+ case WEATHER_STATE_THUNDERSTORM_DRIZZLE_LIGHT:
+ condition = _("Thunderstorm with light drizzle");
+ break;
+ case WEATHER_STATE_THUNDERSTORM_DRIZZLE:
+ condition = _("Thunderstorm with drizzle");
+ break;
+ case WEATHER_STATE_THUNDERSTORM_DRIZZLE_HEAVY:
+ condition = _("Thunderstorm with heavy drizzle");
+ break;
+ case WEATHER_STATE_DRIZZLE_LIGHT:
+ condition = _("Light drizzle");
+ break;
+ case WEATHER_STATE_DRIZZLE:
+ condition = _("Drizzle");
+ break;
+ case WEATHER_STATE_DRIZZLE_HEAVY:
+ condition = _("Heavy drizzle");
+ break;
+ case WEATHER_STATE_DRIZZLE_RAIN_LIGHT:
+ condition = _("Drizzle with light rain");
+ break;
+ case WEATHER_STATE_DRIZZLE_RAIN:
+ condition = _("Drizzle with rain");
+ break;
+ case WEATHER_STATE_DRIZZLE_RAIN_HEAVY:
+ condition = _("Drizzle with heavy rain");
+ break;
+ case WEATHER_STATE_DRIZZLE_RAIN_SHOWER:
+ condition = _("Drizzle with shower rain");
+ break;
+ case WEATHER_STATE_DRIZZLE_RAIN_SHOWER_HEAVY:
+ condition = _("Drizzle with heavy shower rain");
+ break;
+ case WEATHER_STATE_DRIZZLE_SHOWER:
+ condition = _("Shower drizzle");
+ break;
+ case WEATHER_STATE_RAIN_LIGHT:
+ condition = _("Light rain");
+ break;
+ case WEATHER_STATE_RAIN:
+ condition = _("Rain");
+ break;
+ case WEATHER_STATE_RAIN_HEAVY:
+ condition = _("Heavy rain");
+ break;
+ case WEATHER_STATE_RAIN_VERY_HEAVY:
+ condition = _("Very heavy rain");
+ break;
+ case WEATHER_STATE_RAIN_EXTREME:
+ condition = _("Extreme rain");
+ break;
+ case WEATHER_STATE_RAIN_FREEZING:
+ condition = _("Freezing rain");
+ break;
+ case WEATHER_STATE_RAIN_SHOWER_LIGHT:
+ condition = _("Light shower rain");
+ break;
+ case WEATHER_STATE_RAIN_SHOWER:
+ condition = _("Shower rain");
+ break;
+ case WEATHER_STATE_RAIN_SHOWER_HEAVY:
+ condition = _("Heavy shower rain");
+ break;
+ case WEATHER_STATE_RAIN_RAGGED:
+ condition = _("Ragged rain");
+ break;
+ case WEATHER_STATE_SNOW_LIGHT:
+ condition = _("Light snow");
+ break;
+ case WEATHER_STATE_SNOW:
+ condition = _("Snow");
+ break;
+ case WEATHER_STATE_SNOW_HEAVY:
+ condition = _("Heavy snow");
+ break;
+ case WEATHER_STATE_SLEET:
+ condition = _("Sleet");
+ break;
+ case WEATHER_STATE_SLEET_SHOWER:
+ condition = _("Shower sleet");
+ break;
+ case WEATHER_STATE_SNOW_RAIN_LIGHT:
+ condition = _("Snow with light rain");
+ break;
+ case WEATHER_STATE_SNOW_RAIN:
+ condition = _("Snow with rain");
+ break;
+ case WEATHER_STATE_SNOW_SHOWER_LIGHT:
+ condition = _("Light shower snow");
+ break;
+ case WEATHER_STATE_SNOW_SHOWER:
+ condition = _("Shower snow");
+ break;
+ case WEATHER_STATE_SNOW_SHOWER_HEAVY:
+ condition = _("Heavy shower snow");
+ break;
+ case WEATHER_STATE_MIST:
+ condition = _("Mist");
+ break;
+ case WEATHER_STATE_SMOKE:
+ condition = _("Smoke");
+ break;
+ case WEATHER_STATE_HAZE:
+ condition = _("Haze");
+ break;
+ case WEATHER_STATE_DUST_WHIRLS:
+ condition = _("Sand, dust whirls");
+ break;
+ case WEATHER_STATE_FOG:
+ condition = _("Fog");
+ break;
+ case WEATHER_STATE_SAND:
+ condition = _("Sand");
+ break;
+ case WEATHER_STATE_DUST:
+ condition = _("Dust");
+ break;
+ case WEATHER_STATE_VOLCANIC_ASH:
+ condition = _("Volcanic ash");
+ break;
+ case WEATHER_STATE_SQUALLS:
+ condition = _("Squalls");
+ break;
+ case WEATHER_STATE_TORNADO:
+ condition = _("Tornado");
+ break;
+ case WEATHER_STATE_CLEAR_SKY:
+ condition = _("Clear");
+ break;
+ case WEATHER_STATE_FEW_CLOUDS:
+ condition = _("Few clouds");
+ break;
+ case WEATHER_STATE_SCATTERED_CLOUDS:
+ condition = _("Scattered clouds");
+ break;
+ case WEATHER_STATE_BROKEN_CLOUDS:
+ condition = _("Broken clouds");
+ break;
+ case WEATHER_STATE_OVERCAST_CLOUDS:
+ condition = _("Overcast clouds");
+ break;
+ case WEATHER_STATE_TROPICAL_STORM:
+ condition = _("Tropical storm");
+ break;
+ case WEATHER_STATE_HURRICANE:
+ condition = _("Hurricane");
+ break;
+ case WEATHER_STATE_COLD:
+ condition = _("Cold");
+ break;
+ case WEATHER_STATE_HOT:
+ condition = _("Hot");
+ break;
+ case WEATHER_STATE_WINDY:
+ condition = _("Windy");
+ break;
+ case WEATHER_STATE_HAIL:
+ condition = _("Hail");
+ break;
+ }
+ elm_object_part_text_set(obj, "text.condition", condition);
+ }
+ else
+ elm_object_part_text_set(obj, "text.condition", wd->state_name);
+
+ if (inst->cfg->use_celcius)
+ snprintf(buf, sizeof(buf), "%01.1f °C", wd->temperature.value);
+ else
+ snprintf(buf, sizeof(buf), "%01.1f °F",
+ _weather_convert_celcius_to_farhenheit(wd->temperature.value));
+ elm_object_part_text_set(obj, "text.temp", buf);
+
+ if (big)
+ {
+ _weather_format_time(buf_time, sizeof(buf_time),
+ &wd->time_start, inst->cfg->use_24h);
+ _weather_format_time(buf_time2, sizeof(buf_time2),
+ &wd->time_end, inst->cfg->use_24h);
+ snprintf(buf, sizeof(buf), "%s - %s", buf_time, buf_time2);
+ elm_object_part_text_set(obj, "text.date", buf);
+ snprintf(buf, sizeof(buf), "%s (%s)",
+ inst->weather->city, inst->weather->country);
+ elm_object_part_text_set(obj, "text.city", buf);
+ tt = time(NULL);
+ now = localtime(&tt);
+ if (now->tm_mday == wd->time_start.tm_mday)
+ {
+ strftime(buf_time, sizeof(buf_time), "%X", &inst->weather->sunrise);
+ snprintf(buf, sizeof(buf), _("sunrise %s"), buf_time);
+ elm_object_part_text_set(obj, "text.sunrise", buf);
+ strftime(buf_time, sizeof(buf_time), "%X", &inst->weather->sunset);
+ snprintf(buf, sizeof(buf), _("Sunset %s"), buf_time);
+ elm_object_part_text_set(obj, "text.sunrise", buf);
+ }
+ if (inst->cfg->use_celcius)
+ snprintf(buf, sizeof(buf), "%01.1f °C", wd->temperature.value_min);
+ else
+ snprintf(buf, sizeof(buf), "%01.1f °F",
+ _weather_convert_celcius_to_farhenheit(wd->temperature.value_min));
+ elm_object_part_text_set(obj, "text.temp_min", buf);
+ if (inst->cfg->use_celcius)
+ snprintf(buf, sizeof(buf), "%01.1f °C", wd->temperature.value_max);
+ else
+ snprintf(buf, sizeof(buf), "%01.1f °F",
+ _weather_convert_celcius_to_farhenheit(wd->temperature.value_max));
+ elm_object_part_text_set(obj, "text.temp_max", buf);
+ snprintf(buf, sizeof(buf), _("Wind : %s"), wd->wind.name);
+ elm_object_part_text_set(obj, "text.wind", buf);
+ if (inst->cfg->use_metric)
+ snprintf(buf, sizeof(buf), _("Speed : %01.1f Kmh"), (wd->wind.speed * 3.6));
+ else
+ snprintf(buf, sizeof(buf), _("Speed : %01.1f Mph"), (wd->wind.speed * 2.2369));
+ elm_object_part_text_set(obj, "text.wind_speed", buf);
+ snprintf(buf, sizeof(buf), _("Direction : %s"), wd->wind.direction);
+ elm_object_part_text_set(obj, "text.wind_direction", buf);
+ snprintf(buf, sizeof(buf), _("Pressure : %01.1f %s"), wd->pressure.value, wd->pressure.unit);
+ elm_object_part_text_set(obj, "text.pressure", buf);
+ snprintf(buf, sizeof(buf), _("Humidity : %01d %s"), wd->humidity.value, wd->humidity.unit);
+ elm_object_part_text_set(obj, "text.humidity", buf);
+ snprintf(buf, sizeof(buf), _("Precipitation : %01.2f mm"), wd->precipitation.value);
+ elm_object_part_text_set(obj, "text.precipitation", buf);
+ snprintf(buf, sizeof(buf), _("Cloud : %01d %s"), wd->cloud.value, wd->cloud.unit);
+ elm_object_part_text_set(obj, "text.cloud", buf);
+ }
+
+ for (i = 0; i < (sizeof(_signal_table) / sizeof(_signal_table[0])); ++i)
+ {
+ if (_signal_table[i].state == wd->state)
+ {
+ if (night)
+ {
+ if (big)
+ elm_object_signal_emit(obj, _signal_table[i].sig_day_big, "");
+ else
+ elm_object_signal_emit(obj, _signal_table[i].sig_night_small, "");
+ }
+ else
+ {
+ if (big)
+ elm_object_signal_emit(obj, _signal_table[i].sig_day_big, "");
+ else
+ elm_object_signal_emit(obj, _signal_table[i].sig_day_small, "");
+ }
+ break;
+ }
+ }
+
+}
+
+EINTERN void
+weather_gadget_update(Instance *inst)
+{
+ Eina_Bool cfg_update = EINA_FALSE;
+ Weather_Data *wd;
+
+ if (inst->cfg->city != inst->weather->city)
+ {
+ eina_stringshare_replace(&inst->cfg->city, inst->weather->city);
+ cfg_update = EINA_TRUE;
+ }
+ if (inst->cfg->country != inst->weather->country)
+ {
+ eina_stringshare_replace(&inst->cfg->country, inst->weather->country);
+ cfg_update = EINA_TRUE;
+ }
+ if (inst->cfg->geo_id != inst->weather->geo_id)
+ {
+ eina_stringshare_replace(&inst->cfg->geo_id, inst->weather->geo_id);
+ cfg_update = EINA_TRUE;
+ }
+ if (cfg_update) e_config_save_queue();
+ if (inst->obj)
+ {
+ wd = eina_list_data_get(inst->weather->datas);
+ if (!wd) return;
+ fprintf(stderr, "updating gadget\n");
+ _weather_update_object(inst, inst->obj, wd, EINA_FALSE);
+ }
+}
+
+EINTERN Evas_Object *
+weather_small_create(Evas_Object *parent, int *id, E_Gadget_Site_Orient orient)
+{
+ Instance *inst;
+
+ inst = E_NEW(Instance, 1);
+ inst->cfg = _conf_item_get(id);
+ return _weather_create(parent, inst, orient);
+}
+
+EINTERN Evas_Object *
+weather_big_create(Evas_Object *parent, int *id, E_Gadget_Site_Orient orient)
+{
+ Instance *inst;
+
+ inst = E_NEW(Instance, 1);
+ inst->cfg = _conf_item_get(id);
+ return _weather_create(parent, inst, orient);
+}
+
+EINTERN void
+weather_small_wizard(E_Gadget_Wizard_End_Cb cb, void *data)
+{
+ _weather_wizard(cb, data);
+}
+
+
+EINTERN void
+weather_big_wizard(E_Gadget_Wizard_End_Cb cb, void *data)
+{
+ _weather_wizard(cb, data);
+}
+
+EINTERN void
+weather_data_free(Weather_Data *wd)
+{
+ eina_stringshare_del(wd->state_name);
+ eina_stringshare_del(wd->temperature.unit);
+ eina_stringshare_del(wd->precipitation.type);
+ eina_stringshare_del(wd->wind.name);
+ eina_stringshare_del(wd->wind.direction_name);
+ eina_stringshare_del(wd->wind.direction);
+ eina_stringshare_del(wd->cloud.name);
+ eina_stringshare_del(wd->cloud.unit);
+ eina_stringshare_del(wd->humidity.unit);
+ eina_stringshare_del(wd->pressure.unit);
+ free(wd);
+}
+
+EINTERN void
+weather_free(Weather *weather)
+{
+ Weather_Data *wd;
+
+ eina_stringshare_del(weather->city);
+ eina_stringshare_del(weather->country);
+ eina_stringshare_del(weather->geo_id);
+ EINA_LIST_FREE(weather->datas, wd)
+ weather_data_free(wd);
+ free(weather);
+}
diff --git a/src/modules/weather/weather.h b/src/modules/weather/weather.h
new file mode 100644
index 0000000000..a300cfb35e
--- /dev/null
+++ b/src/modules/weather/weather.h
@@ -0,0 +1,190 @@
+#ifndef WEATHER_H
+#define WEATHER_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 _Weather_State
+{
+ WEATHER_STATE_CLEAR_SKY,
+ WEATHER_STATE_FEW_CLOUDS,
+ WEATHER_STATE_SCATTERED_CLOUDS,
+ WEATHER_STATE_BROKEN_CLOUDS,
+ WEATHER_STATE_OVERCAST_CLOUDS,
+ WEATHER_STATE_THUNDERSTORM_LIGHT,
+ WEATHER_STATE_THUNDERSTORM,
+ WEATHER_STATE_THUNDERSTORM_RAIN_LIGHT,
+ WEATHER_STATE_THUNDERSTORM_RAIN,
+ WEATHER_STATE_THUNDERSTORM_RAIN_HEAVY,
+ WEATHER_STATE_THUNDERSTORM_HEAVY,
+ WEATHER_STATE_THUNDERSTORM_RAGGED,
+ WEATHER_STATE_THUNDERSTORM_DRIZZLE_LIGHT,
+ WEATHER_STATE_THUNDERSTORM_DRIZZLE,
+ WEATHER_STATE_THUNDERSTORM_DRIZZLE_HEAVY,
+ WEATHER_STATE_DRIZZLE_LIGHT,
+ WEATHER_STATE_DRIZZLE,
+ WEATHER_STATE_DRIZZLE_HEAVY,
+ WEATHER_STATE_DRIZZLE_RAIN_LIGHT,
+ WEATHER_STATE_DRIZZLE_RAIN,
+ WEATHER_STATE_DRIZZLE_RAIN_HEAVY,
+ WEATHER_STATE_DRIZZLE_RAIN_SHOWER,
+ WEATHER_STATE_DRIZZLE_RAIN_SHOWER_HEAVY,
+ WEATHER_STATE_DRIZZLE_SHOWER,
+ WEATHER_STATE_RAIN_LIGHT,
+ WEATHER_STATE_RAIN,
+ WEATHER_STATE_RAIN_HEAVY,
+ WEATHER_STATE_RAIN_VERY_HEAVY,
+ WEATHER_STATE_RAIN_EXTREME,
+ WEATHER_STATE_RAIN_FREEZING,
+ WEATHER_STATE_RAIN_SHOWER_LIGHT,
+ WEATHER_STATE_RAIN_SHOWER,
+ WEATHER_STATE_RAIN_SHOWER_HEAVY,
+ WEATHER_STATE_RAIN_RAGGED,
+ WEATHER_STATE_SNOW_LIGHT,
+ WEATHER_STATE_SNOW,
+ WEATHER_STATE_SNOW_HEAVY,
+ WEATHER_STATE_SLEET,
+ WEATHER_STATE_SLEET_SHOWER,
+ WEATHER_STATE_SNOW_RAIN_LIGHT,
+ WEATHER_STATE_SNOW_RAIN,
+ WEATHER_STATE_SNOW_SHOWER_LIGHT,
+ WEATHER_STATE_SNOW_SHOWER,
+ WEATHER_STATE_SNOW_SHOWER_HEAVY,
+ WEATHER_STATE_MIST,
+ WEATHER_STATE_SMOKE,
+ WEATHER_STATE_HAZE,
+ WEATHER_STATE_DUST_WHIRLS,
+ WEATHER_STATE_FOG,
+ WEATHER_STATE_SAND,
+ WEATHER_STATE_DUST,
+ WEATHER_STATE_VOLCANIC_ASH,
+ WEATHER_STATE_SQUALLS,
+ WEATHER_STATE_TORNADO,
+ WEATHER_STATE_TROPICAL_STORM,
+ WEATHER_STATE_HURRICANE,
+ WEATHER_STATE_COLD,
+ WEATHER_STATE_HOT,
+ WEATHER_STATE_WINDY,
+ WEATHER_STATE_HAIL,
+} Weather_State;
+
+struct _Config
+{
+ Eina_List *items;
+
+ E_Module *module;
+ Evas_Object *config_dialog;
+};
+
+struct _Config_Item
+{
+ int id;
+ const char *geo_id;
+ const char *city;
+ const char *country;
+ unsigned char use_celcius;
+ unsigned char use_metric;
+ unsigned char use_24h;
+};
+
+
+typedef struct Weather_
+{
+ const char *city;
+ const char *country;
+ const char *geo_id;
+ int altitude;
+ double latitude;
+ double longitude;
+ struct tm sunrise;
+ struct tm sunset;
+ Eina_List *datas;
+// Config_Item *cfg;
+ Eina_Bool translated;
+ Eina_Bool plugin_error;
+} Weather;
+
+typedef struct Weather_Data_
+{
+ struct tm time_start;
+ struct tm time_end;
+ Weather_State state;
+ const char *state_name;
+ struct
+ {
+ double value;
+ double value_min;
+ double value_max;
+ const char *unit;
+ } temperature;
+ struct
+ {
+ const char *type;
+ double value;
+ } precipitation;
+ struct
+ {
+ const char *name;
+ const char *direction_name;
+ const char *direction;
+ double direction_value;
+ double speed;
+ } wind;
+ struct
+ {
+ const char *name;
+ int value;
+ const char *unit;
+ } cloud;
+ struct
+ {
+ int value;
+ const char *unit;
+ } humidity;
+ struct
+ {
+ double value;
+ const char *unit;
+ } pressure;
+ Eina_Bool updated;
+} Weather_Data;
+
+struct _Instance
+{
+ Evas_Object *obj;
+ Evas_Object *popup;
+ Evas_Object *popup_segment;
+ Evas_Object *popup_weather;
+ Config_Item *cfg;
+ Weather *weather;
+};
+
+
+EINTERN Evas_Object *config_weather(Config_Item *, E_Zone*);
+
+EINTERN void weather_init(E_Module *m);
+EINTERN void weather_shutdown(void);
+
+EINTERN Evas_Object *weather_small_create(Evas_Object *parent, int *id, E_Gadget_Site_Orient orient);
+EINTERN Evas_Object *weather_big_create(Evas_Object *parent, int *id, E_Gadget_Site_Orient orient);
+EINTERN void weather_small_wizard(E_Gadget_Wizard_End_Cb cb, void *data);
+EINTERN void weather_big_wizard(E_Gadget_Wizard_End_Cb cb, void *data);
+EINTERN void weather_gadget_update(Instance *inst);
+
+EINTERN void weather_free(Weather *weather);
+EINTERN void weather_data_free(Weather_Data *wd);
+
+extern Config *weather_config;
+extern Eina_List *weather_instances;
+extern Eina_List *weather_list;
+
+#endif