diff --git a/evolution-data-server.spec b/evolution-data-server.spec index d17f1c5..4394a38 100644 --- a/evolution-data-server.spec +++ b/evolution-data-server.spec @@ -27,7 +27,7 @@ Name: evolution-data-server Version: 3.5.3 -Release: 1%{?dist} +Release: 2%{?dist} Group: System Environment/Libraries Summary: Backend data server for Evolution License: LGPLv2+ @@ -43,6 +43,9 @@ Obsoletes: evolution-webcal < 2.24.0 # RH bug #243296 Patch01: evolution-data-server-1.11.5-fix-64bit-acinclude.patch +# http://bugzilla.gnome.org/show_bug.cgi?id=672805 +Patch2: new-gweather-api.patch + ### Build Dependencies ### BuildRequires: bison @@ -123,6 +126,7 @@ This package contains developer documentation for %{name}. %setup -q %patch01 -p1 -b .fix-64bit-acinclude +%patch2 -p1 -b .new-gweather-api mkdir -p krb5-fakeprefix/include mkdir -p krb5-fakeprefix/lib @@ -367,6 +371,9 @@ glib-compile-schemas %{_datadir}/glib-2.0/schemas &>/dev/null || : %{_datadir}/gtk-doc/html/libedataserverui %changelog +* Wed Jun 27 2012 Matthias Clasen - 3.5.3-2 +- Build against libgweather 3.5 + * Mon Jun 25 2012 Matthew Barnes - 3.5.3-1 - Update to 3.5.3 - Add BR: gcr-devel >= 3.4 diff --git a/new-gweather-api.patch b/new-gweather-api.patch new file mode 100644 index 0000000..dd27d51 --- /dev/null +++ b/new-gweather-api.patch @@ -0,0 +1,1032 @@ +From 1b5f527757ea7e6aa1ccc822c91449b541521a40 Mon Sep 17 00:00:00 2001 +From: Giovanni Campagna +Date: Sat, 24 Mar 2012 01:06:02 +0100 +Subject: [PATCH] weather: update for newer GWeather + +GWeather 3.6 changed API to be properly namespaced and GObject based. +Also, WeatherLocation was removed and replaced with GWeatherLocation +in all public API (with additionally the possibility to retrieve one +particular GWeatherLocation by station code) +At the same time, remove a old and now useless abstration by folding +EWeatherSourceCCF into EWeatherSource. + +https://bugzilla.gnome.org/show_bug.cgi?id=672805 +--- + calendar/backends/weather/Makefile.am | 4 +- + calendar/backends/weather/e-cal-backend-weather.c | 112 +++-- + calendar/backends/weather/e-weather-source-ccf.c | 468 --------------------- + calendar/backends/weather/e-weather-source-ccf.h | 76 ---- + calendar/backends/weather/e-weather-source.c | 87 +++- + calendar/backends/weather/e-weather-source.h | 44 +- + configure.ac | 7 +- + 7 files changed, 133 insertions(+), 665 deletions(-) + delete mode 100644 calendar/backends/weather/e-weather-source-ccf.c + delete mode 100644 calendar/backends/weather/e-weather-source-ccf.h + +diff --git a/calendar/backends/weather/Makefile.am b/calendar/backends/weather/Makefile.am +index ed41cf2..25ee7a9 100644 +--- a/calendar/backends/weather/Makefile.am ++++ b/calendar/backends/weather/Makefile.am +@@ -25,9 +25,7 @@ libecalbackendweather_la_SOURCES = \ + e-source-weather.c \ + e-source-weather.h \ + e-weather-source.c \ +- e-weather-source.h \ +- e-weather-source-ccf.c \ +- e-weather-source-ccf.h ++ e-weather-source.h + + libecalbackendweather_la_LIBADD = \ + $(top_builddir)/calendar/libecal/libecal-1.2.la \ +diff --git a/calendar/backends/weather/e-cal-backend-weather.c b/calendar/backends/weather/e-cal-backend-weather.c +index 62357ae..632c5f2 100644 +--- a/calendar/backends/weather/e-cal-backend-weather.c ++++ b/calendar/backends/weather/e-cal-backend-weather.c +@@ -27,7 +27,7 @@ + #include "e-weather-source.h" + + #define GWEATHER_I_KNOW_THIS_IS_UNSTABLE +-#include ++#include + #undef GWEATHER_I_KNOW_THIS_IS_UNSTABLE + + #define WEATHER_UID_EXT "-weather" +@@ -43,7 +43,7 @@ G_DEFINE_TYPE (ECalBackendWeather, e_cal_backend_weather, E_TYPE_CAL_BACKEND_SYN + + static gboolean reload_cb (ECalBackendWeather *cbw); + static gboolean begin_retrieval_cb (ECalBackendWeather *cbw); +-static ECalComponent * create_weather (ECalBackendWeather *cbw, WeatherInfo *report, gboolean is_forecast); ++static ECalComponent * create_weather (ECalBackendWeather *cbw, GWeatherInfo *report, gboolean is_forecast); + static void e_cal_backend_weather_add_timezone (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *tzobj, GError **perror); + + /* Private part of the ECalBackendWeather structure */ +@@ -158,7 +158,7 @@ put_component_to_store (ECalBackendWeather *cb, + } + + static void +-finished_retrieval_cb (WeatherInfo *info, ++finished_retrieval_cb (GWeatherInfo *info, + ECalBackendWeather *cbw) + { + ECalBackendWeatherPrivate *priv; +@@ -197,13 +197,13 @@ finished_retrieval_cb (WeatherInfo *info, + e_cal_backend_notify_component_created (E_CAL_BACKEND (cbw), comp); + g_object_unref (comp); + +- forecasts = weather_info_get_forecast_list (info); ++ forecasts = gweather_info_get_forecast_list (info); + if (forecasts) { + GSList *f; + + /* skip the first one, it's for today, which has been added above */ + for (f = forecasts->next; f; f = f->next) { +- WeatherInfo *nfo = f->data; ++ GWeatherInfo *nfo = f->data; + + if (nfo) { + comp = create_weather (cbw, nfo, TRUE); +@@ -267,7 +267,7 @@ begin_retrieval_cb (ECalBackendWeather *cbw) + } + + static const gchar * +-getCategory (WeatherInfo *report) ++getCategory (GWeatherInfo *report) + { + struct { + const gchar *description; +@@ -286,7 +286,7 @@ getCategory (WeatherInfo *report) + }; + + gint i; +- const gchar *icon_name = weather_info_get_icon_name (report); ++ const gchar *icon_name = gweather_info_get_icon_name (report); + + if (!icon_name) + return NULL; +@@ -302,7 +302,7 @@ getCategory (WeatherInfo *report) + + static ECalComponent * + create_weather (ECalBackendWeather *cbw, +- WeatherInfo *report, ++ GWeatherInfo *report, + gboolean is_forecast) + { + ECalBackendWeatherPrivate *priv; +@@ -314,34 +314,19 @@ create_weather (ECalBackendWeather *cbw, + gchar *uid; + GSList *text_list = NULL; + ECalComponentText *description; +- ESource *source; +- const gchar *tmp; ++ gchar *tmp; + time_t update_time; + icaltimezone *update_zone = NULL; +- ESourceWeather *extension; +- const gchar *extension_name; +- const WeatherLocation *location; +- ESourceWeatherUnits units; ++ const GWeatherLocation *location; ++ const GWeatherTimezone *w_timezone; + + g_return_val_if_fail (E_IS_CAL_BACKEND_WEATHER (cbw), NULL); + +- if (!weather_info_get_value_update (report, &update_time)) ++ if (!gweather_info_get_value_update (report, &update_time)) + return NULL; + + priv = cbw->priv; + +- source = e_backend_get_source (E_BACKEND (cbw)); +- +- extension_name = E_SOURCE_EXTENSION_WEATHER_BACKEND; +- extension = e_source_get_extension (source, extension_name); +- units = e_source_weather_get_units (extension); +- +- /* Prefer metric if units is invalid. */ +- if (units == E_SOURCE_WEATHER_UNITS_IMPERIAL) +- weather_info_to_imperial (report); +- else +- weather_info_to_metric (report); +- + /* create the component and event object */ + ical_comp = icalcomponent_new (ICAL_VEVENT_COMPONENT); + cal_comp = e_cal_component_new (); +@@ -353,9 +338,9 @@ create_weather (ECalBackendWeather *cbw, + g_free (uid); + + /* use timezone of the location to determine date for which this is set */ +- location = weather_info_get_location (report); +- if (location && location->tz_hint && *location->tz_hint) +- update_zone = icaltimezone_get_builtin_timezone (location->tz_hint); ++ location = gweather_info_get_location (report); ++ if (location && (w_timezone = gweather_location_get_timezone ((GWeatherLocation *)location))) ++ update_zone = icaltimezone_get_builtin_timezone (gweather_timezone_get_tzid ((GWeatherTimezone*)w_timezone)); + + if (!update_zone) + update_zone = icaltimezone_get_utc_timezone (); +@@ -380,53 +365,56 @@ create_weather (ECalBackendWeather *cbw, + /* We have to add 1 day to DTEND, as it is not inclusive. */ + e_cal_component_set_dtend (cal_comp, &dt); + +- if (is_forecast) { ++ { + gdouble tmin = 0.0, tmax = 0.0; + +- if (weather_info_get_value_temp_min (report, TEMP_UNIT_DEFAULT, &tmin) && +- weather_info_get_value_temp_max (report, TEMP_UNIT_DEFAULT, &tmax) && ++ if (gweather_info_get_value_temp_min (report, GWEATHER_TEMP_UNIT_DEFAULT, &tmin) && ++ gweather_info_get_value_temp_max (report, GWEATHER_TEMP_UNIT_DEFAULT, &tmax) && + tmin != tmax) { +- /* because weather_info_get_temp* uses one internal buffer, thus finally +- * the last value is shown for both, which is obviously wrong */ +- GString *str = g_string_new (priv->city); ++ gchar *min, *max; + +- g_string_append (str, " : "); +- g_string_append (str, weather_info_get_temp_min (report)); +- g_string_append (str, "/"); +- g_string_append (str, weather_info_get_temp_max (report)); ++ min = gweather_info_get_temp_min (report); ++ max = gweather_info_get_temp_max (report); ++ comp_summary.value = g_strdup_printf ("%s : %s / %s", priv->city, min, max); + +- comp_summary.value = g_string_free (str, FALSE); ++ g_free (min); g_free (max); + } else { +- comp_summary.value = g_strdup_printf ("%s : %s", priv->city, weather_info_get_temp (report)); +- } +- } else { +- gdouble tmin = 0.0, tmax = 0.0; +- /* because weather_info_get_temp* uses one internal buffer, thus finally +- * the last value is shown for both, which is obviously wrong */ +- GString *str = g_string_new (priv->city); ++ gchar *temp; + +- g_string_append (str, " : "); +- if (weather_info_get_value_temp_min (report, TEMP_UNIT_DEFAULT, &tmin) && +- weather_info_get_value_temp_max (report, TEMP_UNIT_DEFAULT, &tmax) && +- tmin != tmax) { +- g_string_append (str, weather_info_get_temp_min (report)); +- g_string_append (str, "/"); +- g_string_append (str, weather_info_get_temp_max (report)); +- } else { +- g_string_append (str, weather_info_get_temp (report)); +- } ++ temp = gweather_info_get_temp (report); ++ comp_summary.value = g_strdup_printf ("%s : %s", priv->city, temp); + +- comp_summary.value = g_string_free (str, FALSE); ++ g_free (temp); ++ } + } + comp_summary.altrep = NULL; + e_cal_component_set_summary (cal_comp, &comp_summary); + g_free ((gchar *) comp_summary.value); + +- tmp = weather_info_get_forecast (report); +- comp_summary.value = weather_info_get_weather_summary (report); ++ tmp = gweather_info_get_forecast (report); ++ comp_summary.value = gweather_info_get_weather_summary (report); + + description = g_new0 (ECalComponentText, 1); +- description->value = g_strconcat (is_forecast ? "" : comp_summary.value, is_forecast ? "" : "\n", tmp ? _("Forecast") : "", tmp ? ":" : "", tmp && !is_forecast ? "\n" : "", tmp ? tmp : "", NULL); ++ { ++ GString *builder; ++ ++ builder = g_string_new (NULL); ++ ++ if (!is_forecast) { ++ g_string_append (builder, comp_summary.value); ++ g_string_append_c (builder, '\n'); ++ } ++ if (tmp) { ++ g_string_append (builder, _("Forecast")); ++ g_string_append_c (builder, ':'); ++ if (!is_forecast) ++ g_string_append_c (builder, '\n'); ++ g_string_append (builder, tmp); ++ } ++ ++ description->value = g_string_free (builder, FALSE); ++ g_free (tmp); ++ } + description->altrep = ""; + text_list = g_slist_append (text_list, description); + e_cal_component_set_description_list (cal_comp, text_list); +diff --git a/calendar/backends/weather/e-weather-source-ccf.c b/calendar/backends/weather/e-weather-source-ccf.c +deleted file mode 100644 +index 2bb76a5..0000000 +--- a/calendar/backends/weather/e-weather-source-ccf.c ++++ /dev/null +@@ -1,468 +0,0 @@ +-/* Evolution calendar - weather backend source class for parsing +- * CCF (coded cities forecast) formatted NWS reports +- * +- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) +- * +- * Authors: David Trowbridge +- * +- * This program is free software; you can redistribute it and/or +- * modify it under the terms of version 2 of the GNU Lesser General Public +- * License as published by the Free Software Foundation. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU Lesser General Public License for more details. +- * +- * You should have received a copy of the GNU Lesser General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +- */ +- +-#ifdef HAVE_CONFIG_H +-#include +-#endif +- +-#include +-#include +- +-#include +- +-#include "e-weather-source-ccf.h" +- +-#define GWEATHER_I_KNOW_THIS_IS_UNSTABLE +-#include +-#include +-#undef GWEATHER_I_KNOW_THIS_IS_UNSTABLE +- +-#ifdef G_OS_WIN32 +- +-#ifdef localtime_r +-#undef localtime_r +-#endif +- +-/* The localtime() in Microsoft's C library is MT-safe */ +-#define localtime_r(tp,tmp) (localtime(tp)?(*(tmp)=*localtime(tp),(tmp)):0) +- +-/* strtok() is also MT-safe (but not stateless, still uses only one +- * buffer pointer per thread, but for the use of strtok_r() here +- * that's enough). +- */ +-#define strtok_r(s,sep,lasts) (*(lasts)=strtok((s),(sep))) +-#endif +- +-G_DEFINE_TYPE (EWeatherSourceCCF, e_weather_source_ccf, E_TYPE_WEATHER_SOURCE) +- +-struct search_struct +-{ +- const gchar *code; +- const gchar *name; +- gboolean is_old; +- WeatherLocation *location; +-}; +- +-static gboolean +-find_location_func (GtkTreeModel *model, +- GtkTreePath *path, +- GtkTreeIter *node, +- gpointer data) +-{ +- WeatherLocation *wl = NULL; +- struct search_struct *search = (struct search_struct *) data; +- +- gtk_tree_model_get (model, node, GWEATHER_XML_COL_POINTER, &wl, -1); +- if (!wl || !wl->name || !wl->code || !search || search->location) +- return FALSE; +- +- if (((!strcmp (wl->code, search->code)) || (search->is_old && !strcmp (wl->code + 1, search->code))) && +- (!strcmp (wl->name, search->name))) { +- search->location = weather_location_clone (wl); +- return TRUE; +- } +- +- return FALSE; +-} +- +-static WeatherLocation * +-find_location (const gchar *code_name, +- gboolean is_old) +-{ +- GtkTreeModel *model; +- gchar **ids; +- struct search_struct search; +- +- search.location = NULL; +- +- ids = g_strsplit (code_name, "/", 2); +- +- if (!ids || !ids[0] || !ids[1]) +- goto done; +- +- model = gweather_xml_load_locations (); +- if (!model) +- goto done; +- +- search.code = ids[0]; +- search.name = ids[1]; +- search.is_old = is_old; +- search.location = NULL; +- +- gtk_tree_model_foreach (model, (GtkTreeModelForeachFunc) find_location_func, &search); +- +- gweather_xml_free_locations (model); +- g_strfreev (ids); +- +-done: +- return search.location; +-} +- +-#if 0 +-static GSList * +-tokenize (gchar *buffer) +-{ +- gchar *token; +- gchar *tokbuf; +- GSList *ret; +- +- token = strtok_r (buffer, " \n", &tokbuf); +- ret = g_slist_append (NULL, g_strdup (token)); +- while ((token = strtok_r (NULL, " \n/", &tokbuf))) +- ret = g_slist_append (ret, g_strdup (token)); +- return ret; +-} +- +-static void +-date2tm (gchar *date, +- struct tm *times) +-{ +- gchar tmp[3]; +- time_t curtime = time (NULL); +- tmp[2] = '\0'; +- +- localtime_r (&curtime, times); +- +- tmp[0] = date[0]; tmp[1] = date[1]; +- times->tm_mday = atoi (tmp); +- tmp[0] = date[2]; tmp[1] = date[3]; +- times->tm_hour = atoi (tmp); +- tmp[0] = date[4]; tmp[1] = date[5]; +- times->tm_min = atoi (tmp); +-} +- +-static WeatherConditions +-decodeConditions (gchar code) +-{ +- switch (code) { +- case 'A': return WEATHER_FAIR; +- case 'B': return WEATHER_PARTLY_CLOUDY; +- case 'C': return WEATHER_CLOUDY; +- case 'D': return WEATHER_DUST; +- case 'E': return WEATHER_MOSTLY_CLOUDY; +- case 'F': return WEATHER_FOGGY; +- case 'G': return WEATHER_VERY_HOT_OR_HOT_HUMID; +- case 'H': return WEATHER_HAZE; +- case 'I': return WEATHER_VERY_COLD_WIND_CHILL; +- case 'J': return WEATHER_SNOW_SHOWERS; +- case 'K': return WEATHER_SMOKE; +- case 'L': return WEATHER_DRIZZLE; +- case 'M': return WEATHER_SNOW_SHOWERS; +- case 'N': return WEATHER_WINDY; +- case 'O': return WEATHER_RAIN_OR_SNOW_MIXED; +- case 'P': return WEATHER_BLIZZARD; +- case 'Q': return WEATHER_BLOWING_SNOW; +- case 'R': return WEATHER_RAIN; +- case 'S': return WEATHER_SNOW; +- case 'T': return WEATHER_THUNDERSTORMS; +- case 'U': return WEATHER_SUNNY; +- case 'V': return WEATHER_CLEAR; +- case 'W': return WEATHER_RAIN_SHOWERS; +- case 'X': return WEATHER_SLEET; +- case 'Y': return WEATHER_FREEZING_RAIN; +- case 'Z': return WEATHER_FREEZING_DRIZZLE; +- /* hmm, this should never happen. */ +- default: return WEATHER_SUNNY; +- } +-} +- +-static gint +-decodePOP (gchar data) +-{ +- gint ret; +- +- switch (data) { +- case '-': +- ret = 5; +- break; +- case '+': +- ret = 95; +- break; +- case '/': +- ret = -1; /* missing data */ +- break; +- default: +- ret = (data - '0') * 10; +- } +- return ret; +-} +- +-static void +-decodeSnowfall (gchar *data, +- gfloat *low, +- gfloat *high) +-{ +- gchar num[3]; +- num[2] = '\0'; +- +- num[0] = data[0]; num[1] = data[1]; +- *low = atof (num) * 2.54f; +- num[0] = data[2]; num[1] = data[3]; +- *high = atof (num) * 2.54f; +-} +- +-static float +-ftoc (gchar *data) +-{ +- gint fahrenheit = atoi (data); +- if (fahrenheit >= 900) +- fahrenheit = (fahrenheit - 900) * -1; +- return ((gfloat)(fahrenheit - 32)) * 5.0f / 9.0f; +-} +- +-static void +-e_weather_source_ccf_do_parse (EWeatherSourceCCF *source, +- gchar *buffer) +-{ +- /* CCF gives us either 2 or 7 days of forecast data. IFPS WFO's +- * will produce 7 day forecasts, whereas pre-IFPS WFO's are only +- * mandated 2 (but may do 7). The morning forecast will give us either 2 +- * or 7 days worth of data. The evening forecast will give us the evening's +- * low temperature plus 2 or 7 days forecast. +- * +- * The CCF format is described in NWS directive 10-503, but it's usually +- * easier to look at a summary put up by one of the stations: +- * http://www.crh.noaa.gov/lmk/product_guide/products/forecast/ccf.htm +- */ +- WeatherForecast *forecasts = g_new0 (WeatherForecast, 7); +- GSList *tokens = tokenize (buffer); +- GSList *date; +- GSList *current = tokens; +- GList *fc = NULL; +- struct tm tms; +- gint i; +- time_t base; +- gint n; +- +- date = g_slist_nth (tokens, 3); +- date2tm (date->data, &tms); +- +- /* fast-forward to the particular station we're interested in */ +- current = g_slist_nth (tokens, 5); +- while (strcmp (current->data, source->substation)) +- current = g_slist_next (current); +- current = g_slist_next (current); +- /* pick up the first two conditions reports */ +- forecasts[0].conditions = decodeConditions (((gchar *)(current->data))[0]); +- forecasts[1].conditions = decodeConditions (((gchar *)(current->data))[1]); +- +- current = g_slist_next (current); +- if (tms.tm_hour < 12) { +- for (i = 0; i < 2; i++) { +- forecasts[i].high = ftoc (current->data); +- current = g_slist_next (current); +- forecasts[i].low = ftoc (current->data); +- current = g_slist_next (current); +- } +- forecasts[2].high = ftoc (current->data); +- current = g_slist_next (current); +- forecasts[0].pop = decodePOP (((gchar *)(current->data))[2]); +- forecasts[1].pop = decodePOP (((gchar *)(current->data))[4]); +- } else { +- for (i = 0; i < 2; i++) { +- current = g_slist_next (current); +- forecasts[i].high = ftoc (current->data); +- current = g_slist_next (current); +- forecasts[i].low = ftoc (current->data); +- } +- current = g_slist_next (current); +- forecasts[0].pop = decodePOP (((gchar *)(current->data))[1]); +- forecasts[1].pop = decodePOP (((gchar *)(current->data))[3]); +- } +- +- current = g_slist_next (current); +- if (strlen (current->data) == 4) { +- /* we've got the optional snowfall field */ +- if (tms.tm_hour < 12) { +- decodeSnowfall (current->data, &forecasts[0].low, &forecasts[0].high); +- current = g_slist_next (g_slist_next (current)); +- decodeSnowfall (current->data, &forecasts[1].low, &forecasts[1].high); +- } else { +- current = g_slist_next (current); +- decodeSnowfall (current->data, &forecasts[0].low, &forecasts[0].high); +- } +- current = g_slist_next (current); +- } +- +- /* set dates */ +- base = mktime (&tms); +- if (tms.tm_hour >= 12) +- base += 43200; +- for (i = 0; i < 7; i++) +- forecasts[i].date = base + 86400 * i; +- +- if (current == NULL || strlen (current->data) == 3) { +- /* We've got a pre-IFPS station. Realloc and return */ +- WeatherForecast *f = g_new0 (WeatherForecast, 2); +- memcpy (f, forecasts, sizeof (WeatherForecast) * 2); +- fc = g_list_append (fc, &f[0]); +- fc = g_list_append (fc, &f[1]); +- source->done (fc, source->finished_data); +- } +- +- /* Grab the conditions for the next 5 days */ +- forecasts[2].conditions = decodeConditions (((gchar *)(current->data))[0]); +- forecasts[3].conditions = decodeConditions (((gchar *)(current->data))[1]); +- forecasts[4].conditions = decodeConditions (((gchar *)(current->data))[2]); +- forecasts[5].conditions = decodeConditions (((gchar *)(current->data))[3]); +- forecasts[6].conditions = decodeConditions (((gchar *)(current->data))[4]); +- +- /* Temperature forecasts */ +- current = g_slist_next (current); +- if (tms.tm_hour < 12) { +- forecasts[2].low = ftoc (current->data); +- for (i = 3; i < 6; i++) { +- current = g_slist_next (current); +- forecasts[i].high = ftoc (current->data); +- current = g_slist_next (current); +- forecasts[i].low = ftoc (current->data); +- } +- current = g_slist_next (current); +- forecasts[6].high = ftoc (current->data); +- forecasts[6].low = forecasts[6].high; +- current = g_slist_next (current); +- forecasts[2].pop = decodePOP (((gchar *)(current->data))[1]); +- forecasts[3].pop = decodePOP (((gchar *)(current->data))[3]); +- forecasts[4].pop = decodePOP (((gchar *)(current->data))[5]); +- forecasts[5].pop = decodePOP (((gchar *)(current->data))[7]); +- forecasts[6].pop = decodePOP (((gchar *)(current->data))[9]); +- n = 7; +- } else { +- for (i = 2; i < 6; i++) { +- forecasts[i].high = ftoc (current->data); +- current = g_slist_next (current); +- forecasts[i].low = ftoc (current->data); +- current = g_slist_next (current); +- } +- n = 6; +- /* hack for people who put out bad data, like Pueblo, CO. Yes, PUB, that means you */ +- if (strlen (current->data) == 3) +- current = g_slist_next (current); +- forecasts[1].pop = decodePOP (((gchar *)(current->data))[0]); +- forecasts[2].pop = decodePOP (((gchar *)(current->data))[2]); +- forecasts[3].pop = decodePOP (((gchar *)(current->data))[4]); +- forecasts[4].pop = decodePOP (((gchar *)(current->data))[6]); +- forecasts[5].pop = decodePOP (((gchar *)(current->data))[8]); +- } +- +- for (i = 0; i < n; i++) { +- fc = g_list_append (fc, &forecasts[i]); +- } +- source->done (fc, source->finished_data); +- +- g_free (forecasts); +- g_list_free (fc); +-} +-#endif +- +-static void +-parse_done (WeatherInfo *info, +- gpointer data) +-{ +- EWeatherSourceCCF *ccfsource = (EWeatherSourceCCF *) data; +- +- if (!ccfsource) +- return; +- +- if (!info || !weather_info_is_valid (info)) { +- ccfsource->done (NULL, ccfsource->finished_data); +- return; +- } +- +- ccfsource->done (info, ccfsource->finished_data); +-} +- +-static void +-e_weather_source_ccf_parse (EWeatherSource *source, +- EWeatherSourceFinished done, +- gpointer data) +-{ +- EWeatherSourceCCF *ccfsource = (EWeatherSourceCCF *) source; +- WeatherPrefs prefs; +- +- ccfsource->finished_data = data; +- ccfsource->done = done; +- +- prefs.type = FORECAST_LIST; +- prefs.radar = FALSE; +- prefs.radar_custom_url = NULL; +- prefs.temperature_unit = TEMP_UNIT_CENTIGRADE; +- prefs.speed_unit = SPEED_UNIT_MS; +- prefs.pressure_unit = PRESSURE_UNIT_HPA; +- prefs.distance_unit = DISTANCE_UNIT_METERS; +- +- if (ccfsource->location && !ccfsource->info) { +- ccfsource->info = weather_info_new (ccfsource->location, &prefs, parse_done, source); +- weather_location_free (ccfsource->location); +- ccfsource->location = NULL; +- } else { +- ccfsource->info = weather_info_update (ccfsource->info, &prefs, parse_done, source); +- } +-} +- +-static void +-e_weather_source_ccf_class_init (EWeatherSourceCCFClass *class) +-{ +- EWeatherSourceClass *source_class; +- +- source_class = E_WEATHER_SOURCE_CLASS (class); +- source_class->parse = e_weather_source_ccf_parse; +-} +- +-static void +-e_weather_source_ccf_init (EWeatherSourceCCF *source) +-{ +- source->location = NULL; +- source->info = NULL; +-} +- +-EWeatherSource * +-e_weather_source_ccf_new (const gchar *location) +-{ +- /* Old location is formatted as ccf/AAA[/BBB] - AAA is the 3-letter +- * station code for identifying the providing station (subdirectory +- * within the crh data repository). BBB is an optional additional +- * station ID for the station within the CCF file. If not present, +- * BBB is assumed to be the same station as AAA. But the new +- * location is code/name, where code is 4-letter code. So if we +- * got the old format, then migrate to the new one, if possible. +- */ +- +- WeatherLocation *wl; +- EWeatherSourceCCF *source; +- +- if (location == NULL) +- return NULL; +- +- if (strncmp (location, "ccf/", 4) == 0) +- wl = find_location (location + 4, TRUE); +- else +- wl = find_location (location, FALSE); +- +- if (wl == NULL) +- return NULL; +- +- source = g_object_new (E_TYPE_WEATHER_SOURCE_CCF, NULL); +- source->location = wl; +- source->info = NULL; +- +- return E_WEATHER_SOURCE (source); +-} +diff --git a/calendar/backends/weather/e-weather-source-ccf.h b/calendar/backends/weather/e-weather-source-ccf.h +deleted file mode 100644 +index e0ae161..0000000 +--- a/calendar/backends/weather/e-weather-source-ccf.h ++++ /dev/null +@@ -1,76 +0,0 @@ +-/* Evolution calendar - weather backend source class for parsing +- * CCF (coded cities forecast) formatted NWS reports +- * +- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) +- * +- * Authors: David Trowbridge +- * +- * This program is free software; you can redistribute it and/or +- * modify it under the terms of version 2 of the GNU Lesser General Public +- * License as published by the Free Software Foundation. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU Lesser General Public License for more details. +- * +- * You should have received a copy of the GNU Lesser General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +- */ +- +-#ifndef E_WEATHER_SOURCE_CCF_H +-#define E_WEATHER_SOURCE_CCF_H +- +-#include +-#include +-#include "e-weather-source.h" +- +-#define GWEATHER_I_KNOW_THIS_IS_UNSTABLE +-#include +-#undef GWEATHER_I_KNOW_THIS_IS_UNSTABLE +- +-/* Standard GObject macros */ +-#define E_TYPE_WEATHER_SOURCE_CCF \ +- (e_weather_source_ccf_get_type ()) +-#define E_WEATHER_SOURCE_CCF(obj) \ +- (G_TYPE_CHECK_INSTANCE_CAST \ +- ((obj), E_TYPE_WEATHER_SOURCE_CCF, EWeatherSourceCCF)) +-#define E_WEATHER_SOURCE_CCF_CLASS(cls) \ +- (G_TYPE_CHECK_CLASS_CAST \ +- ((cls), E_TYPE_WEATHER_SOURCE_CCF, EWeatherSourceCCF)) +-#define E_IS_WEATHER_SOURCE_CCF(obj) \ +- (G_TYPE_CHECK_INSTANCE_TYPE \ +- ((obj), E_TYPE_WEATHER_SOURCE_CCF)) +-#define E_IS_WEATHER_SOURCE_CCF_CLASS(cls) \ +- (G_TYPE_CHECK_CLASS_TYPE \ +- ((cls), E_TYPE_WEATHER_SOURCE_CCF)) +-#define E_WEATHER_SOURCE_CCF_GET_CLASS(obj) \ +- (G_TYPE_INSTANCE_GET_CLASS \ +- ((obj), E_TYPE_WEATHER_SOURCE_CCF, EWeatherSourceCCF)) +- +-G_BEGIN_DECLS +- +-typedef struct _EWeatherSourceCCF EWeatherSourceCCF; +-typedef struct _EWeatherSourceCCFClass EWeatherSourceCCFClass; +- +-struct _EWeatherSourceCCF { +- EWeatherSource parent; +- +- WeatherLocation *location; +- WeatherInfo *info; +- +- EWeatherSourceFinished done; +- gpointer finished_data; +-}; +- +-struct _EWeatherSourceCCFClass { +- EWeatherSourceClass parent_class; +-}; +- +-GType e_weather_source_ccf_get_type (void); +-EWeatherSource *e_weather_source_ccf_new (const gchar *location); +- +-G_END_DECLS +- +-#endif /* E_WEATHER_SOURCE_CCF_H */ +diff --git a/calendar/backends/weather/e-weather-source.c b/calendar/backends/weather/e-weather-source.c +index 3dd3431..3cdbe3a 100644 +--- a/calendar/backends/weather/e-weather-source.c ++++ b/calendar/backends/weather/e-weather-source.c +@@ -19,43 +19,102 @@ + */ + + #include "e-weather-source.h" +-#include "e-weather-source-ccf.h" + + #include + + G_DEFINE_TYPE (EWeatherSource, e_weather_source, G_TYPE_OBJECT) + ++static void ++parse_done (GWeatherInfo *info, ++ gpointer data) ++{ ++ EWeatherSource *source = (EWeatherSource *) data; ++ ++ if (!source) ++ return; ++ ++ if (!info || !gweather_info_is_valid (info)) { ++ source->done (NULL, source->finished_data); ++ return; ++ } ++ ++ source->done (info, source->finished_data); ++} ++ + void +-e_weather_source_parse (EWeatherSource *source, +- EWeatherSourceFinished done, +- gpointer data) ++e_weather_source_parse (EWeatherSource *source, ++ EWeatherSourceFinished done, ++ gpointer data) + { +- EWeatherSourceClass *class; ++ source->finished_data = data; ++ source->done = done; + +- g_return_if_fail (source != NULL); ++ if (!source->info) { ++ source->info = gweather_info_new (source->location, GWEATHER_FORECAST_LIST); ++ g_signal_connect (source->info, "updated", G_CALLBACK (parse_done), source); ++ } else { ++ gweather_info_update (source->info); ++ } ++} + +- class = E_WEATHER_SOURCE_GET_CLASS (source); +- g_return_if_fail (class->parse != NULL); ++static void ++e_weather_source_finalize (GObject *object) ++{ ++ EWeatherSource *self = (EWeatherSource*) object; ++ ++ if (self->location) ++ gweather_location_unref (self->location); ++ g_clear_object (&self->info); + +- class->parse (source, done, data); ++ G_OBJECT_CLASS (e_weather_source_parent_class)->finalize (object); + } + + static void +-e_weather_source_class_init (EWeatherSourceClass *class) ++e_weather_source_class_init (EWeatherSourceClass *klass) + { +- /* nothing to do here */ ++ GObjectClass *gobject_class; ++ ++ gobject_class = G_OBJECT_CLASS (klass); ++ gobject_class->finalize = e_weather_source_finalize; + } + + static void + e_weather_source_init (EWeatherSource *source) + { +- /* nothing to do here */ + } + + EWeatherSource * + e_weather_source_new (const gchar *location) + { +- g_return_val_if_fail (location != NULL, NULL); ++ GWeatherLocation *world, *glocation; ++ EWeatherSource *source; ++ ++ /* Old location is formatted as ccf/AAA[/BBB] - AAA is the 3-letter station ++ * code for identifying the providing station (subdirectory within the crh data ++ * repository). BBB is an optional additional station ID for the station within ++ * the CCF file. If not present, BBB is assumed to be the same station as AAA. ++ * But the new location is code/name, where code is 4-letter code. ++ * So if got the old format, then migrate to the new one, if possible. ++ */ ++ ++ if (!location) ++ return NULL; ++ ++ world = gweather_location_new_world (FALSE); ++ if (strncmp (location, "ccf/", 4) == 0) ++ glocation = gweather_location_find_by_station_code (world, location + 4); ++ else ++ glocation = gweather_location_find_by_station_code (world, location); ++ if (glocation) ++ gweather_location_ref (glocation); ++ gweather_location_unref (world); ++ ++ if (!location) ++ return NULL; ++ ++ source = E_WEATHER_SOURCE (g_object_new (e_weather_source_get_type (), NULL)); ++ source->location = glocation; ++ source->info = NULL; + +- return e_weather_source_ccf_new (location); ++ return source; + } +diff --git a/calendar/backends/weather/e-weather-source.h b/calendar/backends/weather/e-weather-source.h +index e36793e..793c2fa 100644 +--- a/calendar/backends/weather/e-weather-source.h ++++ b/calendar/backends/weather/e-weather-source.h +@@ -25,7 +25,7 @@ + #include + + #define GWEATHER_I_KNOW_THIS_IS_UNSTABLE +-#include ++#include + #undef GWEATHER_I_KNOW_THIS_IS_UNSTABLE + + /* Standard GObject macros */ +@@ -49,35 +49,7 @@ + + G_BEGIN_DECLS + +-typedef enum { +- WEATHER_FAIR, +- WEATHER_SNOW_SHOWERS, +- WEATHER_SNOW, +- WEATHER_PARTLY_CLOUDY, +- WEATHER_SMOKE, +- WEATHER_THUNDERSTORMS, +- WEATHER_CLOUDY, +- WEATHER_DRIZZLE, +- WEATHER_SUNNY, +- WEATHER_DUST, +- WEATHER_CLEAR, +- WEATHER_MOSTLY_CLOUDY, +- WEATHER_WINDY, +- WEATHER_RAIN_SHOWERS, +- WEATHER_FOGGY, +- WEATHER_RAIN_OR_SNOW_MIXED, +- WEATHER_SLEET, +- WEATHER_VERY_HOT_OR_HOT_HUMID, +- WEATHER_BLIZZARD, +- WEATHER_FREEZING_RAIN, +- WEATHER_HAZE, +- WEATHER_BLOWING_SNOW, +- WEATHER_FREEZING_DRIZZLE, +- WEATHER_VERY_COLD_WIND_CHILL, +- WEATHER_RAIN, +-} WeatherConditions; +- +-typedef void (*EWeatherSourceFinished)(WeatherInfo *result, gpointer data); ++typedef void (*EWeatherSourceFinished)(GWeatherInfo *result, gpointer data); + + typedef struct _EWeatherSource EWeatherSource; + typedef struct _EWeatherSourceClass EWeatherSourceClass; +@@ -87,16 +59,16 @@ typedef struct _EWeatherSourceClass EWeatherSourceClass; + * to know how to do is parse the specific format. */ + struct _EWeatherSource { + GObject parent; ++ ++ GWeatherLocation *location; ++ GWeatherInfo *info; ++ ++ EWeatherSourceFinished done; ++ gpointer finished_data; + }; + + struct _EWeatherSourceClass { + GObjectClass parent_class; +- +- /* Returns a list of WeatherForecast objects containing the +- * data for the forecast. */ +- void (*parse) (EWeatherSource *source, +- EWeatherSourceFinished done, +- gpointer data); + }; + + GType e_weather_source_get_type (void); +diff --git a/configure.ac b/configure.ac +index 6afe83d..41a7f7a 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -46,7 +46,7 @@ m4_define([libical_minimum_version], [0.43]) + + dnl Optional Packages + m4_define([goa_minimum_version], [3.2]) +-m4_define([gweather_minimum_version], [2.90.0]) ++m4_define([gweather_minimum_version], [3.5.0]) + + AC_SUBST([BASE_VERSION],[base_version]) + AC_SUBST([API_VERSION],[api_version]) +@@ -1103,11 +1103,6 @@ AC_MSG_RESULT([$use_gweather]) + if test "x$use_gweather" = "xyes"; then + PKG_CHECK_MODULES([LIBGWEATHER], [gweather-3.0 >= gweather_minimum_version],[], + [AC_MSG_ERROR([The weather calendar backend requires GWeather >= gweather_minimum_version. Alternatively, you may specify --disable-weather as a configure option to avoid building the backend.])]) +- +- dnl gweather-3.5 introduces API changes we do not yet support. +- if `$PKG_CONFIG --atleast-version=3.5 gweather-3.0`; then +- AC_MSG_ERROR([gweather-3.5 is not yet supported. Install gweather-3.4 or specify --disable-weather as a configure option to avoid building the backend.]) +- fi + fi + AM_CONDITIONAL(ENABLE_WEATHER, [test $use_gweather = yes]) + +-- +1.7.10.2 \ No newline at end of file