1147 lines
35 KiB
C
1147 lines
35 KiB
C
#include <e.h>
|
|
#include "e_mod_main.h"
|
|
#include <json-c/json.h>
|
|
|
|
char *strptime(const char *s, const char *format, struct tm *tm);
|
|
|
|
#define FORECASTS 2
|
|
#define KM_TO_MI 1.609344
|
|
#define MB_TO_IN 33.864
|
|
|
|
#define GOLDEN_RATIO 1.618033989
|
|
|
|
#define ENABLE_DEBUG 1
|
|
#define DEBUG(f, ...) if (ENABLE_DEBUG) \
|
|
printf("[forecasts] "f "\n", __VA_ARGS__)
|
|
|
|
static E_Gadcon_Client *_gc_init(E_Gadcon *gc, const char *name, const char *id, const char *style);
|
|
static void _gc_shutdown(E_Gadcon_Client *gcc);
|
|
static void _gc_orient(E_Gadcon_Client *gcc, E_Gadcon_Orient orient);
|
|
static const char *_gc_label(const E_Gadcon_Client_Class *client_class);
|
|
static Evas_Object *_gc_icon(const E_Gadcon_Client_Class *client_class, Evas *evas);
|
|
static const char *_gc_id_new(const E_Gadcon_Client_Class *client_class);
|
|
|
|
static E_Config_DD *conf_edd = NULL;
|
|
static E_Config_DD *conf_item_edd = NULL;
|
|
|
|
Config *forecasts_config = NULL;
|
|
|
|
static const E_Gadcon_Client_Class _gadcon_class = {
|
|
GADCON_CLIENT_CLASS_VERSION,
|
|
"forecasts", {_gc_init, _gc_shutdown, _gc_orient, _gc_label, _gc_icon, _gc_id_new, NULL, NULL},
|
|
E_GADCON_CLIENT_STYLE_PLAIN
|
|
};
|
|
|
|
typedef struct _Instance Instance;
|
|
typedef struct _Forecasts Forecasts;
|
|
|
|
struct _Instance
|
|
{
|
|
E_Gadcon_Client *gcc;
|
|
Evas_Object *forecasts_obj;
|
|
Forecasts *forecasts;
|
|
Ecore_Timer *check_timer;
|
|
Ecore_Con_Url *url;
|
|
Ecore_Event_Handler *url_data_handler;
|
|
Ecore_Event_Handler *url_complete_handler;
|
|
|
|
const char *update_time;
|
|
struct
|
|
{
|
|
int temp;
|
|
char update[52];
|
|
char desc[256];
|
|
char code[128];
|
|
} condition;
|
|
|
|
struct
|
|
{
|
|
char temp, distance[3], pressure[3], speed[5];
|
|
} units;
|
|
|
|
struct
|
|
{
|
|
struct
|
|
{
|
|
int chill, direction, speed;
|
|
} wind;
|
|
|
|
struct
|
|
{
|
|
int humidity;
|
|
float pressure;
|
|
} atmosphere;
|
|
|
|
} details;
|
|
|
|
struct
|
|
{
|
|
char day[4];
|
|
char date[12];
|
|
int low, high;
|
|
char code[128];
|
|
char desc[256];
|
|
} forecast[FORECASTS];
|
|
|
|
Eina_Strbuf *buffer;
|
|
const char *location;
|
|
const char *area;
|
|
|
|
E_Gadcon_Popup *popup;
|
|
Config_Item *ci;
|
|
};
|
|
|
|
struct _Forecasts
|
|
{
|
|
Instance *inst;
|
|
Evas_Object *forecasts_obj;
|
|
Evas_Object *icon_obj;
|
|
};
|
|
|
|
/* Module Function Protos */
|
|
static void _forecasts_cb_mouse_up(void *data, Evas *e, Evas_Object *obj,
|
|
void *event_info);
|
|
static void _forecasts_menu_cb_configure(void *data, E_Menu *m,
|
|
E_Menu_Item *mi);
|
|
static void _forecasts_menu_cb_post(void *data, E_Menu *m);
|
|
static Eina_Bool _forecasts_cb_check(void *data);
|
|
static Config_Item *_forecasts_config_item_get(const char *id);
|
|
static Forecasts *_forecasts_new(Evas *evas);
|
|
static void _forecasts_free(Forecasts *w);
|
|
static Eina_Bool _forecasts_url_data(void *data, int type, void *event);
|
|
static Eina_Bool _forecasts_url_complete(void *data, int type, void *event);
|
|
static int _forecasts_parse(void *data);
|
|
static void _forecasts_converter(Instance *inst);
|
|
static void _forecasts_convert_degrees(int *value, int dir);
|
|
static void _forecasts_convert_distances(int *value, int dir);
|
|
static void _forecasts_convert_pressures(float *value, int dir);
|
|
static void _forecasts_display_set(Instance *inst, int ok);
|
|
static void _forecasts_popup_content_create(Instance *inst);
|
|
static void _cb_mouse_up(void *data, Evas *e, Evas_Object *obj, void *event_info);
|
|
static void _cb_mouse_in(void *data, Evas *e, Evas_Object *obj, void *event_info);
|
|
static void _cb_mouse_out(void *data, Evas *e, Evas_Object *obj, void *event_info);
|
|
static Evas_Object *_forecasts_popup_icon_create(Evas *evas, const char *code);
|
|
static void _forecasts_popup_destroy(Instance *inst);
|
|
|
|
/* Gadcon Functions */
|
|
static E_Gadcon_Client *
|
|
_gc_init(E_Gadcon *gc, const char *name, const char *id, const char *style)
|
|
{
|
|
Evas_Object *o;
|
|
E_Gadcon_Client *gcc;
|
|
Forecasts *w;
|
|
Instance *inst;
|
|
|
|
inst = E_NEW(Instance, 1);
|
|
|
|
inst->ci = _forecasts_config_item_get(id);
|
|
inst->area = eina_stringshare_add(inst->ci->location);
|
|
inst->buffer = eina_strbuf_new();
|
|
|
|
w = _forecasts_new(gc->evas);
|
|
w->inst = inst;
|
|
inst->forecasts = w;
|
|
|
|
o = w->forecasts_obj;
|
|
gcc = e_gadcon_client_new(gc, name, id, style, o);
|
|
gcc->data = inst;
|
|
inst->gcc = gcc;
|
|
inst->popup = NULL;
|
|
inst->forecasts_obj = o;
|
|
evas_object_event_callback_add(inst->forecasts_obj, EVAS_CALLBACK_MOUSE_UP,
|
|
_cb_mouse_up, inst);
|
|
evas_object_event_callback_add(inst->forecasts_obj, EVAS_CALLBACK_MOUSE_IN,
|
|
_cb_mouse_in, inst);
|
|
evas_object_event_callback_add(inst->forecasts_obj, EVAS_CALLBACK_MOUSE_OUT,
|
|
_cb_mouse_out, inst);
|
|
|
|
if (!inst->url_data_handler)
|
|
inst->url_data_handler =
|
|
ecore_event_handler_add(ECORE_CON_EVENT_URL_DATA,
|
|
_forecasts_url_data, inst);
|
|
if (!inst->url_complete_handler)
|
|
inst->url_complete_handler =
|
|
ecore_event_handler_add(ECORE_CON_EVENT_URL_COMPLETE,
|
|
_forecasts_url_complete, inst);
|
|
|
|
evas_object_event_callback_add(w->forecasts_obj, EVAS_CALLBACK_MOUSE_UP,
|
|
_forecasts_cb_mouse_up, inst);
|
|
forecasts_config->instances =
|
|
eina_list_append(forecasts_config->instances, inst);
|
|
|
|
_forecasts_cb_check(inst);
|
|
inst->check_timer =
|
|
ecore_timer_add(inst->ci->poll_time, _forecasts_cb_check, inst);
|
|
return gcc;
|
|
}
|
|
|
|
static void
|
|
_gc_shutdown(E_Gadcon_Client *gcc)
|
|
{
|
|
Instance *inst;
|
|
Forecasts *w;
|
|
|
|
inst = gcc->data;
|
|
w = inst->forecasts;
|
|
|
|
if (inst->popup) _forecasts_popup_destroy(inst);
|
|
if (inst->check_timer)
|
|
ecore_timer_del(inst->check_timer);
|
|
if (inst->url_data_handler)
|
|
ecore_event_handler_del(inst->url_data_handler);
|
|
if (inst->url_complete_handler)
|
|
ecore_event_handler_del(inst->url_complete_handler);
|
|
if (inst->url)
|
|
ecore_con_url_free(inst->url);
|
|
if (inst->area)
|
|
eina_stringshare_del(inst->area);
|
|
eina_strbuf_free(inst->buffer);
|
|
if (inst->update_time)
|
|
eina_stringshare_del(inst->update_time);
|
|
|
|
inst->url = NULL;
|
|
forecasts_config->instances =
|
|
eina_list_remove(forecasts_config->instances, inst);
|
|
|
|
evas_object_event_callback_del(w->forecasts_obj, EVAS_CALLBACK_MOUSE_UP,
|
|
_forecasts_cb_mouse_up);
|
|
|
|
_forecasts_free(w);
|
|
E_FREE(inst);
|
|
}
|
|
|
|
static void
|
|
_gc_orient(E_Gadcon_Client *gcc, E_Gadcon_Orient orient)
|
|
{
|
|
Instance *inst;
|
|
|
|
inst = gcc->data;
|
|
|
|
switch (orient)
|
|
{
|
|
case E_GADCON_ORIENT_FLOAT:
|
|
edje_object_signal_emit(inst->forecasts_obj, "e,state,orientation,float", "e");
|
|
e_gadcon_client_aspect_set(gcc, 240, 120);
|
|
e_gadcon_client_min_size_set(gcc, 240, 120);
|
|
break;
|
|
|
|
default:
|
|
edje_object_signal_emit(inst->forecasts_obj, "e,state,orientation,default", "e");
|
|
e_gadcon_client_aspect_set(gcc, 16, 16);
|
|
e_gadcon_client_min_size_set(gcc, 16, 16);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static const char *
|
|
_gc_label(const E_Gadcon_Client_Class *client_class EINA_UNUSED)
|
|
{
|
|
return D_("Forecasts");
|
|
}
|
|
|
|
static Evas_Object *
|
|
_gc_icon(const E_Gadcon_Client_Class *client_class EINA_UNUSED, Evas *evas)
|
|
{
|
|
Evas_Object *o;
|
|
char buf[4096];
|
|
|
|
o = edje_object_add(evas);
|
|
snprintf(buf, sizeof(buf), "%s/e-module-forecasts.edj",
|
|
e_module_dir_get(forecasts_config->module));
|
|
edje_object_file_set(o, buf, "icon");
|
|
return o;
|
|
}
|
|
|
|
static const char *
|
|
_gc_id_new(const E_Gadcon_Client_Class *client_class EINA_UNUSED)
|
|
{
|
|
Config_Item *ci;
|
|
|
|
ci = _forecasts_config_item_get(NULL);
|
|
return ci->id;
|
|
}
|
|
|
|
static void
|
|
_forecasts_cb_mouse_up(void *data, Evas *e EINA_UNUSED,
|
|
Evas_Object *obj EINA_UNUSED,
|
|
void *event_info)
|
|
{
|
|
Instance *inst = data;
|
|
Evas_Event_Mouse_Up *ev = event_info;
|
|
|
|
if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
|
|
if ((ev->button == 3) && (!forecasts_config->menu))
|
|
{
|
|
E_Menu *m;
|
|
E_Menu_Item *mi;
|
|
int x, y, w, h;
|
|
|
|
m = e_menu_new();
|
|
mi = e_menu_item_new(m);
|
|
e_menu_item_label_set(mi, D_("Settings"));
|
|
e_util_menu_item_theme_icon_set(mi, "preferences-system");
|
|
e_menu_item_callback_set(mi, _forecasts_menu_cb_configure, inst);
|
|
|
|
m = e_gadcon_client_util_menu_items_append(inst->gcc, m, 0);
|
|
e_menu_post_deactivate_callback_set(m, _forecasts_menu_cb_post, inst);
|
|
forecasts_config->menu = m;
|
|
|
|
e_gadcon_canvas_zone_geometry_get(inst->gcc->gadcon, &x, &y, &w, &h);
|
|
e_menu_activate_mouse(m,
|
|
e_zone_current_get(), x + ev->output.x,
|
|
y + ev->output.y, 1, 1,
|
|
E_MENU_POP_DIRECTION_DOWN, ev->timestamp);
|
|
evas_event_feed_mouse_up(inst->gcc->gadcon->evas, ev->button,
|
|
EVAS_BUTTON_NONE, ev->timestamp, NULL);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_forecasts_menu_cb_post(void *data EINA_UNUSED, E_Menu *m EINA_UNUSED)
|
|
{
|
|
if (!forecasts_config->menu)
|
|
return;
|
|
e_object_del(E_OBJECT(forecasts_config->menu));
|
|
forecasts_config->menu = NULL;
|
|
}
|
|
|
|
static void
|
|
_forecasts_menu_cb_configure(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED)
|
|
{
|
|
Instance *inst;
|
|
|
|
inst = data;
|
|
_config_forecasts_module(inst->ci);
|
|
}
|
|
|
|
static Config_Item *
|
|
_forecasts_config_item_get(const char *id)
|
|
{
|
|
Eina_List *l;
|
|
Config_Item *ci;
|
|
char buf[128];
|
|
|
|
if (!id)
|
|
{
|
|
int num = 0;
|
|
|
|
/* Create id */
|
|
if (forecasts_config->items)
|
|
{
|
|
const char *p;
|
|
ci = eina_list_last(forecasts_config->items)->data;
|
|
p = strrchr(ci->id, '.');
|
|
if (p) num = strtol(p + 1, NULL, 10) + 1;
|
|
}
|
|
snprintf(buf, sizeof(buf), "%s.%d", _gadcon_class.name, num);
|
|
id = buf;
|
|
}
|
|
else
|
|
{
|
|
for (l = forecasts_config->items; l; l = l->next)
|
|
{
|
|
ci = l->data;
|
|
if (!ci->id)
|
|
continue;
|
|
if (!strcmp(ci->id, id))
|
|
return ci;
|
|
}
|
|
}
|
|
|
|
ci = E_NEW(Config_Item, 1);
|
|
ci->id = eina_stringshare_add(id);
|
|
ci->poll_time = 60.0;
|
|
ci->degrees = DEGREES_C;
|
|
ci->lat = ci->lon = 0;
|
|
ci->show_text = 1;
|
|
ci->popup_on_hover = 1;
|
|
|
|
forecasts_config->items = eina_list_append(forecasts_config->items, ci);
|
|
return ci;
|
|
}
|
|
|
|
/* Gadman Module Setup */
|
|
E_API E_Module_Api e_modapi = {
|
|
E_MODULE_API_VERSION,
|
|
"Forecasts"
|
|
};
|
|
|
|
E_API void *
|
|
e_modapi_init(E_Module *m)
|
|
{
|
|
Eina_List *l;
|
|
Config_Item *ci;
|
|
|
|
ecore_con_url_init();
|
|
bindtextdomain(PACKAGE, LOCALE_DIR);
|
|
bind_textdomain_codeset(PACKAGE, "UTF-8");
|
|
|
|
conf_item_edd = E_CONFIG_DD_NEW("Forecasts_Config_Item", Config_Item);
|
|
#undef T
|
|
#undef D
|
|
#define T Config_Item
|
|
#define D conf_item_edd
|
|
E_CONFIG_VAL(D, T, id, STR);
|
|
E_CONFIG_VAL(D, T, poll_time, DOUBLE);
|
|
E_CONFIG_VAL(D, T, degrees, INT);
|
|
E_CONFIG_VAL(D, T, show_text, INT);
|
|
E_CONFIG_VAL(D, T, popup_on_hover, INT);
|
|
E_CONFIG_VAL(D, T, location_id, INT);
|
|
E_CONFIG_VAL(D, T, location, STR);
|
|
E_CONFIG_VAL(D, T, lat, STR);
|
|
E_CONFIG_VAL(D, T, lon, STR);
|
|
|
|
conf_edd = E_CONFIG_DD_NEW("Forecasts_Config", Config);
|
|
#undef T
|
|
#undef D
|
|
#define T Config
|
|
#define D conf_edd
|
|
E_CONFIG_LIST(D, T, items, conf_item_edd);
|
|
|
|
forecasts_config = e_config_domain_load("module.forecasts", conf_edd);
|
|
if (!forecasts_config)
|
|
{
|
|
forecasts_config = E_NEW(Config, 1);
|
|
|
|
ci = E_NEW(Config_Item, 1);
|
|
ci->poll_time = 60.0;
|
|
ci->degrees = DEGREES_C;
|
|
ci->lat = ci->lon = 0;
|
|
ci->id = eina_stringshare_add("0");
|
|
ci->show_text = 1;
|
|
ci->popup_on_hover = 1;
|
|
|
|
forecasts_config->items = eina_list_append(forecasts_config->items, ci);
|
|
}
|
|
EINA_LIST_FOREACH(forecasts_config->items, l, ci)
|
|
{
|
|
if (ci->poll_time < 60.0) ci->poll_time = 60.0;
|
|
else if (ci->poll_time > 3600.0) ci->poll_time = 3600.0;
|
|
}
|
|
|
|
forecasts_config->module = m;
|
|
e_gadcon_provider_register(&_gadcon_class);
|
|
return m;
|
|
}
|
|
|
|
E_API int
|
|
e_modapi_shutdown(E_Module *m EINA_UNUSED)
|
|
{
|
|
forecasts_config->module = NULL;
|
|
e_gadcon_provider_unregister(&_gadcon_class);
|
|
|
|
if (forecasts_config->config_dialog)
|
|
e_object_del(E_OBJECT(forecasts_config->config_dialog));
|
|
if (forecasts_config->menu)
|
|
{
|
|
e_menu_post_deactivate_callback_set(forecasts_config->menu, NULL, NULL);
|
|
e_object_del(E_OBJECT(forecasts_config->menu));
|
|
forecasts_config->menu = NULL;
|
|
}
|
|
|
|
while (forecasts_config->items)
|
|
{
|
|
Config_Item *ci;
|
|
|
|
ci = forecasts_config->items->data;
|
|
if (ci->id)
|
|
eina_stringshare_del(ci->id);
|
|
if (ci->location)
|
|
eina_stringshare_del(ci->location);
|
|
|
|
forecasts_config->items =
|
|
eina_list_remove_list(forecasts_config->items, forecasts_config->items);
|
|
free(ci);
|
|
ci = NULL;
|
|
}
|
|
|
|
E_FREE(forecasts_config);
|
|
E_CONFIG_DD_FREE(conf_item_edd);
|
|
E_CONFIG_DD_FREE(conf_edd);
|
|
ecore_con_url_shutdown();
|
|
return 1;
|
|
}
|
|
|
|
E_API int
|
|
e_modapi_save(E_Module *m EINA_UNUSED)
|
|
{
|
|
e_config_domain_save("module.forecasts", conf_edd, forecasts_config);
|
|
return 1;
|
|
}
|
|
|
|
static Forecasts *
|
|
_forecasts_new(Evas *evas)
|
|
{
|
|
Forecasts *w;
|
|
char buf[4096];
|
|
|
|
w = E_NEW(Forecasts, 1);
|
|
|
|
w->forecasts_obj = edje_object_add(evas);
|
|
|
|
snprintf(buf, sizeof(buf), "%s/forecasts.edj",
|
|
e_module_dir_get(forecasts_config->module));
|
|
if (!e_theme_edje_object_set(w->forecasts_obj, "base/theme/modules/forecasts",
|
|
"modules/forecasts/main"))
|
|
edje_object_file_set(w->forecasts_obj, buf, "modules/forecasts/main");
|
|
evas_object_show(w->forecasts_obj);
|
|
|
|
w->icon_obj = edje_object_add(evas);
|
|
if (!e_theme_edje_object_set(w->icon_obj, "base/theme/modules/forecasts/icons",
|
|
"modules/forecasts/icons/3200"))
|
|
edje_object_file_set(w->icon_obj, buf, "modules/forecasts/icons/3200");
|
|
edje_object_part_swallow(w->forecasts_obj, "icon", w->icon_obj);
|
|
|
|
return w;
|
|
}
|
|
|
|
static void
|
|
_forecasts_free(Forecasts *w)
|
|
{
|
|
char name[60];
|
|
int i;
|
|
|
|
for (i = 0; i < FORECASTS; i++)
|
|
{
|
|
Evas_Object *swallow;
|
|
|
|
snprintf(name, sizeof(name), "e.swallow.day%d.icon", i);
|
|
swallow = edje_object_part_swallow_get(w->forecasts_obj, name);
|
|
if (swallow)
|
|
evas_object_del(swallow);
|
|
}
|
|
evas_object_del(w->forecasts_obj);
|
|
evas_object_del(w->icon_obj);
|
|
free(w);
|
|
w = NULL;
|
|
}
|
|
|
|
static Eina_Bool
|
|
_forecasts_cb_check(void *data)
|
|
{
|
|
Instance *inst = data;
|
|
char buf[256];
|
|
|
|
/* if we have a previous server, delete it */
|
|
if (inst->url) ecore_con_url_free(inst->url);
|
|
snprintf(buf, sizeof(buf),
|
|
"https://www.enlightenment.org/weather.php?lat=%s&lon=%s",
|
|
inst->ci->lat, inst->ci->lon);
|
|
DEBUG("FC: URL: %s", buf);
|
|
inst->url = ecore_con_url_new(buf);
|
|
if (!inst->url) return EINA_FALSE;
|
|
ecore_con_url_http_version_set(inst->url, ECORE_CON_URL_HTTP_VERSION_1_0);
|
|
ecore_con_url_get(inst->url);
|
|
return EINA_TRUE;
|
|
}
|
|
|
|
static Eina_Bool
|
|
_forecasts_url_data(void *data, int type EINA_UNUSED, void *event)
|
|
{
|
|
Instance *inst = data;
|
|
Ecore_Con_Event_Url_Data *ev = event;
|
|
|
|
if ((!inst->url) || (inst->url != ev->url_con)) return EINA_TRUE;
|
|
eina_strbuf_append_length(inst->buffer, (const char *)ev->data, ev->size);
|
|
return EINA_FALSE;
|
|
}
|
|
|
|
static Eina_Bool
|
|
_forecasts_url_complete(void *data, int type EINA_UNUSED, void *event)
|
|
{
|
|
Instance *inst = data;
|
|
Ecore_Con_Event_Url_Complete *ev = event;
|
|
int ret;
|
|
|
|
if ((!inst->url) || (inst->url != ev->url_con)) return EINA_TRUE;
|
|
DEBUG("FC: status: %i %s", ev->status, eina_strbuf_string_get(inst->buffer));
|
|
ecore_con_url_free(inst->url);
|
|
inst->url = NULL;
|
|
|
|
eina_stringshare_replace(&inst->location, inst->ci->location);
|
|
ret = _forecasts_parse(inst);
|
|
_forecasts_converter(inst);
|
|
_forecasts_display_set(inst, ret);
|
|
|
|
eina_strbuf_string_free(inst->buffer);
|
|
return EINA_FALSE;
|
|
}
|
|
|
|
static void
|
|
_timestamp_local(const char *timestamp, char *buf, size_t len)
|
|
{
|
|
struct tm tm_in;
|
|
struct tm *tm_out;
|
|
time_t t;
|
|
|
|
memset(&tm_in, 0, sizeof(struct tm));
|
|
strptime(timestamp, "%Y-%m-%dT%H:%M:%SZ", &tm_in);
|
|
t = mktime(&tm_in);
|
|
tm_out = localtime(&t);
|
|
strftime(buf, len - 1, "%Y-%m-%d %H:%M:%S", tm_out);
|
|
}
|
|
|
|
static struct tm *
|
|
_timestamp_time(const char *timestamp)
|
|
{
|
|
struct tm tm_in;
|
|
struct tm *tm_out;
|
|
time_t t;
|
|
|
|
memset(&tm_in, 0, sizeof(struct tm));
|
|
strptime(timestamp, "%Y-%m-%dT%H:%M:%SZ", &tm_in);
|
|
t = mktime(&tm_in);
|
|
tm_out = localtime(&t);
|
|
|
|
return tm_out;
|
|
}
|
|
|
|
static int
|
|
_epoch_days(struct tm *tm_in)
|
|
{
|
|
time_t t = mktime(tm_in);
|
|
|
|
return t / 86400;
|
|
}
|
|
|
|
static int
|
|
_forecasts_parse(void *data)
|
|
{
|
|
Instance *inst = data;
|
|
const char *result;
|
|
const char *timestamp, *code;
|
|
time_t now;
|
|
struct tm *tm_local, *tm_data;
|
|
int i, len, days_prev, idx = 0;
|
|
static char *weekdays[7] =
|
|
{
|
|
"Sun",
|
|
"Mon",
|
|
"Tue",
|
|
"Wed",
|
|
"Thu",
|
|
"Fri",
|
|
"Sat",
|
|
};
|
|
|
|
if (!inst->buffer) return 0;
|
|
|
|
for (int i = 0; i < FORECASTS; i++)
|
|
{
|
|
inst->forecast[i].high = -237.15;
|
|
inst->forecast[i].low = 190.0;
|
|
}
|
|
now = time(NULL);
|
|
tm_local = localtime(&now);
|
|
days_prev = _epoch_days(tm_local);
|
|
|
|
result = eina_strbuf_string_get(inst->buffer);
|
|
if (!result) goto error;
|
|
|
|
json_object *o_root = json_tokener_parse(result);
|
|
if (!o_root) goto error;
|
|
json_object *o_properties = json_object_object_get(o_root, "properties");
|
|
if (!o_properties) goto error;
|
|
json_object *o_meta = json_object_object_get(o_properties, "meta");
|
|
if (!o_meta) goto error;
|
|
json_object *o_updated = json_object_object_get(o_meta, "updated_at");
|
|
if (!o_updated) goto error;
|
|
timestamp = json_object_get_string(o_updated);
|
|
if (!timestamp) goto error;
|
|
eina_stringshare_replace(&inst->update_time, timestamp);
|
|
json_object *o_timeseries = json_object_object_get(o_properties, "timeseries");
|
|
if (!o_timeseries) goto error;
|
|
if (json_object_get_type(o_timeseries) != json_type_array) goto error;
|
|
|
|
inst->units.temp = 'C';
|
|
snprintf(inst->units.distance, 3, "km");
|
|
snprintf(inst->units.pressure, 3, "mb");
|
|
snprintf(inst->units.speed, 5, "km/h");
|
|
|
|
len = json_object_array_length(o_timeseries);
|
|
for (i = 0; i < len; i++)
|
|
{
|
|
json_object *o_index = json_object_array_get_idx(o_timeseries, i);
|
|
if (!o_index) break;
|
|
|
|
timestamp = json_object_get_string(json_object_object_get(o_index, "time"));
|
|
tm_data = _timestamp_time(timestamp);
|
|
|
|
int days = _epoch_days(tm_data);
|
|
if ((days != days_prev) && days == (days_prev + 1))
|
|
idx++;
|
|
|
|
if (idx > 1) break;
|
|
else if (idx == 0)
|
|
{
|
|
strftime(inst->forecast[idx].date, 12, "%d %b %Y", tm_data);
|
|
strncpy(inst->forecast[idx].day, weekdays[tm_data->tm_wday], 3);
|
|
}
|
|
else if (idx == 1)
|
|
{
|
|
strftime(inst->forecast[idx].date, 12, "%d %b %Y", tm_data);
|
|
strncpy(inst->forecast[idx].day, weekdays[tm_data->tm_wday], 3);
|
|
}
|
|
|
|
json_object *o_data = json_object_object_get(o_index, "data");
|
|
if (!o_data) break;
|
|
json_object *o_instant = json_object_object_get(o_data, "instant");
|
|
if (!o_instant) break;
|
|
json_object *o_details = json_object_object_get(o_instant, "details");
|
|
if (!o_details) break;
|
|
|
|
double v = json_object_get_double(json_object_object_get(o_details, "air_temperature"));
|
|
|
|
if (v > inst->forecast[idx].high) inst->forecast[idx].high = v;
|
|
if (v < inst->forecast[idx].low) inst->forecast[idx].low = v;
|
|
|
|
if (i == 0)
|
|
{
|
|
inst->condition.temp = v;
|
|
v = json_object_get_double(json_object_object_get(o_details, "air_pressure_at_sea_level"));
|
|
inst->details.atmosphere.pressure = v;
|
|
v = json_object_get_double(json_object_object_get(o_details, "relative_humidity"));
|
|
inst->details.atmosphere.humidity = v;
|
|
v = json_object_get_double(json_object_object_get(o_details, "wind_from_direction"));
|
|
inst->details.wind.direction = v;
|
|
v = json_object_get_double(json_object_object_get(o_details, "wind_speed"));
|
|
v *= 3.6;
|
|
inst->details.wind.speed = v;
|
|
|
|
double t, vpow;
|
|
t = inst->condition.temp;
|
|
vpow = pow(inst->details.wind.speed, 0.16);
|
|
inst->details.wind.chill = (13.12 + (0.6215 * t)) - (11.37 * (vpow)) + ((0.3965 * t) * (vpow));
|
|
|
|
json_object *o_next = json_object_object_get(o_data, "next_1_hours");
|
|
json_object *o_summary = json_object_object_get(o_next, "summary");
|
|
code = json_object_get_string(json_object_object_get(o_summary, "symbol_code"));
|
|
snprintf(inst->condition.code, sizeof(inst->condition.code), "%s", code);
|
|
snprintf(inst->forecast[idx].code, sizeof(inst->condition.code), "%s", code);
|
|
}
|
|
|
|
if (tm_data->tm_hour == 8)
|
|
{
|
|
// XXX We need TZ data.
|
|
json_object *o_next = json_object_object_get(o_data, "next_12_hours");
|
|
json_object *o_summary = json_object_object_get(o_next, "summary");
|
|
code = json_object_get_string(json_object_object_get(o_summary, "symbol_code"));
|
|
snprintf(inst->forecast[idx].code, sizeof(inst->condition.code), "%s", code);
|
|
}
|
|
|
|
days_prev = days;
|
|
}
|
|
|
|
json_object_put(o_root);
|
|
return 1;
|
|
|
|
error:
|
|
printf("FC: ERROR: Couldn't parse info\n");
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
_forecasts_converter(Instance *inst)
|
|
{
|
|
int i, dir = -1;
|
|
|
|
if ((inst->units.temp == 'F') && (inst->ci->degrees == DEGREES_C))
|
|
{
|
|
dir = DEGREES_C;
|
|
inst->units.temp = 'C';
|
|
snprintf(inst->units.distance, 3, "km");
|
|
snprintf(inst->units.pressure, 3, "mb");
|
|
snprintf(inst->units.speed, 5, "km/h");
|
|
}
|
|
else if ((inst->units.temp == 'C') && (inst->ci->degrees == DEGREES_F))
|
|
{
|
|
dir = DEGREES_F;
|
|
inst->units.temp = 'F';
|
|
snprintf(inst->units.distance, 3, "mi");
|
|
snprintf(inst->units.pressure, 3, "in");
|
|
snprintf(inst->units.speed, 4, "mph");
|
|
}
|
|
if (dir == -1) return;
|
|
|
|
_forecasts_convert_degrees(&inst->condition.temp, dir);
|
|
_forecasts_convert_degrees(&inst->details.wind.chill, dir);
|
|
_forecasts_convert_distances(&inst->details.wind.speed, dir);
|
|
_forecasts_convert_pressures(&inst->details.atmosphere.pressure, dir);
|
|
for (i = 0; i < FORECASTS; i++)
|
|
{
|
|
_forecasts_convert_degrees(&inst->forecast[i].low, dir);
|
|
_forecasts_convert_degrees(&inst->forecast[i].high, dir);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_forecasts_convert_degrees(int *value, int dir)
|
|
{
|
|
if ((dir == DEGREES_C))
|
|
*value = (*value - 32) * 5.0 / 9.0;
|
|
else
|
|
*value = (*value * 9.0 / 5.0) + 32;
|
|
}
|
|
|
|
static void
|
|
_forecasts_convert_distances(int *value, int dir)
|
|
{
|
|
if ((dir == DEGREES_C))
|
|
*value = (*value) * KM_TO_MI;
|
|
else
|
|
*value = (*value) / KM_TO_MI;
|
|
}
|
|
|
|
static void
|
|
_forecasts_convert_pressures(float *value, int dir)
|
|
{
|
|
if ((dir == DEGREES_C))
|
|
*value = (*value) * MB_TO_IN;
|
|
else
|
|
*value = (*value) / MB_TO_IN;
|
|
}
|
|
|
|
static void
|
|
_forecasts_display_set(Instance *inst, int ok EINA_UNUSED)
|
|
{
|
|
char buf[4096];
|
|
char m[4096];
|
|
|
|
if (!inst) return;
|
|
|
|
snprintf(m, sizeof(m), "%s/forecasts.edj",
|
|
e_module_dir_get(forecasts_config->module));
|
|
snprintf(buf, sizeof(buf), "modules/forecasts/icons/%s", inst->condition.code);
|
|
if (!e_theme_edje_object_set(inst->forecasts->icon_obj,
|
|
"base/theme/modules/forecasts/icons", buf))
|
|
edje_object_file_set(inst->forecasts->icon_obj, m, buf);
|
|
edje_object_part_swallow(inst->forecasts->forecasts_obj, "icon", inst->forecasts->icon_obj);
|
|
|
|
if (!inst->ci->show_text)
|
|
edje_object_signal_emit(inst->forecasts_obj, "e,state,description,hide", "e");
|
|
else
|
|
edje_object_signal_emit(inst->forecasts_obj, "e,state,description,show", "e");
|
|
|
|
snprintf(buf, sizeof(buf), "%d°%c", inst->condition.temp, inst->units.temp);
|
|
edje_object_part_text_set(inst->forecasts->forecasts_obj, "e.text.temp", buf);
|
|
edje_object_part_text_set(inst->forecasts->forecasts_obj, "e.text.description",
|
|
inst->condition.desc);
|
|
edje_object_part_text_set(inst->forecasts->forecasts_obj, "e.text.location", inst->ci->location);
|
|
|
|
if (inst->gcc->gadcon->orient == E_GADCON_ORIENT_FLOAT)
|
|
{
|
|
char buf[4096], name[60];
|
|
int i;
|
|
|
|
for (i = 0; i < FORECASTS; i++)
|
|
{
|
|
Evas_Object *swallow;
|
|
|
|
snprintf(name, sizeof(name), "e.text.day%d.date", i);
|
|
edje_object_part_text_set(inst->forecasts->forecasts_obj, name, inst->forecast[i].date);
|
|
|
|
snprintf(name, sizeof(name), "e.text.day%d.description", i);
|
|
edje_object_part_text_set(inst->forecasts->forecasts_obj, name, inst->forecast[i].desc);
|
|
|
|
snprintf(name, sizeof(name), "e.text.day%d.high", i);
|
|
snprintf(buf, sizeof(buf), "%d°%c", inst->forecast[i].high, inst->units.temp);
|
|
edje_object_part_text_set(inst->forecasts->forecasts_obj, name, buf);
|
|
|
|
snprintf(name, sizeof(name), "e.text.day%d.low", i);
|
|
snprintf(buf, sizeof(buf), "%d°%c", inst->forecast[i].low, inst->units.temp);
|
|
edje_object_part_text_set(inst->forecasts->forecasts_obj, name, buf);
|
|
|
|
snprintf(name, sizeof(name), "e.swallow.day%d.icon", i);
|
|
swallow = edje_object_part_swallow_get(inst->forecasts->forecasts_obj, name);
|
|
if (swallow)
|
|
evas_object_del(swallow);
|
|
edje_object_part_swallow(inst->forecasts->forecasts_obj, name,
|
|
_forecasts_popup_icon_create(inst->gcc->gadcon->evas, inst->forecast[i].code));
|
|
}
|
|
}
|
|
|
|
if (inst->popup) _forecasts_popup_destroy(inst);
|
|
inst->popup = NULL;
|
|
}
|
|
|
|
void
|
|
_forecasts_config_updated(Config_Item *ci)
|
|
{
|
|
Eina_List *l;
|
|
char buf[4096];
|
|
|
|
if (!forecasts_config)
|
|
return;
|
|
for (l = forecasts_config->instances; l; l = l->next)
|
|
{
|
|
Instance *inst;
|
|
|
|
inst = l->data;
|
|
if (inst->ci != ci) continue;
|
|
int area_changed = 0;
|
|
|
|
if ((!inst->area && inst->ci->location) ||
|
|
(inst->area && strcmp(inst->area, inst->ci->location)))
|
|
area_changed = 1;
|
|
|
|
if (inst->area) eina_stringshare_del(inst->area);
|
|
inst->area = eina_stringshare_add(inst->ci->location);
|
|
_forecasts_converter(inst);
|
|
|
|
if (inst->popup) _forecasts_popup_destroy(inst);
|
|
inst->popup = NULL;
|
|
|
|
snprintf(buf, sizeof(buf), "%d°%c", inst->condition.temp, inst->units.temp);
|
|
edje_object_part_text_set(inst->forecasts->forecasts_obj, "e.text.temp", buf);
|
|
|
|
if (!inst->ci->show_text)
|
|
edje_object_signal_emit(inst->forecasts_obj, "e,state,description,hide", "e");
|
|
else
|
|
edje_object_signal_emit(inst->forecasts_obj, "e,state,description,show", "e");
|
|
|
|
if (area_changed)
|
|
_forecasts_cb_check(inst);
|
|
if (inst->check_timer) ecore_timer_del(inst->check_timer);
|
|
inst->check_timer =
|
|
ecore_timer_add(inst->ci->poll_time, _forecasts_cb_check,
|
|
inst);
|
|
}
|
|
}
|
|
|
|
static Evas_Object *
|
|
_lb_add(Evas_Object *base, const char *txt)
|
|
{
|
|
Evas_Object *lb = elm_label_add(base);
|
|
evas_object_size_hint_weight_set(lb, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
|
|
elm_object_text_set(lb, txt);
|
|
evas_object_show(lb);
|
|
|
|
return lb;
|
|
}
|
|
|
|
static void
|
|
_forecasts_popup_content_create(Instance *inst)
|
|
{
|
|
Evas_Object *base, *bx, *hbx, *fr, *tb, *lb;
|
|
Evas_Object *rec, *ic, *im;
|
|
char buf[2048], tmp[2048];
|
|
int row = 0;
|
|
Evas_Coord w, h;
|
|
|
|
if (!inst->location) return;
|
|
|
|
inst->popup = e_gadcon_popup_new(inst->gcc, 0);
|
|
|
|
base = e_comp->elm;
|
|
|
|
bx = elm_box_add(base);
|
|
evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
|
|
evas_object_size_hint_align_set(bx, EVAS_HINT_FILL, EVAS_HINT_FILL);
|
|
evas_object_show(bx);
|
|
|
|
fr = elm_frame_add(base);
|
|
evas_object_size_hint_weight_set(fr, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
|
|
evas_object_size_hint_align_set(fr, EVAS_HINT_FILL, EVAS_HINT_FILL);
|
|
elm_object_text_set(fr, D_("Current Conditions"));
|
|
evas_object_show(fr);
|
|
elm_box_pack_end(bx, fr);
|
|
|
|
tb = elm_table_add(base);
|
|
evas_object_size_hint_weight_set(tb, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
|
|
evas_object_size_hint_align_set(tb, EVAS_HINT_FILL, EVAS_HINT_FILL);
|
|
elm_table_align_set(tb, 0.0, 0.0);
|
|
elm_table_padding_set(tb, 2, 2);
|
|
evas_object_show(tb);
|
|
|
|
rec = evas_object_rectangle_add(e_comp->evas);
|
|
evas_object_size_hint_min_set(rec, 240, 1);
|
|
elm_table_pack(tb, rec, 0, 0, 2, 1);
|
|
|
|
elm_object_content_set(fr, tb);
|
|
|
|
ic = _forecasts_popup_icon_create(e_comp->evas,
|
|
inst->condition.code);
|
|
edje_object_size_max_get(ic, &w, &h);
|
|
if (w > 160) w = 160;
|
|
if (h > 160) h = 160;
|
|
im = e_widget_image_add_from_object(e_comp->evas, ic, w, h);
|
|
evas_object_show(im);
|
|
elm_table_pack(tb, im, 0, row, 2, 1);
|
|
|
|
_timestamp_local(inst->update_time, tmp, sizeof(tmp));
|
|
snprintf(buf, sizeof(buf), D_("<small>Updated: %s</>"), tmp);
|
|
lb = _lb_add(base, buf);
|
|
evas_object_size_hint_align_set(lb, 1.0, 0.0);
|
|
elm_table_pack(tb, lb, 0, row++, 2, 1);
|
|
|
|
snprintf(buf, sizeof(buf), "<b>%s</>", inst->location);
|
|
lb = _lb_add(base, buf);
|
|
evas_object_size_hint_align_set(lb, 0.5, 1.0);
|
|
elm_table_pack(tb, lb, 0, row++, 2, 1);
|
|
|
|
lb = _lb_add(base, D_("Temperature"));
|
|
elm_table_pack(tb, lb, 0, row, 1, 1);
|
|
snprintf(buf, sizeof(buf), "%d°%c", inst->condition.temp, inst->units.temp);
|
|
lb = _lb_add(base, buf);
|
|
elm_table_pack(tb, lb, 1, row++, 1, 1);
|
|
|
|
lb = _lb_add(base, D_("Wind Chill"));
|
|
elm_table_pack(tb, lb, 0, row, 1, 1);
|
|
snprintf(buf, sizeof(buf), "%d°%c", inst->details.wind.chill, inst->units.temp);
|
|
lb = _lb_add(base, buf);
|
|
elm_table_pack(tb, lb, 1, row++, 1, 1);
|
|
|
|
lb = _lb_add(base, D_("Wind Speed"));
|
|
elm_table_pack(tb, lb, 0, row, 1, 1);
|
|
snprintf(buf, sizeof(buf), "%d %s", inst->details.wind.speed, inst->units.speed);
|
|
lb = _lb_add(base, buf);
|
|
elm_table_pack(tb, lb, 1, row++, 1, 1);
|
|
|
|
lb = _lb_add(base, D_("Humidity"));
|
|
elm_table_pack(tb, lb, 0, row, 1, 1);
|
|
snprintf(buf, sizeof(buf), "%d %%", inst->details.atmosphere.humidity);
|
|
lb = _lb_add(base, buf);
|
|
elm_table_pack(tb, lb, 1, row++, 1, 1);
|
|
|
|
lb = _lb_add(base, D_("Pressure"));
|
|
elm_table_pack(tb, lb, 0, row, 1, 1);
|
|
snprintf(buf, sizeof(buf), "%.2f %s", inst->details.atmosphere.pressure, inst->units.pressure);
|
|
lb = _lb_add(base, buf);
|
|
elm_table_pack(tb, lb, 1, row++, 1, 1);
|
|
|
|
hbx = elm_box_add(base);
|
|
evas_object_size_hint_weight_set(hbx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
|
|
evas_object_size_hint_align_set(hbx, EVAS_HINT_FILL, EVAS_HINT_FILL);
|
|
elm_box_horizontal_set(hbx, 1);
|
|
evas_object_show(hbx);
|
|
elm_box_pack_end(bx, hbx);
|
|
|
|
fr = elm_frame_add(base);
|
|
evas_object_size_hint_weight_set(fr, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
|
|
evas_object_size_hint_align_set(fr, EVAS_HINT_FILL, EVAS_HINT_FILL);
|
|
elm_object_text_set(fr, D_("Today"));
|
|
evas_object_show(fr);
|
|
|
|
tb = elm_table_add(base);
|
|
evas_object_size_hint_weight_set(tb, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
|
|
evas_object_size_hint_align_set(tb, EVAS_HINT_FILL, EVAS_HINT_FILL);
|
|
evas_object_show(tb);
|
|
elm_object_content_set(fr, tb);
|
|
|
|
ic = _forecasts_popup_icon_create(e_comp->evas,
|
|
inst->forecast[0].code);
|
|
im = e_widget_image_add_from_object(e_comp->evas, ic, 24, 24);
|
|
evas_object_size_hint_weight_set(im, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
|
|
evas_object_show(im);
|
|
elm_table_pack(tb, im, 0, 0, 2, 1);
|
|
|
|
lb = _lb_add(base, D_("High"));
|
|
elm_table_pack(tb, lb, 0, 1, 1, 1);
|
|
snprintf(buf, sizeof(buf), "%d°%c", inst->forecast[0].high, inst->units.temp);
|
|
lb = _lb_add(base, buf);
|
|
elm_table_pack(tb, lb, 0, 2, 1, 1);
|
|
|
|
lb = _lb_add(base, D_("Low"));
|
|
elm_table_pack(tb, lb, 1, 1, 1, 1);
|
|
snprintf(buf, sizeof(buf), "%d°%c", inst->forecast[0].low, inst->units.temp);
|
|
lb = _lb_add(base, buf);
|
|
elm_table_pack(tb, lb, 1, 2, 1, 1);
|
|
elm_box_pack_end(hbx, fr);
|
|
|
|
fr = elm_frame_add(base);
|
|
evas_object_size_hint_weight_set(fr, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
|
|
evas_object_size_hint_align_set(fr, EVAS_HINT_FILL, EVAS_HINT_FILL);
|
|
elm_object_text_set(fr, D_("Tomorrow"));
|
|
evas_object_show(fr);
|
|
elm_box_pack_end(hbx, fr);
|
|
|
|
tb = elm_table_add(base);
|
|
evas_object_size_hint_weight_set(tb, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
|
|
evas_object_size_hint_align_set(tb, EVAS_HINT_FILL, EVAS_HINT_FILL);
|
|
evas_object_show(tb);
|
|
elm_object_content_set(fr, tb);
|
|
|
|
ic = _forecasts_popup_icon_create(e_comp->evas,
|
|
inst->forecast[1].code);
|
|
im = e_widget_image_add_from_object(e_comp->evas, ic, 24, 24);
|
|
evas_object_size_hint_weight_set(im, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
|
|
evas_object_show(im);
|
|
elm_table_pack(tb, im, 0, 0, 2, 1);
|
|
|
|
lb = _lb_add(base, D_("High"));
|
|
elm_table_pack(tb, lb, 0, 1, 1, 1);
|
|
snprintf(buf, sizeof(buf), "%d°%c", inst->forecast[1].high, inst->units.temp);
|
|
lb = _lb_add(base, buf);
|
|
elm_table_pack(tb, lb, 0, 2, 1, 1);
|
|
|
|
lb = _lb_add(base, D_("Low"));
|
|
elm_table_pack(tb, lb, 1, 1, 1, 1);
|
|
snprintf(buf, sizeof(buf), "%d°%c", inst->forecast[1].low, inst->units.temp);
|
|
lb = _lb_add(base, buf);
|
|
elm_table_pack(tb, lb, 1, 2, 1, 1);
|
|
|
|
e_gadcon_popup_content_set(inst->popup, bx);
|
|
}
|
|
|
|
static Evas_Object *
|
|
_forecasts_popup_icon_create(Evas *evas, const char *code)
|
|
{
|
|
char buf[4096];
|
|
char m[4096];
|
|
Evas_Object *o;
|
|
|
|
snprintf(m, sizeof(m), "%s/forecasts.edj",
|
|
e_module_dir_get(forecasts_config->module));
|
|
o = edje_object_add(evas);
|
|
snprintf(buf, sizeof(buf), "modules/forecasts/icons/%s", code);
|
|
if (!e_theme_edje_object_set(o, "base/theme/modules/forecasts/icons", buf))
|
|
edje_object_file_set(o, m, buf);
|
|
|
|
return o;
|
|
}
|
|
|
|
static void
|
|
_forecasts_popup_destroy(Instance *inst)
|
|
{
|
|
if (!inst->popup) return;
|
|
e_object_del(E_OBJECT(inst->popup));
|
|
}
|
|
|
|
static void
|
|
_cb_mouse_up(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
|
|
{
|
|
Instance *inst = data;
|
|
Evas_Event_Mouse_Up *ev = event_info;
|
|
|
|
if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
|
|
if (!inst->ci->popup_on_hover)
|
|
{
|
|
if (!inst->popup) _forecasts_popup_content_create(inst);
|
|
e_gadcon_popup_show(inst->popup);
|
|
return;
|
|
}
|
|
|
|
if (ev->button == 1) e_gadcon_popup_toggle_pinned(inst->popup);
|
|
}
|
|
|
|
static void
|
|
_cb_mouse_in(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
|
|
{
|
|
Instance *inst = data;
|
|
|
|
if (!inst->ci->popup_on_hover) return;
|
|
if (!inst->popup) _forecasts_popup_content_create(inst);
|
|
e_gadcon_popup_show(inst->popup);
|
|
}
|
|
|
|
static void
|
|
_cb_mouse_out(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
|
|
{
|
|
Instance *inst = data;
|
|
|
|
if (!(inst->popup)) return;
|
|
if (inst->popup->pinned) return;
|
|
e_gadcon_popup_hide(inst->popup);
|
|
}
|
|
|