diff --git a/panel-plugin/weather-data.c b/panel-plugin/weather-data.c index 5c17a8d..c36402e 100644 --- a/panel-plugin/weather-data.c +++ b/panel-plugin/weather-data.c @@ -27,21 +27,22 @@ #define CHK_NULL(s) ((s) ? (s):"") -static gboolean need_interval(datas type) +gboolean has_timeslice(xml_weather *data, time_t start, time_t end) { - return type == PRECIPITATIONS || type == SYMBOL; + int i = 0; + for (i = 0; i < data->num_timeslices; i++) { + if (data->timeslice[i]->start == start + && data->timeslice[i]->end == end) + return TRUE; + } + return FALSE; } const gchar * -get_data (xml_weather *data, datas type) +get_data (xml_time *timeslice, datas type) { - const xml_time *timeslice = NULL; const xml_location *loc = NULL; - if (data == NULL) - return ""; - - timeslice = get_current_timeslice(data, need_interval(type)); if (timeslice == NULL) return ""; @@ -79,15 +80,10 @@ get_data (xml_weather *data, datas type) } const gchar * -get_unit (xml_weather *data, units unit, datas type) +get_unit (xml_time *timeslice, units unit, datas type) { - const xml_time *timeslice = NULL; const xml_location *loc = NULL; - if (data == NULL) - return ""; - - timeslice = get_current_timeslice(data, need_interval(type)); if (timeslice == NULL) return ""; @@ -118,3 +114,215 @@ get_unit (xml_weather *data, units unit, datas type) return ""; } +/* + * Calculate start and end of a daytime interval using given dates. + * We ought to take one of the intervals supplied by the XML feed, + * which gives the most consistent data and does not force too many + * searches to find something that fits. The following chosen + * intervals were pretty reliable for several tested locations at the + * time of this writing and gave reasonable results: + * Morning: 08:00-14:00 + * Afternoon: 14:00-20:00 + * Evening: 20:00-02:00 + * Night: 02:00-08:00 + */ +void +get_daytime_interval(struct tm *start_t, struct tm *end_t, daytime dt) +{ + start_t->tm_min = end_t->tm_min = 0; + start_t->tm_sec = end_t->tm_sec = 0; + start_t->tm_isdst = end_t->tm_isdst = -1; + switch(dt) { + case MORNING: + start_t->tm_hour = 8; + end_t->tm_hour = 14; + break; + case AFTERNOON: + start_t->tm_hour = 14; + end_t->tm_hour = 20; + break; + case EVENING: + start_t->tm_hour = 20; + end_t->tm_hour = 26; + break; + case NIGHT: + start_t->tm_hour = 26; + end_t->tm_hour = 32; + break; + } +} + +/* + * Check whether it is night or day. Until we have a way to get the + * exact times for sunrise and sunset, we'll have to use reasonable + * hardcoded values. + */ +gboolean +is_night_time() +{ + time_t now; + struct tm tm_now; + time(&now); + tm_now = *localtime(&now); + return (tm_now.tm_hour >= 21 || tm_now.tm_hour < 5); +} + +time_t +time_calc(struct tm tm_time, gint year, gint month, gint day, gint hour, gint min, gint sec) +{ + time_t result; + struct tm tm_new; + tm_new = tm_time; + if (year) + tm_new.tm_year += year; + if (month) + tm_new.tm_mon += month; + if (day) + tm_new.tm_mday += day; + if (hour) + tm_new.tm_hour += hour; + if (min) + tm_new.tm_min += min; + if (sec) + tm_new.tm_sec += sec; + result = mktime(&tm_new); + return result; +} + +time_t +time_calc_hour(struct tm tm_time, gint hours) { + return time_calc(tm_time, 0, 0, 0, hours, 0, 0); +} + +time_t +time_calc_day(struct tm tm_time, gint days) { + return time_calc(tm_time, 0, 0, days, 0, 0, 0); +} + +/* + * Find a timeslice that best matches the start and end times within + * reasonable limits. + */ +xml_time * +find_timeslice(xml_weather *data, struct tm tm_start, struct tm tm_end) +{ + time_t start_t, end_t; + gint hours, hours_limit = 3, interval = 0, interval_limit; + + /* first search for intervals of the same length */ + start_t = mktime(&tm_start); + end_t = mktime(&tm_end); + interval_limit = (gint) (difftime(end_t, start_t) / 3600); + + while (interval <= interval_limit) { + hours = 0; + while (hours <= hours_limit) { + /* check with previous hours */ + start_t = time_calc_hour(tm_start, 0 - hours); + end_t = time_calc_hour(tm_end, 0 - hours - interval); + + if (has_timeslice(data, start_t, end_t)) + return get_timeslice(data, start_t, end_t); + + /* check with later hours */ + start_t = time_calc_hour(tm_start, hours); + end_t = time_calc_hour(tm_end, hours - interval); + + if (has_timeslice(data, start_t, end_t)) + return get_timeslice(data, start_t, end_t); + + hours++; + } + interval++; + } + + return NULL; +} + +/* + * Take point and interval data and generate one combined timeslice + * that provides all information needed to present a forecast. + */ +xml_time * +make_combined_timeslice(xml_time *point, xml_time *interval) +{ + xml_time *forecast; + xml_location *loc; + gint i; + + if (point == NULL || interval == NULL) + return NULL; + + forecast = g_slice_new0(xml_time); + if (forecast == NULL) + return NULL; + + loc = g_slice_new0(xml_location); + if (loc == NULL) + return forecast; + + forecast->start = point->start; + forecast->end = interval->end; + + loc->temperature_value = g_strdup(point->location->temperature_value); + loc->temperature_unit = g_strdup(point->location->temperature_unit); + + loc->wind_dir_deg = g_strdup(point->location->wind_dir_deg); + loc->wind_dir_name = g_strdup(point->location->wind_dir_name); + loc->wind_speed_mps = g_strdup(point->location->wind_speed_mps); + loc->wind_speed_beaufort = g_strdup(point->location->wind_speed_beaufort); + + loc->humidity_value = g_strdup(point->location->humidity_value); + loc->humidity_unit = g_strdup(point->location->humidity_unit); + + loc->pressure_value = g_strdup(point->location->pressure_value); + loc->pressure_unit = g_strdup(point->location->pressure_unit); + + for (i = 0; i < NUM_CLOUDINESS; i++) + loc->cloudiness_percent[i] = g_strdup(point->location->cloudiness_percent[i]); + + loc->fog_percent = g_strdup(point->location->fog_percent); + + loc->precipitation_value = g_strdup(interval->location->precipitation_value); + loc->precipitation_unit = g_strdup(interval->location->precipitation_unit); + + loc->symbol_id = interval->location->symbol_id; + loc->symbol = g_strdup(interval->location->symbol); + + forecast->location = loc; + + return forecast; +} + +/* + * Get forecast data for a given daytime for the day (today + day). + */ +xml_time * +make_forecast_data(xml_weather *data, int day, daytime dt) +{ + xml_time *forecast, *point, *interval; + struct tm tm_now, tm_start, tm_end; + time_t now, start_t, end_t; + + /* initialize times to the current day */ + time(&now); + tm_start = *localtime(&now); + tm_end = *localtime(&now); + + /* calculate daytime interval start and end times for the requested day */ + tm_start.tm_mday += day; + tm_end.tm_mday += day; + get_daytime_interval(&tm_start, &tm_end, dt); + start_t = mktime(&tm_start); + end_t = mktime(&tm_end); + + /* find point data */ + point = find_timeslice(data, tm_start, tm_start); + + /* next find interval data */ + interval = find_timeslice(data, tm_start, tm_end); + + /* create a new timeslice with combined point and interval data */ + forecast = make_combined_timeslice(point, interval); + return forecast; +} diff --git a/panel-plugin/weather-data.h b/panel-plugin/weather-data.h index 5e80763..798a4ec 100644 --- a/panel-plugin/weather-data.h +++ b/panel-plugin/weather-data.h @@ -41,10 +41,27 @@ typedef enum { METRIC } units; +typedef enum { + MORNING, + AFTERNOON, + EVENING, + NIGHT +} daytime; + const gchar * -get_data (xml_weather *data, datas type); +get_data (xml_time *timeslice, datas type); const gchar * -get_unit (xml_weather *data, units unit, datas type); +get_unit (xml_time *timeslice, units unit, datas type); +gboolean +is_night_time(); +time_t +time_calc(struct tm tm_time, gint year, gint mon, gint day, gint hour, gint min, gint sec); +time_t +time_calc_hour(struct tm tm_time, gint hours); +time_t +time_calc_day(struct tm tm_time, gint days); +xml_time * +make_forecast_data(xml_weather *data, int day, daytime dt); G_END_DECLS #endif diff --git a/panel-plugin/weather-icon.c b/panel-plugin/weather-icon.c index da9c5b0..6aaf75c 100644 --- a/panel-plugin/weather-icon.c +++ b/panel-plugin/weather-icon.c @@ -25,25 +25,50 @@ #include "weather-icon.h" - - #define DEFAULT_W_THEME "liquid" - +const gchar *night_symbols[] = { + "CLOUD", + "LIGHTCLOUD", + "LIGHTRAINSUN", + "LIGHTRAINTHUNDERSUN", + "PARTLYCLOUD", + "SNOWSUN", + "SUN", + NULL +}; GdkPixbuf * get_icon (const gchar *number, - gint size) + gint size, + gboolean night) { GdkPixbuf *image = NULL; - gchar *filename; - gchar *night; + gchar *filename, *night_suffix = ""; + gint number_len, night_symbol_len; + guint i; - if (number == NULL || strcmp (number, "-") == 0) + if (number == NULL || strlen(number) == 0) number = "99"; + else if (night) + { + number_len = strlen(number); + for (i = 0; night_symbols[i] != NULL; i++) + { + night_symbol_len = strlen(night_symbols[i]); + if (number_len != night_symbol_len) + continue; + + if (number[0] != night_symbols[i][0]) + continue; + + if (!g_ascii_strncasecmp (night_symbols[i], number, number_len)) + night_suffix = "-night"; + } + } - filename = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s" G_DIR_SEPARATOR_S "%s.png", - THEMESDIR, DEFAULT_W_THEME, number); + filename = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s" G_DIR_SEPARATOR_S "%s%s.png", + THEMESDIR, DEFAULT_W_THEME, number, night_suffix); image = gdk_pixbuf_new_from_file_at_scale (filename, size, size, TRUE, NULL); @@ -51,7 +76,7 @@ get_icon (const gchar *number, g_warning ("Unable to open image: %s", filename); if (number && strcmp(number, "99")) { g_free(filename); - return get_icon("99", size); + return get_icon("99", size, FALSE); } } g_free (filename); diff --git a/panel-plugin/weather-icon.h b/panel-plugin/weather-icon.h index abea3da..cee80ef 100644 --- a/panel-plugin/weather-icon.h +++ b/panel-plugin/weather-icon.h @@ -20,7 +20,7 @@ G_BEGIN_DECLS -GdkPixbuf *get_icon (const gchar * icon, gint size); +GdkPixbuf *get_icon (const gchar * icon, gint size, gboolean night); G_END_DECLS diff --git a/panel-plugin/weather-parsers.c b/panel-plugin/weather-parsers.c index fd16609..d97cb00 100644 --- a/panel-plugin/weather-parsers.c +++ b/panel-plugin/weather-parsers.c @@ -165,6 +165,9 @@ xml_time *get_current_timeslice(xml_weather *data, gboolean interval) int min_found = 7 * 24 * 3600; int i; + if (data == NULL) + return NULL; + for (i = 0; i < data->num_timeslices; i++) { if (interval != (data->timeslice[i]->start != data->timeslice[i]->end)) @@ -279,7 +282,7 @@ static void xml_location_free(xml_location *loc) g_slice_free (xml_location, loc); } -static void xml_time_free(xml_time *timeslice) +void xml_time_free(xml_time *timeslice) { xml_location_free(timeslice->location); g_slice_free (xml_time, timeslice); diff --git a/panel-plugin/weather-parsers.h b/panel-plugin/weather-parsers.h index b461f90..d432507 100644 --- a/panel-plugin/weather-parsers.h +++ b/panel-plugin/weather-parsers.h @@ -78,7 +78,6 @@ typedef struct } xml_weather; - xml_weather *parse_weather (xmlNode * cur_node); void parse_time (xmlNode * cur_node, xml_weather * data); @@ -88,6 +87,7 @@ 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_current_timeslice(xml_weather *data, gboolean interval); +void xml_time_free(xml_time *timeslice); void xml_weather_free (xml_weather * data); G_END_DECLS diff --git a/panel-plugin/weather-summary.c b/panel-plugin/weather-summary.c index b0a4aae..defddad 100644 --- a/panel-plugin/weather-summary.c +++ b/panel-plugin/weather-summary.c @@ -43,8 +43,8 @@ static gboolean lnk_clicked (GtkTextTag *tag, GObject *obj, g_free (value); #define APPEND_TEXT_ITEM(text, item) value = g_strdup_printf("\t%s%s%s %s\n",\ text, text?": ":"", \ - get_data(data->weatherdata, item),\ - get_unit(data->weatherdata, data->unit, item));\ + get_data(timeslice, item), \ + get_unit(timeslice, data->unit, item)); \ APPEND_TEXT_ITEM_REAL(value); #define APPEND_LINK_ITEM(prefix, text, url, lnk_tag) \ gtk_text_buffer_insert(GTK_TEXT_BUFFER(buffer), \ @@ -242,6 +242,7 @@ create_summary_tab (xfceweather_data *data) view = gtk_text_view_new (); gtk_text_view_set_editable (GTK_TEXT_VIEW (view), FALSE); gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (view), FALSE); + gtk_container_set_border_width (GTK_CONTAINER (view), BORDER); frame = gtk_frame_new (NULL); scrolled = gtk_scrolled_window_new (NULL, NULL); @@ -268,7 +269,10 @@ create_summary_tab (xfceweather_data *data) g_free (value); timeslice = get_current_timeslice(data->weatherdata, FALSE); - value = g_strdup_printf (_("Coordinates: lat %s lon %s\nData applies to: %s\n"), + APPEND_BTEXT(_("Coordinates and Time\n")); + value = g_strdup_printf (_("\tLatitude: %s \n" + "\tLongitude: %s\n\n" + "\tData applies to: %s"), data->lat, data->lon, ctime(×lice->start)); APPEND_TEXT_ITEM_REAL (value); @@ -278,211 +282,199 @@ create_summary_tab (xfceweather_data *data) /* Wind */ APPEND_BTEXT (_("\nWind\n")); - wind = translate_wind_speed (data->weatherdata, get_data (data->weatherdata, WIND_SPEED), data->unit); + wind = translate_wind_speed (timeslice, get_data (timeslice, WIND_SPEED), data->unit); value = g_strdup_printf ("\t%s: %s (%s on the Beaufort scale)\n", _("Speed"), wind, - get_data (data->weatherdata, WIND_BEAUFORT)); + get_data (timeslice, WIND_BEAUFORT)); g_free (wind); APPEND_TEXT_ITEM_REAL (value); - wind = translate_wind_direction (get_data (data->weatherdata, WIND_DIRECTION)); + wind = translate_wind_direction (get_data (timeslice, WIND_DIRECTION)); value = g_strdup_printf ("\t%s: %s (%s%s)\n", _("Direction"), - wind ? wind : get_data (data->weatherdata, WIND_DIRECTION), - get_data (data->weatherdata, WIND_DIRECTION_DEG), - get_unit (data->weatherdata, data->unit, WIND_DIRECTION_DEG)); + wind ? wind : get_data (timeslice, WIND_DIRECTION), + get_data (timeslice, WIND_DIRECTION_DEG), + get_unit (timeslice, data->unit, WIND_DIRECTION_DEG)); g_free (wind); APPEND_TEXT_ITEM_REAL (value); - /* Atmospheric pressure */ - APPEND_BTEXT (_("\nAtmospheric pressure\n")); + /* Atmosphere */ + APPEND_BTEXT (_("\nAtmosphere\n")); APPEND_TEXT_ITEM (_("Pressure"), PRESSURE); - - /* Other */ - APPEND_BTEXT (_("\nOther\n")); APPEND_TEXT_ITEM (_("Humidity"), HUMIDITY); + + /* Clouds */ + APPEND_BTEXT (_("\nClouds\n")); + APPEND_TEXT_ITEM (_("Fog"), FOG); APPEND_TEXT_ITEM (_("Low clouds"), CLOUDINESS_LOW); APPEND_TEXT_ITEM (_("Medium clouds"), CLOUDINESS_MED); APPEND_TEXT_ITEM (_("High clouds"), CLOUDINESS_HIGH); - APPEND_TEXT_ITEM (_("Fog"), FOG); APPEND_BTEXT (_("\nData from The Norwegian Meteorological Institute\n")); APPEND_LINK_ITEM ("\t", "Thanks to met.no", "http://met.no/", ltag1); g_signal_connect(G_OBJECT(view), "motion-notify-event", - G_CALLBACK(view_motion_notify), view); + G_CALLBACK(view_motion_notify), view); g_signal_connect(G_OBJECT(view), "leave-notify-event", - G_CALLBACK(view_leave_notify), view); + G_CALLBACK(view_leave_notify), view); if (hand_cursor == NULL) hand_cursor = gdk_cursor_new(GDK_HAND2); if (text_cursor == NULL) text_cursor = gdk_cursor_new(GDK_XTERM); - return frame; } +GtkWidget * +add_forecast_cell(GtkWidget *widget, GdkColor *color) { + GtkWidget *ebox; + ebox = gtk_event_box_new(); + if (color == NULL) + gtk_event_box_set_visible_window(GTK_EVENT_BOX(ebox), FALSE); + else { + gtk_event_box_set_visible_window(GTK_EVENT_BOX(ebox), TRUE); + gtk_widget_modify_bg(GTK_WIDGET(ebox), GTK_STATE_NORMAL, color); + } + gtk_widget_show(GTK_WIDGET(ebox)); + gtk_container_add(GTK_CONTAINER(ebox), GTK_WIDGET(widget)); + return ebox; +} + +GtkWidget * +add_forecast_header(gchar *text, gdouble angle, GdkColor *color) +{ + gchar *str; + GtkWidget *label, *box; + + box = gtk_vbox_new(FALSE, 0); + gtk_container_set_border_width(GTK_CONTAINER(box), 4); + gtk_widget_show(GTK_WIDGET(box)); + + label = gtk_label_new(NULL); + gtk_label_set_angle(label, angle); + gtk_widget_show(label); + str = g_strdup_printf("%s", text ? text : ""); + gtk_label_set_markup(GTK_LABEL(label), str); + g_free(str); + gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(label), + TRUE, FALSE, 2); + return add_forecast_cell(box, color); +} + static GtkWidget * -make_forecast (xml_weather *weatherdata, +make_forecast (xfceweather_data *data, units unit) { - GtkWidget *item_vbox, *temp_hbox, *icon_hbox, - *label, *icon_d, *icon_n, *box_d, *box_n; - GdkPixbuf *icon; - gchar *str, *day, *wind; - - 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); - - - 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)); - g_free (day); - - gtk_label_set_markup (GTK_LABEL (label), str); - g_free (str); - - gtk_box_pack_start (GTK_BOX (item_vbox), label, FALSE, FALSE, 0); - - 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); - - if (G_LIKELY (icon)) - g_object_unref (G_OBJECT (icon)); - - if (G_UNLIKELY (!tooltips)) - 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); - 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 (item_vbox), icon_hbox, FALSE, FALSE, 0); - - label = gtk_label_new (NULL); - gtk_misc_set_alignment (GTK_MISC (label), 0.5, 0.5); - gtk_label_set_markup (GTK_LABEL (label), _("Precipitation")); - gtk_box_pack_start (GTK_BOX (item_vbox), label, FALSE, FALSE, 0); - - 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)); - 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); - - label = gtk_label_new (NULL); - gtk_misc_set_alignment (GTK_MISC (label), 0.5, 0.5); - gtk_label_set_markup (GTK_LABEL (label), _("Temperature")); - gtk_box_pack_start (GTK_BOX (item_vbox), label, FALSE, FALSE, 0); - - 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 %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)); - 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); - - label = gtk_label_new (NULL); - gtk_misc_set_alignment (GTK_MISC (label), 0.5, 0.5); - gtk_label_set_markup (GTK_LABEL (label), _("Wind")); - gtk_box_pack_start (GTK_BOX (item_vbox), label, FALSE, FALSE, 0); - - temp_hbox = gtk_hbox_new (FALSE, 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_D)); - 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)); - g_free (wind); - - 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); - - /* speed */ - 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)); - 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; + GtkWidget *ebox, *table, *scrolled, *day_label; + GtkWidget *forecast_box, *box, *label, *image; + GdkPixbuf *icon; + GdkColor lightbg = {0, 0xeaea, 0xeaea, 0xeaea}; + GdkColor darkbg = {0, 0x6666, 0x6666, 0x6666}; + gint num_days = 5, i, weekday, daytime; + gchar *dayname, *value; + xml_time *fcdata; + time_t now_t = time(NULL), fcday_t; + struct tm tm_fcday; + + table = gtk_table_new(num_days + 1, 5, FALSE); + gtk_table_set_row_spacings(GTK_TABLE(table), 0); + gtk_table_set_col_spacings(GTK_TABLE(table), 0); + gtk_widget_show(GTK_WIDGET(table)); + + /* empty upper left corner */ + box = gtk_vbox_new(FALSE, 0); + gtk_widget_show(GTK_WIDGET(box)); + gtk_table_attach_defaults(GTK_TABLE(table), + add_forecast_cell(box, NULL), + 0, 1, 0, 1); + + /* daytime headers */ + gtk_table_attach_defaults(GTK_TABLE(table), + add_forecast_header(_("Morning"), 0.0, &darkbg), + 1, 2, 0, 1); + gtk_table_attach_defaults(GTK_TABLE(table), + add_forecast_header(_("Afternoon"), 0.0, &darkbg), + 2, 3, 0, 1); + gtk_table_attach_defaults(GTK_TABLE(table), + add_forecast_header(_("Evening"), 0.0, &darkbg), + 3, 4, 0, 1); + gtk_table_attach_defaults(GTK_TABLE(table), + add_forecast_header(_("Night"), 0.0, &darkbg), + 4, 5, 0, 1); + + for (i = 0; i < num_days; i++) { + /* Forecast day headers */ + tm_fcday = *localtime(&now_t); + fcday_t = time_calc_day(tm_fcday, i); + weekday = localtime(&fcday_t)->tm_wday; + if (i == 0) + dayname = _("Today"); + else if (i == 1) + dayname = _("Tomorrow"); + else + dayname = translate_day(weekday); + + if (i % 2) + box = add_forecast_header(dayname, 90.0, &darkbg); + else + box = add_forecast_header(dayname, 90.0, &darkbg); + + gtk_table_attach_defaults(GTK_TABLE(table), GTK_WIDGET(box), + 0, 1, i+1, i+2); + + /* Get forecast data for each daytime */ + for (daytime = MORNING; daytime <= NIGHT; daytime++) { + forecast_box = gtk_vbox_new(FALSE, 0); + if (i % 2) + box = add_forecast_cell(forecast_box, NULL); + else + box = add_forecast_cell(forecast_box, &lightbg); + + fcdata = make_forecast_data(data->weatherdata, i, daytime); + if (fcdata != NULL) { + if (fcdata->location != NULL) { + icon = get_icon(get_data(fcdata, SYMBOL), 48, (daytime == NIGHT)); + image = gtk_image_new_from_pixbuf(icon); + gtk_box_pack_start(GTK_BOX(forecast_box), GTK_WIDGET(image), + TRUE, TRUE, 0); + if (G_LIKELY (icon)) + g_object_unref (G_OBJECT (icon)); + + value = g_strdup_printf(" %s ", + translate_desc(get_data(fcdata, SYMBOL), + (daytime == NIGHT))); + label = gtk_label_new(NULL); + gtk_label_set_markup(GTK_LABEL(label), value); + gtk_widget_show(GTK_WIDGET(label)); + gtk_box_pack_start(GTK_BOX(forecast_box), GTK_WIDGET(label), + TRUE, TRUE, 0); + g_free(value); + + value = g_strdup_printf(" %s %s ", + get_data(fcdata, TEMPERATURE), + get_unit(fcdata, data->unit, TEMPERATURE)); + label = gtk_label_new(value); + gtk_widget_show(GTK_WIDGET(label)); + gtk_box_pack_start(GTK_BOX(forecast_box), GTK_WIDGET(label), + TRUE, TRUE, 0); + g_free(value); + + value = g_strdup_printf(" %s %s %s ", + translate_wind_direction(get_data(fcdata, WIND_DIRECTION)), + get_data(fcdata, WIND_SPEED), + get_unit(fcdata, data->unit, WIND_SPEED)); + label = gtk_label_new(value); + gtk_widget_show(GTK_WIDGET(label)); + gtk_box_pack_start(GTK_BOX(forecast_box), label, TRUE, TRUE, 0); + g_free(value); + } + xml_time_free(fcdata); + } + gtk_table_attach_defaults(GTK_TABLE(table), + GTK_WIDGET(box), + 1+daytime, 2+daytime, i+1, i+2); + } + } + return table; } @@ -490,34 +482,17 @@ make_forecast (xml_weather *weatherdata, static GtkWidget * create_forecast_tab (xfceweather_data *data) { - GtkWidget *widg = gtk_hbox_new (FALSE, 0); + GtkWidget *box; guint i; - 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 - return widg; + box = gtk_vbox_new (FALSE, 0); + gtk_widget_show(box); + gtk_container_set_border_width (GTK_CONTAINER (box), 6); + if (data->weatherdata) + gtk_box_pack_start (GTK_BOX (box), + make_forecast (data, data->unit), + FALSE, FALSE, 0); + return box; } static void @@ -534,9 +509,10 @@ summary_dialog_response (GtkWidget *dlg, GtkWidget * create_summary_window (xfceweather_data *data) { - GtkWidget *window, *notebook, *vbox; + GtkWidget *window, *notebook, *vbox, *hbox, *label; gchar *title; GdkPixbuf *icon; + xml_time *timeslice; window = xfce_titled_dialog_new_with_buttons (_("Weather Update"), NULL, @@ -545,36 +521,49 @@ create_summary_window (xfceweather_data *data) GTK_RESPONSE_HELP, GTK_STOCK_CLOSE, GTK_RESPONSE_ACCEPT, NULL); - - title = g_strdup_printf (_("Weather report for: %s"), data->location_name); - - xfce_titled_dialog_set_subtitle (XFCE_TITLED_DIALOG (window), title); - g_free (title); + if (data->location_name != NULL) { + title = g_strdup_printf (_("Weather report for: %s"), data->location_name); + xfce_titled_dialog_set_subtitle (XFCE_TITLED_DIALOG (window), title); + g_free (title); + } vbox = gtk_vbox_new (FALSE, 0); gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), vbox, TRUE, TRUE, 0); - icon = get_icon (get_data (data->weatherdata, SYMBOL), 48); - - if (!icon) - icon = get_icon ("99", 48); + timeslice = get_current_timeslice(data->weatherdata, TRUE); + icon = get_icon (get_data (timeslice, SYMBOL), 48, is_night_time()); gtk_window_set_icon (GTK_WINDOW (window), icon); if (G_LIKELY (icon)) g_object_unref (G_OBJECT (icon)); - notebook = gtk_notebook_new (); - gtk_container_set_border_width (GTK_CONTAINER (notebook), BORDER); - gtk_notebook_append_page (GTK_NOTEBOOK (notebook), - create_forecast_tab (data), - gtk_label_new (_("Forecast"))); - gtk_notebook_append_page (GTK_NOTEBOOK (notebook), - create_summary_tab (data), - gtk_label_new (_("Details"))); - - gtk_box_pack_start (GTK_BOX (vbox), notebook, TRUE, TRUE, 0); + if (data->location_name == NULL || data->weatherdata == NULL) { + hbox = gtk_hbox_new (FALSE, 0); + gtk_widget_show(hbox); + if (data->location_name == NULL) + label = gtk_label_new(_("Please set a location in the plugin settings.")); + else + label = gtk_label_new(_("Currently no data available.")); + gtk_widget_show(label); + gtk_box_pack_start (GTK_BOX (hbox), GTK_WIDGET(label), + TRUE, TRUE, 0); + + gtk_box_pack_start (GTK_BOX (vbox), GTK_WIDGET(hbox), + TRUE, TRUE, 0); + } else { + notebook = gtk_notebook_new (); + gtk_container_set_border_width (GTK_CONTAINER (notebook), BORDER); + gtk_notebook_append_page (GTK_NOTEBOOK (notebook), + create_forecast_tab (data), + gtk_label_new (_("Forecast"))); + gtk_notebook_append_page (GTK_NOTEBOOK (notebook), + create_summary_tab (data), + gtk_label_new (_("Details"))); + + gtk_box_pack_start (GTK_BOX (vbox), notebook, TRUE, TRUE, 0); + } g_signal_connect (G_OBJECT (window), "response", G_CALLBACK (summary_dialog_response), window); diff --git a/panel-plugin/weather-translate.c b/panel-plugin/weather-translate.c index 6ba9c2f..97a0ecf 100644 --- a/panel-plugin/weather-translate.c +++ b/panel-plugin/weather-translate.c @@ -276,42 +276,46 @@ typedef struct { gint id; gchar *symbol; gchar *desc; + gchar *night_desc; } SymbolToDesc; static const SymbolToDesc symbol_to_desc[] = { - { 1, "SUN", N_("Sunny") }, - { 2, "LIGHTCLOUD", N_("Lightly cloudy") }, - { 3, "PARTLYCLOUD", N_("Partly cloudy") }, - { 4, "CLOUD", N_("Cloudy") }, - { 5, "LIGHTRAINSUN", N_("Sunny, rain showers") }, - { 6, "LIGHTRAINTHUNDERSUN", - N_("Sunny, rain showers with thunder") }, - { 7, "SLEETSUN", N_("Sunny, Sleet") }, - { 8, "SNOWSUN", N_("Sunny, Snow") }, - { 9, "LIGHTRAIN", N_("Rain showers") }, - { 10,"RAIN", N_("Rain") }, - { 11,"RAINTHUNDER", N_("Rain with thunder") }, - { 12,"SLEET", N_("Sleet") }, - { 13,"SNOW", N_("Snow") }, - { 14,"SNOWTHUNDER", N_("Snow with thunder") }, - { 15,"FOG", N_("Fog") }, - { 16,"SUN", N_("Sunny") }, - { 17,"LIGHTCLOUD", N_("Lightly cloudy") }, - { 18,"LIGHTRAINSUN", N_("Sunny, rain showers") }, - { 19,"SNOWSUN", N_("Sunny, Snow") }, - { 20,"SLEETSUNTHUNDER", N_("Sunny, Sleet and thunder") }, - { 21,"SNOWSUNTHUNDER", N_("Sunny, Snow and thunder") }, - { 22,"LIGHTRAINTHUNDER",N_("Rain showers with thunder") }, - { 23,"SLEETTHUNDER", N_("Sleet and thunder") }, + { 1, "SUN", N_("Sunny"), N_("Clear") }, + { 2, "LIGHTCLOUD", N_("Lightly cloudy"), N_("Lightly cloudy") }, + { 3, "PARTLYCLOUD", N_("Partly cloudy"), N_("Partly cloudy") }, + { 4, "CLOUD", N_("Cloudy"), N_("Cloudy") }, + { 5, "LIGHTRAINSUN", N_("Sunny, rain showers"), N_("Clear, rain showers") }, + { 6, "LIGHTRAINTHUNDERSUN", N_("Sunny, rain showers with thunder"), + N_("Clear, rain showers with thunder") }, + { 7, "SLEETSUN", N_("Sunny, Sleet"), N_("Clear, Sleet") }, + { 8, "SNOWSUN", N_("Sunny, Snow"), N_("Clear, Snow") }, + { 9, "LIGHTRAIN", N_("Rain showers"), N_("Rain showers") }, + { 10,"RAIN", N_("Rain"), N_("Rain") }, + { 11,"RAINTHUNDER", N_("Rain with thunder"), N_("Rain with thunder") }, + { 12,"SLEET", N_("Sleet"), N_("Sleet") }, + { 13,"SNOW", N_("Snow"), N_("Snow") }, + { 14,"SNOWTHUNDER", N_("Snow with thunder"), N_("Snow with thunder") }, + { 15,"FOG", N_("Fog"), N_("Fog") }, + { 16,"SUN", N_("Sunny"), N_("Clear") }, + { 17,"LIGHTCLOUD", N_("Lightly cloudy"), N_("Lightly cloudy") }, + { 18,"LIGHTRAINSUN", N_("Sunny, rain showers"), N_("Clear, rain showers") }, + { 19,"SNOWSUN", N_("Sunny, Snow"), N_("Clear, Snow") }, + { 20,"SLEETSUNTHUNDER", N_("Sunny, Sleet and thunder"), N_("Clear, sleet and thunder") }, + { 21,"SNOWSUNTHUNDER", N_("Sunny, Snow and thunder"), N_("Clear, snow and thunder") }, + { 22,"LIGHTRAINTHUNDER", N_("Rain showers with thunder"), N_("Rain showers with thunder") }, + { 23,"SLEETTHUNDER", N_("Sleet and thunder"), N_("Sleet and thunder") }, }; #define NUM_SYMBOLS (sizeof(symbol_to_desc)/sizeof(symbol_to_desc[0])) const gchar * -translate_desc (const gchar *desc) +translate_desc (const gchar *desc, gboolean nighttime) { int i; for (i = 0; i < NUM_SYMBOLS; i++) { if (!strcmp(desc, symbol_to_desc[i].symbol)) - return _(symbol_to_desc[i].desc); + if (nighttime) + return _(symbol_to_desc[i].night_desc); + else + return _(symbol_to_desc[i].desc); } return desc; } @@ -390,40 +394,28 @@ translate_lsup (const gchar *lsup) gchar * -translate_day (const gchar *day) +translate_day (gint weekday) { - gint wday = -1; struct tm time_tm; - guint i; - const gchar *days[] = {"su", "mo", "tu", "we", "th", "fr", "sa", NULL}; gchar *day_loc; int len; - if (day == NULL || strlen (day) < 2) + if (weekday < 0 || weekday > 6) return NULL; - for (i = 0; days[i] != NULL; i++) - if (!g_ascii_strncasecmp (day, days[i], 2)) - wday = i; + time_tm.tm_wday = weekday; - if (wday == -1) - return NULL; - else - { - time_tm.tm_wday = wday; + day_loc = g_malloc (DAY_LOC_N); - day_loc = g_malloc (DAY_LOC_N); - - len = strftime (day_loc, DAY_LOC_N, "%A", &time_tm); - day_loc[len] = 0; - if (!g_utf8_validate(day_loc, -1, NULL)) { - gchar *utf8 = g_locale_to_utf8(day_loc, -1, NULL, NULL, NULL); - g_free(day_loc); - day_loc = utf8; - } + len = strftime (day_loc, DAY_LOC_N, "%A", &time_tm); + day_loc[len] = 0; + if (!g_utf8_validate(day_loc, -1, NULL)) { + gchar *utf8 = g_locale_to_utf8(day_loc, -1, NULL, NULL, NULL); + g_free(day_loc); + day_loc = utf8; + } - return day_loc; - } + return day_loc; } @@ -474,7 +466,7 @@ translate_wind_direction (const gchar *wdir) /* calm or a number */ gchar * -translate_wind_speed (xml_weather *data, +translate_wind_speed (xml_time *timeslice, const gchar *wspeed, units unit) { @@ -484,9 +476,10 @@ translate_wind_speed (xml_weather *data, wspeed_loc = g_strdup (_("calm")); else if (g_ascii_strcasecmp (wspeed, "N/A") == 0) wspeed_loc = g_strdup (_("N/A")); - else + else { wspeed_loc = - g_strdup_printf ("%s %s", wspeed, get_unit (data, unit, WIND_SPEED)); + g_strdup_printf ("%s %s", wspeed, get_unit (timeslice, unit, WIND_SPEED)); + } return wspeed_loc; } diff --git a/panel-plugin/weather-translate.h b/panel-plugin/weather-translate.h index 7ef4674..a8b1adf 100644 --- a/panel-plugin/weather-translate.h +++ b/panel-plugin/weather-translate.h @@ -23,7 +23,7 @@ G_BEGIN_DECLS -const gchar *translate_desc (const gchar *); +const gchar *translate_desc (const gchar *, gboolean); const gchar *translate_bard (const gchar *); @@ -32,11 +32,11 @@ const gchar *translate_risk (const gchar *); /* these return a newly alocted string, that should be freed */ gchar *translate_lsup (const gchar *); -gchar *translate_day (const gchar *); +gchar *translate_day (gint); gchar *translate_wind_direction (const gchar *); -gchar *translate_wind_speed (xml_weather *data, const gchar *, units); +gchar *translate_wind_speed (xml_time *, const gchar *, units); gchar *translate_time (const gchar *); diff --git a/panel-plugin/weather.c b/panel-plugin/weather.c index 7b75c4b..cedef93 100644 --- a/panel-plugin/weather.c +++ b/panel-plugin/weather.c @@ -102,6 +102,7 @@ make_label (xml_weather *weatherdata, { gchar *str, *value; + xml_time *timeslice; const gchar *rawvalue, *lbl, *txtsize; switch (opt) @@ -153,7 +154,10 @@ make_label (xml_weather *weatherdata, else txtsize = "xx-small"; - rawvalue = get_data (weatherdata, opt); + /* get data from current timeslice */ + timeslice = get_current_timeslice(weatherdata, + opt == PRECIPITATIONS || opt == SYMBOL); + rawvalue = get_data(timeslice, opt); switch (opt) { @@ -161,7 +165,7 @@ make_label (xml_weather *weatherdata, value = translate_wind_direction (rawvalue); break; case WIND_SPEED: - value = translate_wind_speed (weatherdata, rawvalue, unit); + value = translate_wind_speed (timeslice, rawvalue, unit); break; default: value = NULL; @@ -179,7 +183,7 @@ make_label (xml_weather *weatherdata, else { str = g_strdup_printf ("%s: %s %s", - txtsize, lbl, rawvalue, get_unit (weatherdata, unit, opt)); + txtsize, lbl, rawvalue, get_unit (timeslice, unit, opt)); } } else { if (value != NULL) @@ -191,7 +195,7 @@ make_label (xml_weather *weatherdata, else { str = g_strdup_printf ("%s %s", - txtsize, rawvalue, get_unit (weatherdata, unit, opt)); + txtsize, rawvalue, get_unit (timeslice, unit, opt)); } } return str; @@ -236,9 +240,9 @@ set_icon_error (xfceweather_data *data) gtk_widget_get_size_request (data->scrollbox, NULL, &height); if (data->orientation == GTK_ORIENTATION_VERTICAL) - icon = get_icon ("99", data->size - height - 2); + icon = get_icon ("99", data->size - height - 2, FALSE); else - icon = get_icon ("99", data->size); + icon = get_icon ("99", data->size, FALSE); gtk_image_set_from_pixbuf (GTK_IMAGE (data->iconimage), icon); @@ -256,11 +260,13 @@ set_icon_error (xfceweather_data *data) static void set_icon_current (xfceweather_data *data) { + xml_time *timeslice; guint i; GdkPixbuf *icon = NULL; datas opt; gchar *str; gint size, height; + gboolean nighttime; for (i = 0; i < data->labels->len; i++) { @@ -286,7 +292,10 @@ set_icon_current (xfceweather_data *data) size = data->size; } - icon = get_icon (get_data (data->weatherdata, SYMBOL), size); + /* get data from current timeslice */ + timeslice = get_current_timeslice(data->weatherdata, TRUE); + nighttime = is_night_time(); + icon = get_icon (get_data (timeslice, SYMBOL), size, nighttime); gtk_image_set_from_pixbuf (GTK_IMAGE (data->iconimage), icon); @@ -295,7 +304,7 @@ set_icon_current (xfceweather_data *data) #if !GTK_CHECK_VERSION(2,12,0) gtk_tooltips_set_tip (data->tooltips, data->tooltipbox, - translate_desc (get_data (data->weatherdata, SYMBOL)), + translate_desc (get_data (timeslice, SYMBOL), nighttime), NULL); #endif } @@ -757,7 +766,11 @@ static gboolean weather_get_tooltip_cb (GtkWidget *widget, { GdkPixbuf *icon; gchar *markup_text; + xml_time *timeslice; + gboolean nighttime; + timeslice = get_current_timeslice(data->weatherdata, TRUE); + nighttime = is_night_time(); if (data->weatherdata == NULL) { gtk_tooltip_set_text (tooltip, _("Cannot update weather data")); } else { @@ -765,12 +778,12 @@ static gboolean weather_get_tooltip_cb (GtkWidget *widget, "%s\n" "%s", data->location_name, - translate_desc (get_data (data->weatherdata, SYMBOL)) + translate_desc (get_data (timeslice, SYMBOL), nighttime) ); gtk_tooltip_set_markup (tooltip, markup_text); g_free(markup_text); } - icon = get_icon (get_data (data->weatherdata, SYMBOL), 32); + icon = get_icon (get_data (timeslice, SYMBOL), 32, nighttime); gtk_tooltip_set_icon (tooltip, icon); g_object_unref (G_OBJECT(icon)); @@ -795,7 +808,7 @@ xfceweather_create_control (XfcePanelPlugin *plugin) #endif data->scrollbox = gtk_scrollbox_new (); - icon = get_icon ("99", 16); + icon = get_icon ("99", 16, FALSE); data->iconimage = gtk_image_new_from_pixbuf (icon); if (G_LIKELY (icon)) @@ -843,7 +856,7 @@ xfceweather_create_control (XfcePanelPlugin *plugin) /* add refresh button to right click menu, for people who missed the middle mouse click feature */ mi = gtk_image_menu_item_new_with_mnemonic (_("_Forecast")); - icon = get_icon ("SUN", 16); + icon = get_icon ("SUN", 16, FALSE); gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(mi), gtk_image_new_from_pixbuf(icon)); if (G_LIKELY (icon))