Commit d21230f7 authored by Matthew Barnes's avatar Matthew Barnes
Browse files

Add 'cal-config-weather' module.

Registers the "Weather" backend in ECalSourceConfig widgets.

Replaces the 'calendar-weather' plugin.
parent c030e2f0
......@@ -1301,7 +1301,7 @@ dnl Add any new plugins here
plugins_base_always="calendar-http itip-formatter default-source mark-all-read publish-calendar imap-features"
plugins_base="$plugins_base_always"
dist_plugins_base="$plugins_base_always calendar-weather"
dist_plugins_base="$plugins_base_always"
plugins_standard_always="bbdb save-calendar mail-to-task mailing-list-actions prefer-plain mail-notification attachment-reminder email-custom-header face templates vcard-inline dbx-import external-editor"
......@@ -1352,10 +1352,8 @@ if test "x$enable_weather" != "xno"; then
AC_SUBST(GWEATHER_CFLAGS)
AC_SUBST(GWEATHER_LIBS)
if test "x$have_weather" = "xyes"; then
plugins_base="$plugins_base calendar-weather"
else
AC_MSG_ERROR([gweather-3.0 >= gweather_minimum_version is required for configuring weather calendars. Use --disable-weather to disable this features.])
if test "x$have_weather" = "xno"; then
AC_MSG_ERROR([gweather-3.0 >= gweather_minimum_version is required for configuring weather calendars. Use --disable-weather to disable this feature.])
fi
dnl gweather-3.5 introduces API changes we do not yet support.
......@@ -1363,6 +1361,7 @@ if test "x$enable_weather" != "xno"; then
AC_MSG_ERROR([gweather-3.5 is not yet supported. Install gweather-3.4 or specify --disable-weather as a configure option to exclude the calendar-weather plugin.])
fi
fi
AM_CONDITIONAL(ENABLE_WEATHER, [test "x$enable_weather" != "xno"])
dnl ********************************************************************
dnl maps in contacts preview requires champlain-gtk, geoclue and clutter
......@@ -1641,6 +1640,7 @@ modules/cal-config-caldav/Makefile
modules/cal-config-contacts/Makefile
modules/cal-config-google/Makefile
modules/cal-config-local/Makefile
modules/cal-config-weather/Makefile
modules/composer-autosave/Makefile
modules/mailto-handler/Makefile
modules/mdn/Makefile
......@@ -1658,7 +1658,6 @@ plugins/attachment-reminder/Makefile
plugins/audio-inline/Makefile
plugins/bbdb/Makefile
plugins/calendar-http/Makefile
plugins/calendar-weather/Makefile
plugins/dbx-import/Makefile
plugins/default-source/Makefile
plugins/email-custom-header/Makefile
......
......@@ -2,6 +2,10 @@ if ENABLE_LDAP
CONFIG_LDAP_DIR = book-config-ldap
endif
if ENABLE_WEATHER
CONFIG_WEATHER_DIR = cal-config-weather
endif
if ENABLE_MONO
MONO_DIR = plugin-mono
endif
......@@ -28,6 +32,7 @@ SUBDIRS = \
cal-config-contacts \
cal-config-google \
cal-config-local \
$(CONFIG_WEATHER_DIR) \
composer-autosave \
mailto-handler \
mdn \
......
eds_datadir = `pkg-config --variable=privdatadir evolution-data-server-1.2`
module_LTLIBRARIES = module-cal-config-weather.la
@EVO_PLUGIN_RULE@
plugin_DATA = org-gnome-calendar-weather.eplug
plugin_LTLIBRARIES = liborg-gnome-calendar-weather.la
liborg_gnome_calendar_weather_la_CPPFLAGS = \
module_cal_config_weather_la_CPPFLAGS = \
$(AM_CPPFLAGS) \
-I$(top_srcdir) \
-I$(top_srcdir)/widgets \
-DWEATHER_DATADIR=\""$(weatherdatadir)"\" \
-DWEATHER_EDS_DATADIR=\""$(eds_datadir)/weather"\" \
-DG_LOG_DOMAIN=\"evolution-cal-config-weather\" \
$(EVOLUTION_DATA_SERVER_CFLAGS) \
$(GNOME_PLATFORM_CFLAGS) \
$(GWEATHER_CFLAGS)
liborg_gnome_calendar_weather_la_SOURCES = calendar-weather.c
liborg_gnome_calendar_weather_la_LDFLAGS = -module -avoid-version $(NO_UNDEFINED)
liborg_gnome_calendar_weather_la_LIBADD = \
$(top_builddir)/calendar/gui/libevolution-calendar.la \
module_cal_config_weather_la_SOURCES = \
evolution-cal-config-weather.c \
e-source-weather.c \
e-source-weather.h
module_cal_config_weather_la_LIBADD = \
$(top_builddir)/e-util/libeutil.la \
$(top_builddir)/widgets/misc/libemiscwidgets.la \
$(top_builddir)/calendar/gui/libevolution-calendar.la \
$(EVOLUTION_DATA_SERVER_LIBS) \
$(GNOME_PLATFORM_LIBS) \
$(GWEATHER_LIBS)
EXTRA_DIST = \
org-gnome-calendar-weather.eplug.xml \
$(weatherdata_DATA)
BUILT_SOURCES = $(plugin_DATA)
CLEANFILES = $(BUILT_SOURCES)
module_cal_config_weather_la_LDFLAGS = \
-module -avoid-version $(NO_UNDEFINED)
-include $(top_srcdir)/git.mk
/*
* 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;
}
/*
* 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 */
/*
* evolution-cal-config-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 <http://www.gnu.org/licenses/>
*
*/
#include <config.h>
#include <glib/gi18n-lib.h>
#include <libebackend/e-extension.h>
#define GWEATHER_I_KNOW_THIS_IS_UNSTABLE
#include <libgweather/location-entry.h>
#undef GWEATHER_I_KNOW_THIS_IS_UNSTABLE
#include <misc/e-source-config-backend.h>
#include <calendar/gui/e-cal-source-config.h>
#include "e-source-weather.h"
typedef ESourceConfigBackend ECalConfigWeather;
typedef ESourceConfigBackendClass ECalConfigWeatherClass;
/* Module Entry Points */
void e_module_load (GTypeModule *type_module);
void e_module_unload (GTypeModule *type_module);
typedef struct _Context Context;
struct _Context {
GtkWidget *location_entry;
GtkWidget *units_combo;
};
/* Forward Declarations */
GType e_cal_config_weather_get_type (void);
G_DEFINE_DYNAMIC_TYPE (
ECalConfigWeather,
e_cal_config_weather,
E_TYPE_SOURCE_CONFIG_BACKEND)
static void
cal_config_weather_context_free (Context *context)
{
g_object_unref (context->location_entry);
g_object_unref (context->units_combo);
g_slice_free (Context, context);
}
static gboolean
cal_config_weather_location_to_string (GBinding *binding,
const GValue *source_value,
GValue *target_value,
gpointer user_data)
{
GWeatherLocation *location;
gchar *string = NULL;
location = g_value_get_pointer (source_value);
if (location != NULL) {
const gchar *code;
gchar *city_name;
code = gweather_location_get_code (location);
city_name = gweather_location_get_city_name (location);
string = g_strdup_printf ("%s/%s", code, city_name);
g_free (city_name);
}
g_value_take_string (target_value, string);
return TRUE;
}
/* XXX This is a private libgweather constant.
* The value may change at any time. */
#define GWEATHER_LOCATION_ENTRY_COL_LOCATION 1
static gboolean
cal_config_weather_string_to_location (GBinding *binding,
const GValue *source_value,
GValue *target_value,
gpointer user_data)
{
GObject *target;
GWeatherLocation *match = NULL;
GtkEntryCompletion *completion;
GtkTreeModel *model;
GtkTreeIter iter;
const gchar *string;
const gchar *city_name;
const gchar *code;
gchar **tokens;
/* XXX This is a bit convoluted because libgweather lacks a
* GWeatherLocation lookup function. The algorithm is
* copied from gweather_location_entry_set_city(). */
string = g_value_get_string (source_value);
if (string == NULL)
return FALSE;
/* String is: STATION-CODE '/' CITY-NAME */
tokens = g_strsplit (string, "/", 2);
if (g_strv_length (tokens) != 2) {
g_strfreev (tokens);
return FALSE;
}
code = tokens[0];
city_name = tokens[1];
target = g_binding_get_target (binding);
completion = gtk_entry_get_completion (GTK_ENTRY (target));
model = gtk_entry_completion_get_model (completion);
gtk_tree_model_get_iter_first (model, &iter);
do {
GWeatherLocation *location;
const gchar *cmp_code;
gchar *cmp_city_name;
gtk_tree_model_get (
model, &iter,
GWEATHER_LOCATION_ENTRY_COL_LOCATION,
&location, -1);
/* Does the station code match? */
cmp_code = gweather_location_get_code (location);
if (g_strcmp0 (code, cmp_code) != 0)
continue;
/* Does the city name match? */
cmp_city_name = gweather_location_get_city_name (location);
if (g_strcmp0 (city_name, cmp_city_name) != 0) {
g_free (cmp_city_name);
continue;
}
g_free (cmp_city_name);
/* We found a match! */
match = location;
break;
} while (gtk_tree_model_iter_next (model, &iter));
g_value_set_pointer (target_value, match);
g_strfreev (tokens);
return TRUE;
}
static gboolean