Add an ESource extension for the weather backend.
authorMatthew Barnes <mbarnes@redhat.com>
Tue, 23 Nov 2010 22:39:27 +0000 (17:39 -0500)
committerMatthew Barnes <mbarnes@redhat.com>
Sun, 3 Jun 2012 23:51:09 +0000 (19:51 -0400)
calendar/backends/weather/Makefile.am
calendar/backends/weather/e-cal-backend-weather-factory.c
calendar/backends/weather/e-cal-backend-weather.c
calendar/backends/weather/e-source-weather.c [new file with mode: 0644]
calendar/backends/weather/e-source-weather.h [new file with mode: 0644]
calendar/backends/weather/e-weather-source-ccf.c
calendar/backends/weather/e-weather-source-ccf.h
calendar/backends/weather/e-weather-source.c
calendar/backends/weather/e-weather-source.h

index 5b0afa4..8f74137 100644 (file)
@@ -21,6 +21,8 @@ libecalbackendweather_la_SOURCES =    \
        e-cal-backend-weather-factory.c \
        e-cal-backend-weather.c         \
        e-cal-backend-weather.h         \
+       e-source-weather.c              \
+       e-source-weather.h              \
        e-weather-source.c              \
        e-weather-source.h              \
        e-weather-source-ccf.c          \
index f68113d..fd81ca9 100644 (file)
@@ -22,6 +22,7 @@
 
 #include <libedata-cal/e-cal-backend-factory.h>
 #include "e-cal-backend-weather.h"
+#include "e-source-weather.h"
 
 #define FACTORY_NAME "weather"
 
@@ -61,6 +62,7 @@ e_cal_backend_weather_events_factory_init (ECalBackendFactory *factory)
 G_MODULE_EXPORT void
 e_module_load (GTypeModule *type_module)
 {
+       e_source_weather_type_register (type_module);
        e_cal_backend_weather_events_factory_register_type (type_module);
 }
 
index bcd4329..aac8328 100644 (file)
 #include <libedata-cal/e-cal-backend-file-store.h>
 #include <libedata-cal/e-cal-backend-util.h>
 #include <libedata-cal/e-cal-backend-sexp.h>
+#include <libedataserver/e-source-refresh.h>
 #include <glib/gi18n-lib.h>
 #include <string.h>
 #include "e-cal-backend-weather.h"
+#include "e-source-weather.h"
 #include "e-weather-source.h"
 
 #define GWEATHER_I_KNOW_THIS_IS_UNSTABLE
@@ -60,7 +62,6 @@ struct _ECalBackendWeatherPrivate {
 
        /* Reload */
        guint reload_timeout_id;
-       guint source_changed_id;
        guint is_loading : 1;
 
        /* Flags */
@@ -92,21 +93,13 @@ reload_cb (ECalBackendWeather *cbw)
 }
 
 static void
-source_changed (ESource *source,
-                ECalBackendWeather *cbw)
-{
-       /* FIXME
-        * We should force a reload of the data when this gets called. Unfortunately,
-        * this signal isn't getting through from evolution to the backend
-        */
-}
-
-static void
 maybe_start_reload_timeout (ECalBackendWeather *cbw)
 {
        ECalBackendWeatherPrivate *priv;
        ESource *source;
-       const gchar *refresh_str;
+       ESourceRefresh *extension;
+       const gchar *extension_name;
+       guint interval_in_minutes = 0;
 
        priv = cbw->priv;
 
@@ -114,27 +107,25 @@ maybe_start_reload_timeout (ECalBackendWeather *cbw)
                return;
 
        source = e_backend_get_source (E_BACKEND (cbw));
-       if (!source) {
-               g_warning ("Could not get source for ECalBackendWeather reload.");
-               return;
-       }
 
-       if (priv->source_changed_id == 0)
-               priv->source_changed_id = g_signal_connect (G_OBJECT (source),
-                                                           "changed",
-                                                           G_CALLBACK (source_changed),
-                                                           cbw);
-
-       refresh_str = e_source_get_property (source, "refresh");
+       extension_name = E_SOURCE_EXTENSION_REFRESH;
+       extension = e_source_get_extension (source, extension_name);
 
        /* By default, reload every 4 hours. At least for CCF, the forecasts
         * only come out twice a day, and chances are while the NWS and similar
         * organizations have some serious bandwidth, they would appreciate it
         * if we didn't hammer their servers. */
-       priv->reload_timeout_id = g_timeout_add (
-               (refresh_str ? atoi (refresh_str) : 240) * 60000,
-               (GSourceFunc) reload_cb, cbw);
+       if (e_source_refresh_get_enabled (extension)) {
+               interval_in_minutes =
+                       e_source_refresh_get_interval_minutes (extension);
+               if (interval_in_minutes == 0)
+                       interval_in_minutes = 240;
+       }
 
+       if (interval_in_minutes > 0)
+               priv->reload_timeout_id = g_timeout_add_seconds (
+                       interval_in_minutes * 60,
+                       (GSourceFunc) reload_cb, cbw);
 }
 
 /* TODO Do not replicate this in every backend */
@@ -237,20 +228,29 @@ static gboolean
 begin_retrieval_cb (ECalBackendWeather *cbw)
 {
        ECalBackendWeatherPrivate *priv = cbw->priv;
+       ESource *e_source;
        GSource *source;
 
+       /* XXX Too much overloading of the word 'source' here! */
+
        if (!e_backend_get_online (E_BACKEND (cbw)))
                return TRUE;
 
        maybe_start_reload_timeout (cbw);
 
+       e_source = e_backend_get_source (E_BACKEND (cbw));
+
        if (priv->source == NULL) {
-               ESource *e_source;
-               const gchar *uri;
+               ESourceWeather *extension;
+               const gchar *extension_name;
+               gchar *location;
+
+               extension_name = E_SOURCE_EXTENSION_WEATHER_BACKEND;
+               extension = e_source_get_extension (e_source, extension_name);
 
-               e_source = e_backend_get_source (E_BACKEND (cbw));
-               uri = e_source_get_uri (e_source);
-               priv->source = e_weather_source_new (uri);
+               location = e_source_weather_dup_location (extension);
+               priv->source = e_weather_source_new (location);
+               g_free (location);
        }
 
        source = g_main_current_source ();
@@ -319,11 +319,13 @@ create_weather (ECalBackendWeather *cbw,
        GSList                    *text_list = NULL;
        ECalComponentText         *description;
        ESource                   *source;
-       gboolean                   metric;
-       const gchar                *tmp;
+       const gchar               *tmp;
        time_t                     update_time;
        icaltimezone              *update_zone = NULL;
+       ESourceWeather            *extension;
+       const gchar               *extension_name;
        const WeatherLocation     *location;
+       ESourceWeatherUnits        units;
 
        g_return_val_if_fail (E_IS_CAL_BACKEND_WEATHER (cbw), NULL);
 
@@ -333,21 +335,16 @@ create_weather (ECalBackendWeather *cbw,
        priv = cbw->priv;
 
        source = e_backend_get_source (E_BACKEND (cbw));
-       tmp = e_source_get_property (source, "units");
-       if (tmp == NULL) {
-               tmp = e_source_get_property (source, "temperature");
-               if (tmp == NULL)
-                       metric = FALSE;
-               else
-                       metric = (strcmp (tmp, "fahrenheit") != 0);
-       } else {
-               metric = (strcmp (tmp, "metric") == 0);
-       }
 
-       if (metric)
-               weather_info_to_metric (report);
-       else
+       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);
@@ -496,21 +493,26 @@ e_cal_backend_weather_open (ECalBackendSync *backend,
        ECalBackendWeather *cbw;
        ECalBackendWeatherPrivate *priv;
        ESource *source;
+       ESourceWeather *extension;
+       const gchar *extension_name;
        const gchar *cache_dir;
-       const gchar *uri;
+       gchar *location;
        gboolean online;
 
        cbw = E_CAL_BACKEND_WEATHER (backend);
        priv = cbw->priv;
 
        source = e_backend_get_source (E_BACKEND (backend));
-       uri = e_source_get_uri (source);
-
        cache_dir = e_cal_backend_get_cache_dir (E_CAL_BACKEND (backend));
 
-       if (priv->city)
-               g_free (priv->city);
-       priv->city = g_strdup (strrchr (uri, '/') + 1);
+       extension_name = E_SOURCE_EXTENSION_WEATHER_BACKEND;
+       extension = e_source_get_extension (source, extension_name);
+
+       g_free (priv->city);
+
+       location = e_source_weather_dup_location (extension);
+       priv->city = g_strdup (strrchr (location, '/') + 1);
+       g_free (location);
 
        e_cal_backend_notify_readonly (E_CAL_BACKEND (backend), TRUE);
 
@@ -903,4 +905,7 @@ e_cal_backend_weather_class_init (ECalBackendWeatherClass *class)
 
        backend_class->start_view               = e_cal_backend_weather_start_view;
        backend_class->internal_get_timezone    = e_cal_backend_weather_internal_get_timezone;
+
+       /* Register our ESource extension. */
+       E_TYPE_SOURCE_WEATHER;
 }
diff --git a/calendar/backends/weather/e-source-weather.c b/calendar/backends/weather/e-source-weather.c
new file mode 100644 (file)
index 0000000..0f7e581
--- /dev/null
@@ -0,0 +1,252 @@
+/*
+ * e-source-weather.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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 the program; if not, see <webcal://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-source-weather.h"
+
+#include <libedataserver/e-data-server-util.h>
+
+#define E_SOURCE_WEATHER_GET_PRIVATE(obj) \
+       (G_TYPE_INSTANCE_GET_PRIVATE \
+       ((obj), E_TYPE_SOURCE_WEATHER, ESourceWeatherPrivate))
+
+struct _ESourceWeatherPrivate {
+       GMutex *property_lock;
+       ESourceWeatherUnits units;
+       gchar *location;
+};
+
+enum {
+       PROP_0,
+       PROP_LOCATION,
+       PROP_UNITS
+};
+
+static GType e_source_weather_units_type = G_TYPE_INVALID;
+
+G_DEFINE_DYNAMIC_TYPE (
+       ESourceWeather,
+       e_source_weather,
+       E_TYPE_SOURCE_EXTENSION)
+
+static void
+source_weather_set_property (GObject *object,
+                             guint property_id,
+                             const GValue *value,
+                             GParamSpec *pspec)
+{
+       switch (property_id) {
+               case PROP_LOCATION:
+                       e_source_weather_set_location (
+                               E_SOURCE_WEATHER (object),
+                               g_value_get_string (value));
+                       return;
+
+               case PROP_UNITS:
+                       e_source_weather_set_units (
+                               E_SOURCE_WEATHER (object),
+                               g_value_get_enum (value));
+                       return;
+       }
+
+       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+source_weather_get_property (GObject *object,
+                             guint property_id,
+                             GValue *value,
+                             GParamSpec *pspec)
+{
+       switch (property_id) {
+               case PROP_LOCATION:
+                       g_value_take_string (
+                               value,
+                               e_source_weather_dup_location (
+                               E_SOURCE_WEATHER (object)));
+                       return;
+
+               case PROP_UNITS:
+                       g_value_set_enum (
+                               value,
+                               e_source_weather_get_units (
+                               E_SOURCE_WEATHER (object)));
+                       return;
+       }
+
+       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+source_weather_finalize (GObject *object)
+{
+       ESourceWeatherPrivate *priv;
+
+       priv = E_SOURCE_WEATHER_GET_PRIVATE (object);
+
+       g_mutex_free (priv->property_lock);
+
+       g_free (priv->location);
+
+       /* Chain up to parent's finalize() method. */
+       G_OBJECT_CLASS (e_source_weather_parent_class)->finalize (object);
+}
+
+static void
+e_source_weather_class_init (ESourceWeatherClass *class)
+{
+       GObjectClass *object_class;
+       ESourceExtensionClass *extension_class;
+
+       g_type_class_add_private (class, sizeof (ESourceWeatherPrivate));
+
+       object_class = G_OBJECT_CLASS (class);
+       object_class->set_property = source_weather_set_property;
+       object_class->get_property = source_weather_get_property;
+       object_class->finalize = source_weather_finalize;
+
+       extension_class = E_SOURCE_EXTENSION_CLASS (class);
+       extension_class->name = E_SOURCE_EXTENSION_WEATHER_BACKEND;
+
+       g_object_class_install_property (
+               object_class,
+               PROP_LOCATION,
+               g_param_spec_string (
+                       "location",
+                       "Location",
+                       "Weather location code",
+                       NULL,
+                       G_PARAM_READWRITE |
+                       G_PARAM_CONSTRUCT |
+                       E_SOURCE_PARAM_SETTING));
+
+       g_object_class_install_property (
+               object_class,
+               PROP_UNITS,
+               g_param_spec_enum (
+                       "units",
+                       "Units",
+                       "Metric or imperial units",
+                       E_TYPE_SOURCE_WEATHER_UNITS,
+                       E_SOURCE_WEATHER_UNITS_METRIC,
+                       G_PARAM_READWRITE |
+                       G_PARAM_CONSTRUCT |
+                       E_SOURCE_PARAM_SETTING));
+}
+
+static void
+e_source_weather_class_finalize (ESourceWeatherClass *class)
+{
+}
+
+static void
+e_source_weather_init (ESourceWeather *extension)
+{
+       extension->priv = E_SOURCE_WEATHER_GET_PRIVATE (extension);
+       extension->priv->property_lock = g_mutex_new ();
+}
+
+void
+e_source_weather_type_register (GTypeModule *type_module)
+{
+       static const GEnumValue e_source_weather_units_values[] = {
+               { E_SOURCE_WEATHER_UNITS_METRIC,
+                 "E_SOURCE_WEATHER_UNITS_METRIC",
+                 "metric" },
+               { E_SOURCE_WEATHER_UNITS_IMPERIAL,
+                 "E_SOURCE_WEATHER_UNITS_IMPERIAL",
+                 "imperial" },
+               { 0, NULL, NULL }
+       };
+
+       e_source_weather_units_type =
+               g_type_module_register_enum (
+               type_module, "ESourceWeatherUnits",
+               e_source_weather_units_values);
+
+       /* XXX G_DEFINE_DYNAMIC_TYPE declares a static type registration
+        *     function, so we have to wrap it with a public function in
+        *     order to register types from a separate compilation unit. */
+       e_source_weather_register_type (type_module);
+}
+
+const gchar *
+e_source_weather_get_location (ESourceWeather *extension)
+{
+       g_return_val_if_fail (E_IS_SOURCE_WEATHER (extension), NULL);
+
+       return extension->priv->location;
+}
+
+gchar *
+e_source_weather_dup_location (ESourceWeather *extension)
+{
+       const gchar *protected;
+       gchar *duplicate;
+
+       g_return_val_if_fail (E_IS_SOURCE_WEATHER (extension), NULL);
+
+       g_mutex_lock (extension->priv->property_lock);
+
+       protected = e_source_weather_get_location (extension);
+       duplicate = g_strdup (protected);
+
+       g_mutex_unlock (extension->priv->property_lock);
+
+       return duplicate;
+}
+
+void
+e_source_weather_set_location (ESourceWeather *extension,
+                               const gchar *location)
+{
+       g_return_if_fail (E_IS_SOURCE_WEATHER (extension));
+
+       g_mutex_lock (extension->priv->property_lock);
+
+       g_free (extension->priv->location);
+       extension->priv->location = e_util_strdup_strip (location);
+
+       g_mutex_unlock (extension->priv->property_lock);
+
+       g_object_notify (G_OBJECT (extension), "location");
+}
+
+ESourceWeatherUnits
+e_source_weather_get_units (ESourceWeather *extension)
+{
+       g_return_val_if_fail (E_IS_SOURCE_WEATHER (extension), 0);
+
+       return extension->priv->units;
+}
+
+void
+e_source_weather_set_units (ESourceWeather *extension,
+                            ESourceWeatherUnits units)
+{
+       g_return_if_fail (E_IS_SOURCE_WEATHER (extension));
+
+       extension->priv->units = units;
+
+       g_object_notify (G_OBJECT (extension), "units");
+}
+
+ESourceWeatherUnits
+e_source_weather_units_get_type (void)
+{
+       return e_source_weather_units_type;
+}
diff --git a/calendar/backends/weather/e-source-weather.h b/calendar/backends/weather/e-source-weather.h
new file mode 100644 (file)
index 0000000..85ad991
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * e-source-weather.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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 the program; if not, see <webcal://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_SOURCE_WEATHER_H
+#define E_SOURCE_WEATHER_H
+
+#include <libedataserver/e-source-extension.h>
+
+/* Standard GObject macros */
+#define E_TYPE_SOURCE_WEATHER \
+       (e_source_weather_get_type ())
+#define E_SOURCE_WEATHER(obj) \
+       (G_TYPE_CHECK_INSTANCE_CAST \
+       ((obj), E_TYPE_SOURCE_WEATHER, ESourceWeather))
+#define E_SOURCE_WEATHER_CLASS(cls) \
+       (G_TYPE_CHECK_CLASS_CAST \
+       ((cls), E_TYPE_SOURCE_WEATHER, ESourceWeatherClass))
+#define E_IS_SOURCE_WEATHER(obj) \
+       (G_TYPE_CHECK_INSTANCE_TYPE \
+       ((obj), E_TYPE_SOURCE_WEATHER))
+#define E_IS_SOURCE_WEATHER_CLASS(cls) \
+       (G_TYPE_CHECK_CLASS_TYPE \
+       ((cls), E_TYPE_SOURCE_WEATHER))
+#define E_SOURCE_WEATHER_GET_CLASS(obj) \
+       (G_TYPE_INSTANCE_GET_CLASS \
+       ((obj), E_TYPE_SOURCE_WEATHER, ESourceWeatherClass))
+
+#define E_TYPE_SOURCE_WEATHER_UNITS \
+       (e_source_weather_units_get_type ())
+
+#define E_SOURCE_EXTENSION_WEATHER_BACKEND "Weather Backend"
+
+G_BEGIN_DECLS
+
+typedef struct _ESourceWeather ESourceWeather;
+typedef struct _ESourceWeatherClass ESourceWeatherClass;
+typedef struct _ESourceWeatherPrivate ESourceWeatherPrivate;
+
+struct _ESourceWeather {
+       ESourceExtension parent;
+       ESourceWeatherPrivate *priv;
+};
+
+struct _ESourceWeatherClass {
+       ESourceExtensionClass parent_class;
+};
+
+typedef enum {
+       E_SOURCE_WEATHER_UNITS_METRIC,
+       E_SOURCE_WEATHER_UNITS_IMPERIAL
+} ESourceWeatherUnits;
+
+GType          e_source_weather_get_type       (void);
+void           e_source_weather_type_register  (GTypeModule *type_module);
+const gchar *  e_source_weather_get_location   (ESourceWeather *extension);
+gchar *                e_source_weather_dup_location   (ESourceWeather *extension);
+void           e_source_weather_set_location   (ESourceWeather *extension,
+                                                const gchar *location);
+ESourceWeatherUnits
+               e_source_weather_get_units      (ESourceWeather *extension);
+void           e_source_weather_set_units      (ESourceWeather *extension,
+                                                ESourceWeatherUnits units);
+
+GType          e_source_weather_units_get_type         (void);
+
+G_END_DECLS
+
+#endif /* E_SOURCE_WEATHER_H */
index a5c23b5..18f6b5f 100644 (file)
@@ -437,26 +437,27 @@ e_weather_source_ccf_init (EWeatherSourceCCF *source)
 }
 
 EWeatherSource *
-e_weather_source_ccf_new (const gchar *uri)
+e_weather_source_ccf_new (const gchar *location)
 {
-       /* Old URI is formatted as weather://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 URI is as weather://code/name, where code is 4-letter code.
-        * So if got the old URI, then migrate to the new one, if possible.
+       /* 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 (uri == NULL)
+       if (location == NULL)
                return NULL;
 
-       if (strncmp (uri, "ccf/", 4) == 0)
-               wl = find_location (uri + 4, TRUE);
+       if (strncmp (location, "ccf/", 4) == 0)
+               wl = find_location (location + 4, TRUE);
        else
-               wl = find_location (uri, FALSE);
+               wl = find_location (location, FALSE);
 
        if (wl == NULL)
                return NULL;
index 1832b72..e0ae161 100644 (file)
@@ -69,7 +69,7 @@ struct _EWeatherSourceCCFClass {
 };
 
 GType          e_weather_source_ccf_get_type   (void);
-EWeatherSource *e_weather_source_ccf_new       (const gchar *uri);
+EWeatherSource *e_weather_source_ccf_new       (const gchar *location);
 
 G_END_DECLS
 
index 74ea669..3dd3431 100644 (file)
@@ -53,9 +53,9 @@ e_weather_source_init (EWeatherSource *source)
 }
 
 EWeatherSource *
-e_weather_source_new (const gchar *uri)
+e_weather_source_new (const gchar *location)
 {
-       const gchar *base = uri + 10; /* skip weather:// */
+       g_return_val_if_fail (location != NULL, NULL);
 
-       return e_weather_source_ccf_new (base);
+       return e_weather_source_ccf_new (location);
 }
index e5e94cc..e36793e 100644 (file)
@@ -100,7 +100,7 @@ struct _EWeatherSourceClass {
 };
 
 GType          e_weather_source_get_type       (void);
-EWeatherSource *e_weather_source_new           (const gchar *uri);
+EWeatherSource *e_weather_source_new           (const gchar *location);
 void           e_weather_source_parse          (EWeatherSource *source,
                                                 EWeatherSourceFinished done,
                                                 gpointer data);