From e52d6ca128eec11d97c2278e1fa791af38b5bb15 Mon Sep 17 00:00:00 2001 From: Wayne Song Date: Thu, 14 Jun 2012 22:48:06 -0700 Subject: [PATCH] Fixed forecast to work with api.yr.no data --- panel-plugin/weather-data.c | 22 ++++-- panel-plugin/weather-data.h | 4 + panel-plugin/weather-parsers.c | 56 +++++++++++--- panel-plugin/weather-parsers.h | 3 + panel-plugin/weather-summary.c | 159 +++++++++++++++------------------------- 5 files changed, 128 insertions(+), 116 deletions(-) diff --git a/panel-plugin/weather-data.c b/panel-plugin/weather-data.c index 5c17a8d..a83fe61 100644 --- a/panel-plugin/weather-data.c +++ b/panel-plugin/weather-data.c @@ -35,8 +35,7 @@ static gboolean need_interval(datas type) const gchar * get_data (xml_weather *data, datas type) { - const xml_time *timeslice = NULL; - const xml_location *loc = NULL; + xml_time *timeslice = NULL; if (data == NULL) return ""; @@ -44,8 +43,13 @@ get_data (xml_weather *data, datas type) timeslice = get_current_timeslice(data, need_interval(type)); if (timeslice == NULL) return ""; + return get_data_from_timeslice (timeslice, type); +} - loc = timeslice->location; +const gchar * +get_data_from_timeslice (xml_time *timeslice, datas type) +{ + const xml_location *loc = timeslice->location; switch(type) { case TEMPERATURE: @@ -81,8 +85,7 @@ get_data (xml_weather *data, datas type) const gchar * get_unit (xml_weather *data, units unit, datas type) { - const xml_time *timeslice = NULL; - const xml_location *loc = NULL; + xml_time *timeslice = NULL; if (data == NULL) return ""; @@ -90,12 +93,17 @@ get_unit (xml_weather *data, units unit, datas type) timeslice = get_current_timeslice(data, need_interval(type)); if (timeslice == NULL) return ""; + return get_unit_from_timeslice (timeslice, unit, type); +} - loc = timeslice->location; +const gchar * +get_unit_from_timeslice (xml_time *timeslice, units unit, datas type) +{ + const xml_location *loc = timeslice->location; switch(type) { case TEMPERATURE: - return strcmp(loc->temperature_unit, "celcius") ? "°F":"°C"; + return strcmp(CHK_NULL(loc->temperature_unit), "celcius") ? "°F":"°C"; case PRESSURE: return CHK_NULL(loc->pressure_unit); case WIND_SPEED: diff --git a/panel-plugin/weather-data.h b/panel-plugin/weather-data.h index 5e80763..f6fd6fe 100644 --- a/panel-plugin/weather-data.h +++ b/panel-plugin/weather-data.h @@ -44,7 +44,11 @@ typedef enum { const gchar * get_data (xml_weather *data, datas type); const gchar * +get_data_from_timeslice (xml_time *timeslice, datas type); +const gchar * get_unit (xml_weather *data, units unit, datas type); +const gchar * +get_unit_from_timeslice (xml_time *timeslice, units unit, datas type); G_END_DECLS #endif diff --git a/panel-plugin/weather-parsers.c b/panel-plugin/weather-parsers.c index fd16609..ef85473 100644 --- a/panel-plugin/weather-parsers.c +++ b/panel-plugin/weather-parsers.c @@ -158,9 +158,8 @@ xml_time *get_timeslice(xml_weather *data, time_t start, time_t end) return data->timeslice[data->num_timeslices - 1]; } -xml_time *get_current_timeslice(xml_weather *data, gboolean interval) +xml_time *get_closest_timeslice(xml_weather *data, time_t t, gboolean interval) { - time_t now = time(NULL); int closest = -1; int min_found = 7 * 24 * 3600; int i; @@ -169,19 +168,19 @@ xml_time *get_current_timeslice(xml_weather *data, gboolean interval) if (interval != (data->timeslice[i]->start != data->timeslice[i]->end)) continue; - if (data->timeslice[i]->start <= now - && data->timeslice[i]->end >= now) + if (data->timeslice[i]->start <= t + && data->timeslice[i]->end >= t) return data->timeslice[i]; /* we also search for the closest before */ - if (data->timeslice[i]->end < now - && data->timeslice[i]->end - now < min_found) { - min_found = data->timeslice[i]->end - now; + if (data->timeslice[i]->end < t + && ABS_VALUE(data->timeslice[i]->end - t) < min_found) { + min_found = ABS_VALUE(data->timeslice[i]->end - t); closest = i; } /* and after */ - if (data->timeslice[i]->start > now - && data->timeslice[i]->start - now < min_found) { - min_found = data->timeslice[i]->start - now; + if (data->timeslice[i]->start > t + && ABS_VALUE(data->timeslice[i]->start - t) < min_found) { + min_found = ABS_VALUE(data->timeslice[i]->start - t); closest = i; } } @@ -191,6 +190,43 @@ xml_time *get_current_timeslice(xml_weather *data, gboolean interval) return NULL; } +xml_time *get_next_closest_timeslice(xml_weather *data, time_t t, gboolean interval) +{ + int closest = -1; + int min_found = 7 * 24 * 3600; + int i; + + for (i = 0; i < data->num_timeslices; i++) { + if (interval != + (data->timeslice[i]->start != data->timeslice[i]->end)) + continue; + if (data->timeslice[i]->start <= t + && data->timeslice[i]->end >= t) + return data->timeslice[i]; + /* we also search for the closest before */ + if (data->timeslice[i]->end < t + && ABS_VALUE(data->timeslice[i]->end - t) < min_found) { + min_found = ABS_VALUE(data->timeslice[i]->end - t); + closest = i; + } + /* and after */ + if (data->timeslice[i]->start > t + && ABS_VALUE(data->timeslice[i]->start - t) < min_found) { + min_found = ABS_VALUE(data->timeslice[i]->start - t); + closest = i; + } + } + if (closest != -1 && closest < data->num_timeslices - 1) + return data->timeslice[closest + 1]; + + return NULL; +} + +xml_time *get_current_timeslice(xml_weather *data, gboolean interval) +{ + return get_closest_timeslice(data, time(NULL), interval); +} + void parse_location (xmlNode * cur_node, xml_location *loc) { xmlNode *child_node; diff --git a/panel-plugin/weather-parsers.h b/panel-plugin/weather-parsers.h index b461f90..cc5755a 100644 --- a/panel-plugin/weather-parsers.h +++ b/panel-plugin/weather-parsers.h @@ -26,6 +26,7 @@ G_BEGIN_DECLS #define DATA(node) (gchar *) xmlNodeListGetString(node->doc, node->children, 1) #define PROP(node, prop) ((gchar *) xmlGetProp ((node), (const xmlChar *) (prop))) #define NODE_IS_TYPE(node, type) xmlStrEqual (node->name, (const xmlChar *) type) +#define ABS_VALUE(x) x < 0 ? -x : x #define MAX_TIMESLICE 250 enum @@ -86,6 +87,8 @@ void parse_time (xmlNode * cur_node, xml_weather * data); void parse_location (xmlNode * cur_node, xml_location *location); xml_time *get_timeslice(xml_weather *data, time_t start, time_t end); +xml_time *get_closest_timeslice(xml_weather *data, time_t t, gboolean interval); +xml_time *get_next_closest_timeslice(xml_weather *data, time_t t, gboolean interval); xml_time *get_current_timeslice(xml_weather *data, gboolean interval); void xml_weather_free (xml_weather * data); diff --git a/panel-plugin/weather-summary.c b/panel-plugin/weather-summary.c index b0a4aae..40edd78 100644 --- a/panel-plugin/weather-summary.c +++ b/panel-plugin/weather-summary.c @@ -267,10 +267,12 @@ create_summary_tab (xfceweather_data *data) APPEND_BTEXT (value); g_free (value); - timeslice = get_current_timeslice(data->weatherdata, FALSE); - value = g_strdup_printf (_("Coordinates: lat %s lon %s\nData applies to: %s\n"), + if (data->weatherdata != NULL) { + timeslice = get_current_timeslice(data->weatherdata, FALSE); + value = g_strdup_printf (_("Coordinates: lat %s lon %s\nData applies to: %s\n"), data->lat, data->lon, ctime(×lice->start)); - APPEND_TEXT_ITEM_REAL (value); + APPEND_TEXT_ITEM_REAL (value); + } /* Temperature */ APPEND_BTEXT (_("\nTemperature\n")); @@ -322,26 +324,41 @@ create_summary_tab (xfceweather_data *data) } static GtkWidget * -make_forecast (xml_weather *weatherdata, +make_forecast (xml_weather *data, + time_t t, units unit) { GtkWidget *item_vbox, *temp_hbox, *icon_hbox, - *label, *icon_d, *icon_n, *box_d, *box_n; + *label, *icon_widg, *box_widg; GdkPixbuf *icon; gchar *str, *day, *wind; + xml_time *timeslice, *next_timeslice; item_vbox = gtk_vbox_new (FALSE, 0); -#if 0 - DBG ("this day %s", weatherdata->day); + gtk_container_set_border_width (GTK_CONTAINER (item_vbox), 6); + timeslice = get_closest_timeslice(data, t, FALSE); + if (!timeslice) + return item_vbox; + /* api.yr.no doesn't seem to include precipitation data or symbol data + in the timeslice that stores all the other weather data for a given time. + Instead, it seems to store this data in the timeslice after that one. */ + next_timeslice = get_next_closest_timeslice(data, t, FALSE); + if (!next_timeslice) + /* If we can't get the next timeslice, then the current one is the best + that we can do. */ + next_timeslice = timeslice; label = gtk_label_new (NULL); gtk_misc_set_alignment (GTK_MISC (label), 0.5, 0.5); - day = translate_day (get_data_f (weatherdata, WDAY)); - str = g_strdup_printf ("%s", day ? day : get_data_f (weatherdata, WDAY)); + const gchar *days[] = {"su", "mo", "tu", "we", "th", "fr", "sa", NULL}; + gint weekday = localtime(&(timeslice->start))->tm_wday; + + day = translate_day (days[weekday]); + str = g_strdup_printf ("%s", day ? day : ""); g_free (day); gtk_label_set_markup (GTK_LABEL (label), str); @@ -351,20 +368,11 @@ make_forecast (xml_weather *weatherdata, icon_hbox = gtk_hbox_new (FALSE, 0); - icon = get_icon (get_data_f (weatherdata, ICON_D), 48); - icon_d = gtk_image_new_from_pixbuf (icon); - box_d = gtk_event_box_new (); - gtk_event_box_set_visible_window (GTK_EVENT_BOX (box_d), FALSE); - gtk_container_add (GTK_CONTAINER (box_d), icon_d); - - if (G_LIKELY (icon)) - g_object_unref (G_OBJECT (icon)); - - icon = get_icon (get_data_f (weatherdata, ICON_N), 48); - icon_n = gtk_image_new_from_pixbuf (icon); - box_n = gtk_event_box_new (); - gtk_event_box_set_visible_window (GTK_EVENT_BOX (box_n), FALSE); - gtk_container_add (GTK_CONTAINER (box_n), icon_n); + icon = get_icon (get_data_from_timeslice (next_timeslice, SYMBOL), 48); + icon_widg = gtk_image_new_from_pixbuf (icon); + box_widg = gtk_event_box_new (); + gtk_event_box_set_visible_window (GTK_EVENT_BOX (box_widg), FALSE); + gtk_container_add (GTK_CONTAINER (box_widg), icon_widg); if (G_LIKELY (icon)) g_object_unref (G_OBJECT (icon)); @@ -373,17 +381,11 @@ make_forecast (xml_weather *weatherdata, tooltips = gtk_tooltips_new (); str = g_strdup_printf (_("Day: %s"), - translate_desc (get_data_f (weatherdata, TRANS_D))); - gtk_tooltips_set_tip (tooltips, box_d, str, NULL); - g_free (str); - - str = g_strdup_printf (_("Night: %s"), - translate_desc (get_data_f (weatherdata, TRANS_N))); - gtk_tooltips_set_tip (tooltips, box_n, str, NULL); + translate_desc (get_data_from_timeslice (next_timeslice, SYMBOL))); + gtk_tooltips_set_tip (tooltips, box_widg, str, NULL); g_free (str); - gtk_box_pack_start (GTK_BOX (icon_hbox), box_d, TRUE, TRUE, 0); - gtk_box_pack_start (GTK_BOX (icon_hbox), box_n, TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (icon_hbox), box_widg, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (item_vbox), icon_hbox, FALSE, FALSE, 0); label = gtk_label_new (NULL); @@ -394,17 +396,11 @@ make_forecast (xml_weather *weatherdata, temp_hbox = gtk_hbox_new (FALSE, 0); label = gtk_label_new (NULL); gtk_misc_set_alignment (GTK_MISC (label), 0.5, 0.5); - str = g_strdup_printf ("%s %%", get_data_f (weatherdata, PPCP_D)); + str = g_strdup_printf ("%s %%", get_data_from_timeslice (next_timeslice, PRECIPITATIONS)); gtk_label_set_markup (GTK_LABEL (label), str); g_free (str); gtk_box_pack_start (GTK_BOX (temp_hbox), label, TRUE, TRUE, 0); - label = gtk_label_new (NULL); - gtk_misc_set_alignment (GTK_MISC (label), 0.5, 0.5); - str = g_strdup_printf ("%s %%", get_data_f (weatherdata, PPCP_N)); - gtk_label_set_markup (GTK_LABEL (label), str); - g_free (str); - gtk_box_pack_start (GTK_BOX (temp_hbox), label, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (item_vbox), temp_hbox, FALSE, FALSE, 0); @@ -417,18 +413,11 @@ make_forecast (xml_weather *weatherdata, label = gtk_label_new (NULL); gtk_misc_set_alignment (GTK_MISC (label), 0.5, 0.5); str = g_strdup_printf ("%s %s", - get_data_f (weatherdata, TEMP_MAX), get_unit (unit, - TEMP)); - gtk_label_set_markup (GTK_LABEL (label), str); - g_free (str); - gtk_box_pack_start (GTK_BOX (temp_hbox), label, TRUE, TRUE, 0); - label = gtk_label_new (NULL); - gtk_misc_set_alignment (GTK_MISC (label), 0.5, 0.5); - str = g_strdup_printf ("%s %s", - get_data_f (weatherdata, TEMP_MIN), get_unit (unit, - TEMP)); + get_data_from_timeslice (timeslice, TEMPERATURE), + get_unit_from_timeslice (timeslice, unit, TEMPERATURE)); gtk_label_set_markup (GTK_LABEL (label), str); g_free (str); + gtk_box_pack_start (GTK_BOX (temp_hbox), label, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (item_vbox), temp_hbox, FALSE, FALSE, 0); @@ -441,21 +430,10 @@ make_forecast (xml_weather *weatherdata, label = gtk_label_new (NULL); gtk_misc_set_alignment (GTK_MISC (label), 0.5, 0.5); - wind = translate_wind_direction (get_data_f (weatherdata, W_DIRECTION_D)); + wind = translate_wind_direction (get_data_from_timeslice (timeslice, WIND_DIRECTION)); gtk_label_set_markup (GTK_LABEL (label), - wind ? wind : get_data_f (weatherdata, - W_DIRECTION_D)); - g_free (wind); - - gtk_box_pack_start (GTK_BOX (temp_hbox), label, TRUE, TRUE, 0); - - label = gtk_label_new (NULL); - gtk_misc_set_alignment (GTK_MISC (label), 0.5, 0.5); - - wind = translate_wind_direction (get_data_f (weatherdata, W_DIRECTION_N)); - gtk_label_set_markup (GTK_LABEL (label), - wind ? wind : get_data_f (weatherdata, - W_DIRECTION_N)); + wind ? wind : get_data_from_timeslice (timeslice, + WIND_DIRECTION)); g_free (wind); gtk_box_pack_start (GTK_BOX (temp_hbox), label, TRUE, TRUE, 0); @@ -465,58 +443,41 @@ make_forecast (xml_weather *weatherdata, temp_hbox = gtk_hbox_new (FALSE, 2); label = gtk_label_new (NULL); gtk_misc_set_alignment (GTK_MISC (label), 0.5, 0.5); - str = g_strdup_printf ("%s %s", get_data_f (weatherdata, W_SPEED_D), - get_unit (unit, WIND_SPEED)); + str = g_strdup_printf ("%s %s", + get_data_from_timeslice (timeslice, WIND_SPEED), + get_unit_from_timeslice (timeslice, unit, WIND_SPEED)); gtk_label_set_markup (GTK_LABEL (label), str); g_free (str); - gtk_box_pack_start (GTK_BOX (temp_hbox), label, TRUE, TRUE, 0); - label = gtk_label_new (NULL); - gtk_misc_set_alignment (GTK_MISC (label), 0.5, 0.5); - str = g_strdup_printf ("%s %s", get_data_f (weatherdata, W_SPEED_N), - get_unit (unit, WIND_SPEED)); - gtk_label_set_markup (GTK_LABEL (label), str); - g_free (str); gtk_box_pack_start (GTK_BOX (temp_hbox), label, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (item_vbox), temp_hbox, FALSE, FALSE, 0); - DBG ("Done"); -#endif return item_vbox; } - - static GtkWidget * create_forecast_tab (xfceweather_data *data) { GtkWidget *widg = gtk_hbox_new (FALSE, 0); guint i; + time_t current_time = time(NULL); gtk_container_set_border_width (GTK_CONTAINER (widg), 6); -#if 0 - if (data->weatherdata && data->weatherdata->dayf) - { - for (i = 0; i < XML_WEATHER_DAYF_N - 1; i++) - { - if (!data->weatherdata->dayf[i]) - break; - - DBG ("%s", data->weatherdata->dayf[i]->day); - - gtk_box_pack_start (GTK_BOX (widg), - make_forecast (data->weatherdata->dayf[i], data->unit), FALSE, - FALSE, 0); - gtk_box_pack_start (GTK_BOX (widg), gtk_vseparator_new (), TRUE, - TRUE, 0); - } - - if (data->weatherdata->dayf[i]) - gtk_box_pack_start (GTK_BOX (widg), - make_forecast (data->weatherdata->dayf[i], data->unit), FALSE, FALSE, - 0); - } -#endif + if (data->weatherdata) + { + for (i = 0; i < 6; i++) + { + gtk_box_pack_start (GTK_BOX (widg), + make_forecast (data->weatherdata, + current_time, + data->unit), FALSE, + FALSE, 0); + if (i != 5) // Add a separator if we're not on the last one + gtk_box_pack_start (GTK_BOX (widg), gtk_vseparator_new (), TRUE, + TRUE, 0); + current_time += 60*60*24; // Add 24 hours to current time + } + } return widg; } -- 1.7.9.5