From 1b5f527757ea7e6aa1ccc822c91449b541521a40 Mon Sep 17 00:00:00 2001
From: Giovanni Campagna <gcampagna@src.gnome.org>
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 <libgweather/weather.h>
+#include <libgweather/gweather-weather.h>
 #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 <trowbrds@cs.colorado.edu>
- *
- * 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 <config.h>
-#endif
-
-#include <string.h>
-#include <stdlib.h>
-
-#include <glib/gi18n-lib.h>
-
-#include "e-weather-source-ccf.h"
-
-#define GWEATHER_I_KNOW_THIS_IS_UNSTABLE
-#include <libgweather/weather.h>
-#include <libgweather/gweather-xml.h>
-#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 <trowbrds@cs.colorado.edu>
- *
- * 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 <libsoup/soup-session-async.h>
-#include <libsoup/soup-uri.h>
-#include "e-weather-source.h"
-
-#define GWEATHER_I_KNOW_THIS_IS_UNSTABLE
-#include <libgweather/weather.h>
-#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 <string.h>
 
 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 <time.h>
 
 #define GWEATHER_I_KNOW_THIS_IS_UNSTABLE
-#include <libgweather/weather.h>
+#include <libgweather/gweather-weather.h>
 #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
