1032 lines
33 KiB
Diff
1032 lines
33 KiB
Diff
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
|