X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=src%2Fplugins%2Falert.c;h=cc9f9468c80dc5e98e3a2a436ad083b85d2a9bea;hb=72842797f3fddb8ddb3c309ba9ceec889c4ec4e2;hp=d4c6e212286995556f73ccd9976446508872ee24;hpb=a52c3912b474f14a476f9be92fcdb312fa6cbba5;p=aweather diff --git a/src/plugins/alert.c b/src/plugins/alert.c index d4c6e21..cc9f946 100644 --- a/src/plugins/alert.c +++ b/src/plugins/alert.c @@ -18,14 +18,16 @@ #include #include -#include #include #include #include "alert.h" #include "alert-info.h" +#include "compat.h" + #define MSG_INDEX "http://alerts.weather.gov/cap/us.php?x=0" +#define CONFIG_HEIGHT 3 /* Format for single cap alert: * "http://alerts.weather.gov/cap/wwacapget.php?x=" @@ -319,22 +321,22 @@ GList *msg_load_index(GritsHttp *http, time_t when, time_t *updated, gboolean of return msgs; } -void msg_load_cap(GritsHttp *http, AlertMsg *msg) +gboolean msg_load_cap(GritsHttp *http, AlertMsg *msg) { if (msg->description || msg->instruction || msg->polygon) - return; + return TRUE; g_debug("GritsPlguinAlert: update_cap"); /* Download */ gchar *id = strrchr(msg->link, '='); - if (!id) return; id++; + if (!id) return FALSE; id++; gchar *dir = g_strdelimit(g_strdup(msg->info->abbr), " ", '_'); gchar *tmp = g_strdup_printf("%s/%s.xml", dir, id); gchar *file = grits_http_fetch(http, msg->link, tmp, GRITS_ONCE, NULL, NULL); g_free(tmp); g_free(dir); if (!file) - return; + return FALSE; /* Parse */ gchar *text; gsize len; @@ -342,6 +344,7 @@ void msg_load_cap(GritsHttp *http, AlertMsg *msg) msg_parse_cap(msg, text, len); g_free(file); g_free(text); + return TRUE; } @@ -477,7 +480,7 @@ static GtkWidget *_make_msg_details(AlertMsg *msg) g_free(alert_str); GtkWidget *align = gtk_alignment_new(0, 0, 1, 1); - GtkWidget *box = gtk_vbox_new(FALSE, 10); + GtkWidget *box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 10); gtk_alignment_set_padding(GTK_ALIGNMENT(align), 10, 10, 10, 10); gtk_container_add(GTK_CONTAINER(align), box); gtk_box_pack_start(GTK_BOX(box), title, FALSE, FALSE, 0); @@ -497,11 +500,14 @@ static GtkWidget *_find_details(GtkNotebook *notebook, AlertMsg *msg) return NULL; } -static void _show_details(GritsPoly *county, GritsPluginAlert *alert) +static gboolean _show_details(GritsPoly *county, GdkEvent *_, GritsPluginAlert *alert) { /* Add details for this messages */ AlertMsg *msg = g_object_get_data(G_OBJECT(county), "msg"); - msg_load_cap(alert->http, msg); + + // TODO: move this to a thread since it blocks on net access + if (!msg_load_cap(alert->http, msg)) + return FALSE; GtkWidget *dialog = alert->details; GtkWidget *content = gtk_dialog_get_content_area(GTK_DIALOG(dialog)); @@ -520,10 +526,12 @@ static void _show_details(GritsPoly *county, GritsPluginAlert *alert) gtk_widget_show_all(dialog); gint num = gtk_notebook_page_num(GTK_NOTEBOOK(notebook), details); gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), num); + + return FALSE; } /* Update counties */ -static void _alert_leave(GritsPoly *county, GritsPluginAlert *alert) +static gboolean _alert_leave(GritsPoly *county, GdkEvent *_, GritsPluginAlert *alert) { g_debug("_alert_leave"); if (county->width == 3) { @@ -533,9 +541,10 @@ static void _alert_leave(GritsPoly *county, GritsPluginAlert *alert) county->width = 1; } grits_object_queue_draw(GRITS_OBJECT(county)); + return FALSE; } -static void _alert_enter(GritsPoly *county, GritsPluginAlert *alert) +static gboolean _alert_enter(GritsPoly *county, GdkEvent *_, GritsPluginAlert *alert) { g_debug("_alert_enter"); if (county->width == 3) { @@ -545,11 +554,12 @@ static void _alert_enter(GritsPoly *county, GritsPluginAlert *alert) county->width = 2; } grits_object_queue_draw(GRITS_OBJECT(county)); + return FALSE; } /* Update polygons */ static void _load_common(GritsPluginAlert *alert, AlertMsg *msg, GritsPoly *poly, - float color, float border, int width) + float color, float border, int width, gchar *hidden) { g_object_set_data(G_OBJECT(poly), "msg", msg); poly->color[0] = poly->border[0] = (float)msg->info->color[0] / 256; @@ -559,7 +569,8 @@ static void _load_common(GritsPluginAlert *alert, AlertMsg *msg, GritsPoly *poly poly->border[3] = border; poly->width = width; GRITS_OBJECT(poly)->lod = 0; - GRITS_OBJECT(poly)->hidden = msg->info->hidden; + GRITS_OBJECT(poly)->hidden = msg->info->hidden || + grits_prefs_get_boolean(alert->prefs, hidden, NULL); g_signal_connect(poly, "enter", G_CALLBACK(_alert_enter), alert); g_signal_connect(poly, "leave", G_CALLBACK(_alert_leave), alert); g_signal_connect(poly, "clicked", G_CALLBACK(_show_details), alert); @@ -570,11 +581,15 @@ static GritsPoly *_load_storm_based(GritsPluginAlert *alert, AlertMsg *msg) if (!msg->info->ispoly) return NULL; - msg_load_cap(alert->http, msg); + if (!msg_load_cap(alert->http, msg)) + return NULL; + + if (!msg->polygon) + return NULL; GritsPoly *poly = grits_poly_parse(msg->polygon, "\t", " ", ","); - _load_common(alert, msg, poly, 0, 1, 3); - grits_viewer_add(alert->viewer, GRITS_OBJECT(poly), GRITS_LEVEL_WORLD+2, TRUE); + _load_common(alert, msg, poly, 0, 1, 3, "alert/hide_storm_based"); + grits_viewer_add(alert->viewer, GRITS_OBJECT(poly), GRITS_LEVEL_WORLD+4, FALSE); return poly; } @@ -599,7 +614,7 @@ static GritsPoly *_load_county_based(GritsPluginAlert *alert, AlertMsg *msg) /* Create new county based warning */ GritsPoly *poly = fips_combine(counties); - _load_common(alert, msg, poly, 0.25, 0.25, 0); + _load_common(alert, msg, poly, 0.25, 0.25, 0, "alert/hide_county_based"); grits_viewer_add(alert->viewer, GRITS_OBJECT(poly), GRITS_LEVEL_WORLD+1, FALSE); g_list_free(counties); @@ -607,24 +622,40 @@ static GritsPoly *_load_county_based(GritsPluginAlert *alert, AlertMsg *msg) } /* Update buttons */ -static void _button_click(GtkToggleButton *button, gpointer _alert) +static gboolean _show_hide(GtkToggleButton *button, GritsPluginAlert *alert) { - g_debug("GritsPluginAlert: _button_click"); - GritsPluginAlert *alert = _alert; + g_debug("GritsPluginAlert: _show_hide - alert=%p, config=%p", alert, alert->config); + + /* Check if we've clicked a alert type button */ AlertInfo *info = g_object_get_data(G_OBJECT(button), "info"); - info->hidden = !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)); + if (info) + info->hidden = !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)); - /* Show/hide each polygons */ + /* Update county/storm based hiding */ + GtkWidget *ctoggle = g_object_get_data(G_OBJECT(alert->config), "county_based"); + GtkWidget *stoggle = g_object_get_data(G_OBJECT(alert->config), "storm_based"); + + gboolean cshow = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ctoggle)); + gboolean sshow = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(stoggle)); + + grits_prefs_set_boolean(alert->prefs, "alert/hide_county_based", !cshow); + grits_prefs_set_boolean(alert->prefs, "alert/hide_storm_based", !sshow); + + /* Show/hide each message */ for (GList *cur = alert->msgs; cur; cur = cur->next) { AlertMsg *msg = cur->data; - if (msg->info != info) - continue; - if (msg->county_based) GRITS_OBJECT(msg->county_based)->hidden = info->hidden; - if (msg->storm_based) GRITS_OBJECT(msg->storm_based)->hidden = info->hidden; + gboolean hide = msg->info->hidden; + if (msg->county_based) + GRITS_OBJECT(msg->county_based)->hidden = !cshow || hide; + if (msg->storm_based) + GRITS_OBJECT(msg->storm_based)->hidden = !sshow || hide; } - gtk_widget_queue_draw(GTK_WIDGET(alert->viewer)); + + grits_viewer_queue_draw(alert->viewer); + return TRUE; } + static GtkWidget *_button_new(AlertInfo *info) { g_debug("GritsPluginAlert: _button_new - %s", info->title); @@ -685,18 +716,15 @@ static gboolean _update_buttons(GritsPluginAlert *alert) GtkWidget *table = g_object_get_data(G_OBJECT(alerts), alert_info[i].category); GList *kids = gtk_container_get_children(GTK_CONTAINER(table)); - gint nkids = g_list_length(kids); - guint rows, cols; - gtk_table_get_size(GTK_TABLE(table), &rows, &cols); - gint x = nkids % cols; - gint y = nkids / cols; + gint nkids = g_list_length(kids); + gint x = nkids / CONFIG_HEIGHT; + gint y = nkids % CONFIG_HEIGHT; g_list_free(kids); GtkWidget *button = _button_new(&alert_info[i]); gtk_table_attach(GTK_TABLE(table), button, x, x+1, y, y+1, GTK_FILL|GTK_EXPAND, GTK_FILL, 0, 0); - g_signal_connect(button, "clicked", - G_CALLBACK(_button_click), alert); + g_signal_connect(button, "clicked", G_CALLBACK(_show_hide), alert); } /* Set time widget */ @@ -708,6 +736,7 @@ static gboolean _update_buttons(GritsPluginAlert *alert) g_free(date_str); gtk_widget_show_all(GTK_WIDGET(alert->config)); + alert->update_source = 0; return FALSE; } @@ -737,11 +766,19 @@ static void _update_warnings(GritsPluginAlert *alert, GList *old) } /* Add new messages */ + /* Load counties first since it does not require network access */ for (GList *cur = alert->msgs; cur; cur = cur->next) { AlertMsg *msg = cur->data; msg->county_based = _load_county_based(alert, msg); + } + grits_viewer_queue_draw(alert->viewer); + for (GList *cur = alert->msgs; cur; cur = cur->next) { + AlertMsg *msg = cur->data; msg->storm_based = _load_storm_based(alert, msg); + if (alert->aborted) + return; } + grits_viewer_queue_draw(alert->viewer); g_debug("GritsPluginAlert: _load_warnings - end"); } @@ -750,6 +787,8 @@ static void _update_warnings(GritsPluginAlert *alert, GList *old) static void _update(gpointer _, gpointer _alert) { GritsPluginAlert *alert = _alert; + if (alert->aborted) + return; GList *old = alert->msgs; g_debug("GritsPluginAlert: _update"); @@ -758,13 +797,13 @@ static void _update(gpointer _, gpointer _alert) if (!(alert->msgs = msg_load_index(alert->http, when, &alert->updated, offline))) return; - g_idle_add((GSourceFunc)_update_buttons, alert); + if (!alert->update_source) + alert->update_source = g_idle_add((GSourceFunc)_update_buttons, alert); _update_warnings(alert, old); g_list_foreach(old, (GFunc)msg_free, NULL); g_list_free(old); - gtk_widget_queue_draw(GTK_WIDGET(alert->viewer)); g_debug("GritsPluginAlert: _update - end"); } @@ -774,27 +813,34 @@ static void _on_update(GritsPluginAlert *alert) } /* Init helpers */ -static GtkWidget *_make_config(void) +static GtkWidget *_make_config(GritsPluginAlert *alert) { - GtkWidget *config = gtk_vbox_new(FALSE, 0); + GtkWidget *config = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); /* Setup tools area */ - GtkWidget *tools = gtk_hbox_new(FALSE, 10); + GtkWidget *tools = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 10); GtkWidget *updated = gtk_label_new(" Loading..."); + GtkWidget *storm_based = gtk_toggle_button_new_with_label("Storm based"); + GtkWidget *county_based = gtk_toggle_button_new_with_label("County based"); gtk_label_set_use_markup(GTK_LABEL(updated), TRUE); - gtk_box_pack_start(GTK_BOX(tools), updated, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(tools), updated, FALSE, FALSE, 0); + gtk_box_pack_end (GTK_BOX(tools), storm_based, FALSE, FALSE, 0); + gtk_box_pack_end (GTK_BOX(tools), county_based, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(config), tools, FALSE, FALSE, 0); - g_object_set_data(G_OBJECT(config), "updated", updated); + g_object_set_data(G_OBJECT(config), "updated", updated); + g_object_set_data(G_OBJECT(config), "storm_based", storm_based); + g_object_set_data(G_OBJECT(config), "county_based", county_based); + g_signal_connect(storm_based, "toggled", G_CALLBACK(_show_hide), alert); + g_signal_connect(county_based, "toggled", G_CALLBACK(_show_hide), alert); /* Setup alerts */ gchar *labels[] = {"Warnings", "Watches", "Advisories", "Other"}; gchar *keys[] = {"warning", "watch", "advisory", "other"}; - gint cols[] = {2, 2, 3, 2}; - GtkWidget *alerts = gtk_hbox_new(FALSE, 10); + GtkWidget *alerts = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 10); for (int i = 0; i < G_N_ELEMENTS(labels); i++) { GtkWidget *frame = gtk_frame_new(labels[i]); - GtkWidget *table = gtk_table_new(1, cols[i], TRUE); + GtkWidget *table = gtk_table_new(1, 1, TRUE); GtkWidget *label = gtk_frame_get_label_widget(GTK_FRAME(frame)); gtk_label_set_use_markup(GTK_LABEL(label), TRUE); gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_NONE); @@ -820,7 +866,7 @@ static gboolean _clear_details(GtkWidget *dialog) return TRUE; } -static gboolean _set_details_uri(GtkWidget *notebook, GtkNotebookPage *_, +static gboolean _set_details_uri(GtkWidget *notebook, gpointer _, guint num, GtkWidget *button) { g_debug("_set_details_uri"); @@ -871,6 +917,13 @@ GritsPluginAlert *grits_plugin_alert_new(GritsViewer *viewer, GritsPrefs *prefs) for (GList *cur = alert->states; cur; cur = cur->next) grits_viewer_add(viewer, cur->data, GRITS_LEVEL_WORLD+1, FALSE); + gboolean chide = grits_prefs_get_boolean(alert->prefs, "alert/hide_county_based", NULL); + gboolean shide = grits_prefs_get_boolean(alert->prefs, "alert/hide_storm_based", NULL); + GtkWidget *ctoggle = g_object_get_data(G_OBJECT(alert->config), "county_based"); + GtkWidget *stoggle = g_object_get_data(G_OBJECT(alert->config), "storm_based"); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ctoggle), !chide); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(stoggle), !shide); + _on_update(alert); return alert; } @@ -897,8 +950,8 @@ static void grits_plugin_alert_init(GritsPluginAlert *alert) { g_debug("GritsPluginAlert: init"); /* Set defaults */ - alert->threads = g_thread_pool_new(_update, alert, 1, TRUE, NULL); - alert->config = _make_config(); + alert->threads = g_thread_pool_new(_update, alert, 1, FALSE, NULL); + alert->config = _make_config(alert); alert->http = grits_http_new(G_DIR_SEPARATOR_S "alerts" G_DIR_SEPARATOR_S "cap" G_DIR_SEPARATOR_S); @@ -915,17 +968,17 @@ static void grits_plugin_alert_dispose(GObject *gobject) { g_debug("GritsPluginAlert: dispose"); GritsPluginAlert *alert = GRITS_PLUGIN_ALERT(gobject); + alert->aborted = TRUE; /* Drop references */ if (alert->viewer) { GritsViewer *viewer = alert->viewer; - alert->viewer = NULL; g_signal_handler_disconnect(viewer, alert->refresh_id); g_signal_handler_disconnect(viewer, alert->time_changed_id); - soup_session_abort(alert->http->soup); + grits_http_abort(alert->http); g_thread_pool_free(alert->threads, TRUE, TRUE); - gtk_widget_destroy(alert->details); - while (gtk_events_pending()) - gtk_main_iteration(); + if (alert->update_source) + g_source_remove(alert->update_source); + alert->viewer = NULL; for (GList *cur = alert->msgs; cur; cur = cur->next) { AlertMsg *msg = cur->data; if (msg->county_based) grits_viewer_remove(viewer, @@ -935,6 +988,7 @@ static void grits_plugin_alert_dispose(GObject *gobject) } for (GList *cur = alert->states; cur; cur = cur->next) grits_viewer_remove(viewer, cur->data); + gtk_widget_destroy(alert->details); g_object_unref(alert->prefs); g_object_unref(viewer); }