1 /* Evolution calendar - weather backend
3 * Copyright (C) 2005 Novell, Inc (www.novell.com)
5 * Authors: David Trowbridge <trowbrds@cs.colorado.edu>
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of version 2 of the GNU Lesser General Public
9 * License as published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 #include <libedata-cal/e-cal-backend-cache.h>
23 #include <libedata-cal/e-cal-backend-util.h>
24 #include <libedata-cal/e-cal-backend-sexp.h>
25 #include <glib/gi18n-lib.h>
27 #include "e-cal-backend-weather.h"
28 #include "e-weather-source.h"
30 #define WEATHER_UID_EXT "-weather"
32 static gboolean reload_cb (ECalBackendWeather *cbw);
33 static gboolean begin_retrieval_cb (ECalBackendWeather *cbw);
34 static ECalComponent* create_weather (ECalBackendWeather *cbw, WeatherForecast *report);
35 static ECalBackendSyncStatus
36 e_cal_backend_weather_add_timezone (ECalBackendSync *backend, EDataCal *cal, const char *tzobj);
38 /* Private part of the ECalBackendWeather structure */
39 struct _ECalBackendWeatherPrivate {
40 /* URI to get remote weather data from */
43 /* Local/remote mode */
47 ECalBackendCache *cache;
49 /* The calendar's default timezone, used for resolving DATE and
50 floating DATE-TIME values. */
51 icaltimezone *default_zone;
55 guint reload_timeout_id;
56 guint source_changed_id;
62 /* City (for summary) */
66 EWeatherSource *source;
69 static ECalBackendSyncClass *parent_class;
72 reload_cb (ECalBackendWeather *cbw)
74 ECalBackendWeatherPrivate *priv;
81 priv->reload_timeout_id = 0;
83 begin_retrieval_cb (cbw);
88 source_changed (ESource *source, ECalBackendWeather *cbw)
91 * We should force a reload of the data when this gets called. Unfortunately,
92 * this signal isn't getting through from evolution to the backend
97 maybe_start_reload_timeout (ECalBackendWeather *cbw)
99 ECalBackendWeatherPrivate *priv;
101 const gchar *refresh_str;
105 if (priv->reload_timeout_id)
108 source = e_cal_backend_get_source (E_CAL_BACKEND (cbw));
110 g_warning ("Could not get source for ECalBackendWeather reload.");
114 if (priv->source_changed_id == 0)
115 priv->source_changed_id = g_signal_connect (G_OBJECT (source),
117 G_CALLBACK (source_changed),
120 refresh_str = e_source_get_property (source, "refresh");
122 /* By default, reload every 4 hours. At least for CCF, the forecasts only come out
123 * twice a day, and chances are while the NWS and similar organizations have some
124 * serious bandwidth, they would appreciate it if we didn't hammer their servers
126 priv->reload_timeout_id = g_timeout_add ((refresh_str ? atoi (refresh_str) : 240) * 60000,
127 (GSourceFunc) reload_cb, cbw);
132 finished_retrieval_cb (GList *forecasts, ECalBackendWeather *cbw)
134 ECalBackendWeatherPrivate *priv;
136 icalcomponent *icomp;
141 if (forecasts == NULL) {
142 e_cal_backend_notify_error (E_CAL_BACKEND (cbw), _("Could not retrieve weather data"));
147 l = e_cal_backend_cache_get_components (priv->cache);
148 for (; l != NULL; l = g_list_next (l)) {
151 icomp = e_cal_component_get_icalcomponent (E_CAL_COMPONENT (l->data));
152 id = e_cal_component_get_id (E_CAL_COMPONENT (l->data));
154 e_cal_backend_notify_object_removed (E_CAL_BACKEND (cbw),
156 icalcomponent_as_ical_string (icomp),
159 e_cal_component_free_id (id);
160 g_object_unref (G_OBJECT (l->data));
163 e_file_cache_clean (E_FILE_CACHE (priv->cache));
165 for (l = forecasts; l != NULL; l = g_list_next (l)) {
166 comp = create_weather (cbw, l->data);
167 e_cal_backend_cache_put_component (priv->cache, comp);
168 icomp = e_cal_component_get_icalcomponent (comp);
169 e_cal_backend_notify_object_created (E_CAL_BACKEND (cbw), icalcomponent_as_ical_string (icomp));
172 priv->is_loading = FALSE;
176 begin_retrieval_cb (ECalBackendWeather *cbw)
178 ECalBackendWeatherPrivate *priv = cbw->priv;
180 if (priv->mode != CAL_MODE_REMOTE)
183 maybe_start_reload_timeout (cbw);
185 if (priv->source == NULL)
186 priv->source = e_weather_source_new (e_cal_backend_get_uri (E_CAL_BACKEND (cbw)));
188 if (priv->is_loading)
191 priv->is_loading = TRUE;
193 e_weather_source_parse (priv->source, (EWeatherSourceFinished) finished_retrieval_cb, cbw);
199 getConditions (WeatherForecast *report)
201 switch (report->conditions) {
202 case WEATHER_FAIR: return _("Fair");
203 case WEATHER_SNOW_SHOWERS: return _("Snow showers");
204 case WEATHER_SNOW: return _("Snow");
205 case WEATHER_PARTLY_CLOUDY: return _("Partly cloudy");
206 case WEATHER_SMOKE: return _("Smoke");
207 case WEATHER_THUNDERSTORMS: return _("Thunderstorms");
208 case WEATHER_CLOUDY: return _("Cloudy");
209 case WEATHER_DRIZZLE: return _("Drizzle");
210 case WEATHER_SUNNY: return _("Sunny");
211 case WEATHER_DUST: return _("Dust");
212 case WEATHER_CLEAR: return _("Clear");
213 case WEATHER_MOSTLY_CLOUDY: return _("Mostly cloudy");
214 case WEATHER_WINDY: return _("Windy");
215 case WEATHER_RAIN_SHOWERS: return _("Rain showers");
216 case WEATHER_FOGGY: return _("Foggy");
217 case WEATHER_RAIN_OR_SNOW_MIXED: return _("Rain/snow mixed");
218 case WEATHER_SLEET: return _("Sleet");
219 case WEATHER_VERY_HOT_OR_HOT_HUMID: return _("Very hot/humid");
220 case WEATHER_BLIZZARD: return _("Blizzard");
221 case WEATHER_FREEZING_RAIN: return _("Freezing rain");
222 case WEATHER_HAZE: return _("Haze");
223 case WEATHER_BLOWING_SNOW: return _("Blowing snow");
224 case WEATHER_FREEZING_DRIZZLE: return _("Freezing drizzle");
225 case WEATHER_VERY_COLD_WIND_CHILL: return _("Very cold/wind chill");
226 case WEATHER_RAIN: return _("Rain");
227 default: return NULL;
232 getCategory (WeatherForecast *report)
234 /* Right now this is based on which icons we have available */
235 switch (report->conditions) {
236 case WEATHER_FAIR: return _("Weather: Sunny");
237 case WEATHER_SNOW_SHOWERS: return _("Weather: Snow");
238 case WEATHER_SNOW: return _("Weather: Snow");
239 case WEATHER_PARTLY_CLOUDY: return _("Weather: Partly Cloudy");
240 case WEATHER_SMOKE: return _("Weather: Fog");
241 case WEATHER_THUNDERSTORMS: return _("Weather: Thunderstorms");
242 case WEATHER_CLOUDY: return _("Weather: Cloudy");
243 case WEATHER_DRIZZLE: return _("Weather: Rain");
244 case WEATHER_SUNNY: return _("Weather: Sunny");
245 case WEATHER_DUST: return _("Weather: Fog");
246 case WEATHER_CLEAR: return _("Weather: Sunny");
247 case WEATHER_MOSTLY_CLOUDY: return _("Weather: Cloudy");
248 case WEATHER_WINDY: return "";
249 case WEATHER_RAIN_SHOWERS: return _("Weather: Rain");
250 case WEATHER_FOGGY: return _("Weather: Fog");
251 case WEATHER_RAIN_OR_SNOW_MIXED: return _("Weather: Rain");
252 case WEATHER_SLEET: return _("Weather: Rain");
253 case WEATHER_VERY_HOT_OR_HOT_HUMID: return _("Weather: Sunny");
254 case WEATHER_BLIZZARD: return _("Weather: Snow");
255 case WEATHER_FREEZING_RAIN: return _("Weather: Rain");
256 case WEATHER_HAZE: return _("Weather: Fog");
257 case WEATHER_BLOWING_SNOW: return _("Weather: Snow");
258 case WEATHER_FREEZING_DRIZZLE: return _("Weather: Rain");
259 case WEATHER_VERY_COLD_WIND_CHILL: return "";
260 case WEATHER_RAIN: return _("Weather: Rain");
261 default: return NULL;
268 return ((c * 9.0f / 5.0f) + 32.0f);
277 static ECalComponent*
278 create_weather (ECalBackendWeather *cbw, WeatherForecast *report)
280 ECalBackendWeatherPrivate *priv;
281 ECalComponent *cal_comp;
282 ECalComponentText comp_summary;
283 icalcomponent *ical_comp;
284 struct icaltimetype itt;
285 ECalComponentDateTime dt;
287 GSList *text_list = NULL;
288 ECalComponentText *description;
294 g_return_val_if_fail (E_IS_CAL_BACKEND_WEATHER (cbw), NULL);
298 source = e_cal_backend_get_source (E_CAL_BACKEND (cbw));
299 format = e_source_get_property (source, "units");
300 if (format == NULL) {
301 format = e_source_get_property (source, "temperature");
305 metric = (strcmp (format, "fahrenheit") != 0);
307 metric = (strcmp (format, "metric") == 0);
310 /* create the component and event object */
311 ical_comp = icalcomponent_new (ICAL_VEVENT_COMPONENT);
312 cal_comp = e_cal_component_new ();
313 e_cal_component_set_icalcomponent (cal_comp, ical_comp);
316 uid = e_cal_component_gen_uid ();
317 e_cal_component_set_uid (cal_comp, uid);
319 /* Set all-day event's date from forecast data */
320 itt = icaltime_from_timet (report->date, 1);
323 e_cal_component_set_dtstart (cal_comp, &dt);
325 itt = icaltime_from_timet (report->date, 1);
326 icaltime_adjust (&itt, 1, 0, 0, 0);
329 /* We have to add 1 day to DTEND, as it is not inclusive. */
330 e_cal_component_set_dtend (cal_comp, &dt);
332 /* The summary is the high or high/low temperatures */
333 if (report->high == report->low) {
335 comp_summary.value = g_strdup_printf (_("%.1f°C - %s"), report->high, priv->city);
337 comp_summary.value = g_strdup_printf (_("%.1f°F - %s"), ctof (report->high), priv->city);
340 comp_summary.value = g_strdup_printf (_("%.1f/%.1f°C - %s"), report->high, report->low, priv->city);
342 comp_summary.value = g_strdup_printf (_("%.1f/%.1f°F - %s"), ctof (report->high), ctof (report->low), priv->city);
344 comp_summary.altrep = NULL;
345 e_cal_component_set_summary (cal_comp, &comp_summary);
347 if (report->pop != 0)
348 pop = g_strdup_printf (_("%d%% chance of precipitation\n"), report->pop);
351 if (report->snowhigh == 0)
352 snow = g_strdup ("");
353 else if (report->snowhigh == report->snowlow) {
355 snow = g_strdup_printf (_("%.1fcm snow\n"), report->snowhigh);
357 snow = g_strdup_printf (_("%.1fin snow\n"), cmtoin(report->snowhigh));
360 snow = g_strdup_printf (_("%.1f-%.1fcm snow\n"), report->snowlow, report->snowhigh);
362 snow = g_strdup_printf (_("%.1f-%.1fin snow\n"), cmtoin(report->snowlow), cmtoin(report->snowhigh));
364 description = g_new0 (ECalComponentText, 1);
365 description->value = g_strdup_printf ("%s\n%s%s", getConditions (report), pop, snow);
366 description->altrep = "";
367 text_list = g_slist_append (text_list, description);
368 e_cal_component_set_description_list (cal_comp, text_list);
370 /* Set category and visibility */
371 e_cal_component_set_categories (cal_comp, getCategory (report));
372 e_cal_component_set_classification (cal_comp, E_CAL_COMPONENT_CLASS_PUBLIC);
374 /* Weather is shown as free time */
375 e_cal_component_set_transparency (cal_comp, E_CAL_COMPONENT_TRANSP_TRANSPARENT);
377 e_cal_component_commit_sequence (cal_comp);
385 static ECalBackendSyncStatus
386 e_cal_backend_weather_is_read_only (ECalBackendSync *backend, EDataCal *cal, gboolean *read_only)
390 return GNOME_Evolution_Calendar_Success;
393 static ECalBackendSyncStatus
394 e_cal_backend_weather_get_cal_address (ECalBackendSync *backend, EDataCal *cal, char **address)
396 /* Weather has no particular email addresses associated with it */
399 return GNOME_Evolution_Calendar_Success;
402 static ECalBackendSyncStatus
403 e_cal_backend_weather_get_alarm_email_address (ECalBackendSync *backend, EDataCal *cal, char **address)
405 /* Weather has no particular email addresses associated with it */
408 return GNOME_Evolution_Calendar_Success;
411 static ECalBackendSyncStatus
412 e_cal_backend_weather_get_ldap_attribute (ECalBackendSync *backend, EDataCal *cal, char **attribute)
416 return GNOME_Evolution_Calendar_Success;
419 static ECalBackendSyncStatus
420 e_cal_backend_weather_get_static_capabilities (ECalBackendSync *backend, EDataCal *cal, char **capabilities)
422 *capabilities = g_strdup (CAL_STATIC_CAPABILITY_NO_ALARM_REPEAT ","
423 CAL_STATIC_CAPABILITY_NO_AUDIO_ALARMS ","
424 CAL_STATIC_CAPABILITY_NO_DISPLAY_ALARMS ","
425 CAL_STATIC_CAPABILITY_NO_PROCEDURE_ALARMS ","
426 CAL_STATIC_CAPABILITY_NO_TASK_ASSIGNMENT ","
427 CAL_STATIC_CAPABILITY_NO_THISANDFUTURE ","
428 CAL_STATIC_CAPABILITY_NO_THISANDPRIOR);
430 return GNOME_Evolution_Calendar_Success;
433 static ECalBackendSyncStatus
434 e_cal_backend_weather_open (ECalBackendSync *backend, EDataCal *cal, gboolean only_if_exists, const char *username, const char *password)
436 ECalBackendWeather *cbw;
437 ECalBackendWeatherPrivate *priv;
440 cbw = E_CAL_BACKEND_WEATHER (backend);
443 uri = e_cal_backend_get_uri (E_CAL_BACKEND (backend));
446 priv->city = g_strdup (strrchr (uri, '/') + 1);
449 priv->cache = e_cal_backend_cache_new (uri, E_CAL_SOURCE_TYPE_EVENT);
452 e_cal_backend_notify_error (E_CAL_BACKEND (cbw), _("Could not create cache file"));
453 return GNOME_Evolution_Calendar_OtherError;
456 if (priv->default_zone) {
457 icalcomponent *icalcomp = icaltimezone_get_component (priv->default_zone);
458 icaltimezone *zone = icaltimezone_new ();
460 icaltimezone_set_component (zone, icalcomponent_new_clone (icalcomp));
462 g_hash_table_insert (priv->zones, g_strdup (icaltimezone_get_tzid (zone)), zone);
465 if (priv->mode == CAL_MODE_LOCAL)
466 return GNOME_Evolution_Calendar_Success;
468 g_idle_add ((GSourceFunc) begin_retrieval_cb, cbw);
471 return GNOME_Evolution_Calendar_Success;
474 static ECalBackendSyncStatus
475 e_cal_backend_weather_remove (ECalBackendSync *backend, EDataCal *cal)
477 ECalBackendWeather *cbw;
478 ECalBackendWeatherPrivate *priv;
480 cbw = E_CAL_BACKEND_WEATHER (backend);
484 return GNOME_Evolution_Calendar_OtherError;
486 e_file_cache_remove (E_FILE_CACHE (priv->cache));
487 return GNOME_Evolution_Calendar_Success;
490 static ECalBackendSyncStatus
491 e_cal_backend_weather_discard_alarm (ECalBackendSync *backend, EDataCal *cal, const char *uid, const char *auid)
493 return GNOME_Evolution_Calendar_Success;
496 static ECalBackendSyncStatus
497 e_cal_backend_weather_receive_objects (ECalBackendSync *backend, EDataCal *cal, const char *calobj)
499 return GNOME_Evolution_Calendar_PermissionDenied;
502 static ECalBackendSyncStatus
503 e_cal_backend_weather_get_default_object (ECalBackendSync *backend, EDataCal *cal, char **object)
505 return GNOME_Evolution_Calendar_UnsupportedMethod;
508 static ECalBackendSyncStatus
509 e_cal_backend_weather_get_object (ECalBackendSync *backend, EDataCal *cal, const char *uid, const char *rid, char **object)
511 ECalBackendWeather *cbw = E_CAL_BACKEND_WEATHER (backend);
512 ECalBackendWeatherPrivate *priv = cbw->priv;
515 g_return_val_if_fail (uid != NULL, GNOME_Evolution_Calendar_ObjectNotFound);
516 g_return_val_if_fail (priv->cache != NULL, GNOME_Evolution_Calendar_ObjectNotFound);
518 comp = e_cal_backend_cache_get_component (priv->cache, uid, rid);
519 g_return_val_if_fail (comp != NULL, GNOME_Evolution_Calendar_ObjectNotFound);
521 *object = e_cal_component_get_as_string (comp);
522 g_object_unref (comp);
524 return GNOME_Evolution_Calendar_Success;
527 static ECalBackendSyncStatus
528 e_cal_backend_weather_get_object_list (ECalBackendSync *backend, EDataCal *cal, const char *sexp_string, GList **objects)
530 ECalBackendWeather *cbw = E_CAL_BACKEND_WEATHER (backend);
531 ECalBackendWeatherPrivate *priv = cbw->priv;
532 ECalBackendSExp *sexp = e_cal_backend_sexp_new (sexp_string);
533 GList *components, *l;
536 return GNOME_Evolution_Calendar_InvalidQuery;
539 components = e_cal_backend_cache_get_components (priv->cache);
540 for (l = components; l != NULL; l = g_list_next (l)) {
541 if (e_cal_backend_sexp_match_comp (sexp, E_CAL_COMPONENT (l->data), E_CAL_BACKEND (backend)))
542 *objects = g_list_append (*objects, e_cal_component_get_as_string (l->data));
545 g_list_foreach (components, (GFunc) g_object_unref, NULL);
546 g_list_free (components);
547 g_object_unref (sexp);
549 return GNOME_Evolution_Calendar_Success;
552 static ECalBackendSyncStatus
553 e_cal_backend_weather_get_timezone (ECalBackendSync *backend, EDataCal *cal, const char *tzid, char **object)
555 ECalBackendWeather *cbw;
556 ECalBackendWeatherPrivate *priv;
558 icalcomponent *icalcomp;
560 cbw = E_CAL_BACKEND_WEATHER (backend);
563 g_return_val_if_fail (tzid != NULL, GNOME_Evolution_Calendar_ObjectNotFound);
565 zone = e_cal_backend_internal_get_timezone (E_CAL_BACKEND (backend), tzid);
567 return GNOME_Evolution_Calendar_ObjectNotFound;
569 icalcomp = icaltimezone_get_component (zone);
571 return GNOME_Evolution_Calendar_InvalidObject;
573 *object = g_strdup (icalcomponent_as_ical_string (icalcomp));
575 return GNOME_Evolution_Calendar_Success;
578 static ECalBackendSyncStatus
579 e_cal_backend_weather_add_timezone (ECalBackendSync *backend, EDataCal *cal, const char *tzobj)
581 ECalBackendWeather *cbw;
582 ECalBackendWeatherPrivate *priv;
583 icalcomponent *tz_comp;
587 cbw = (ECalBackendWeather*) backend;
589 g_return_val_if_fail (E_IS_CAL_BACKEND_WEATHER (cbw), GNOME_Evolution_Calendar_OtherError);
590 g_return_val_if_fail (tzobj != NULL, GNOME_Evolution_Calendar_OtherError);
594 tz_comp = icalparser_parse_string (tzobj);
595 g_return_val_if_fail (tz_comp != NULL, GNOME_Evolution_Calendar_InvalidObject);
597 if (icalcomponent_isa (tz_comp) != ICAL_VTIMEZONE_COMPONENT)
598 return GNOME_Evolution_Calendar_InvalidObject;
600 zone = icaltimezone_new ();
601 icaltimezone_set_component (zone, tz_comp);
602 tzid = icaltimezone_get_tzid (zone);
604 if (g_hash_table_lookup (priv->zones, tzid)) {
605 icaltimezone_free (zone, TRUE);
606 return GNOME_Evolution_Calendar_Success;
609 g_hash_table_insert (priv->zones, g_strdup (tzid), zone);
610 return GNOME_Evolution_Calendar_Success;
613 static ECalBackendSyncStatus
614 e_cal_backend_weather_set_default_zone (ECalBackendSync *backend, EDataCal *cal, const char *tzobj)
616 icalcomponent *tz_comp;
617 ECalBackendWeather *cbw;
618 ECalBackendWeatherPrivate *priv;
621 cbw = (ECalBackendWeather *) backend;
623 g_return_val_if_fail (E_IS_CAL_BACKEND_WEATHER (cbw), GNOME_Evolution_Calendar_OtherError);
624 g_return_val_if_fail (tzobj != NULL, GNOME_Evolution_Calendar_OtherError);
628 tz_comp = icalparser_parse_string (tzobj);
630 return GNOME_Evolution_Calendar_InvalidObject;
632 zone = icaltimezone_new ();
633 icaltimezone_set_component (zone, tz_comp);
635 if (priv->default_zone)
636 icaltimezone_free (priv->default_zone, 1);
638 /* Set the default timezone to it. */
639 priv->default_zone = zone;
641 return GNOME_Evolution_Calendar_Success;
644 static ECalBackendSyncStatus
645 e_cal_backend_weather_get_free_busy (ECalBackendSync *backend, EDataCal *cal, GList *users, time_t start, time_t end, GList **freebusy)
647 /* Weather doesn't count as busy time */
648 icalcomponent *vfb = icalcomponent_new_vfreebusy ();
649 icaltimezone *utc_zone = icaltimezone_get_utc_timezone ();
652 icalcomponent_set_dtstart (vfb, icaltime_from_timet_with_zone (start, FALSE, utc_zone));
653 icalcomponent_set_dtend (vfb, icaltime_from_timet_with_zone (end, FALSE, utc_zone));
655 calobj = icalcomponent_as_ical_string (vfb);
656 *freebusy = g_list_append (NULL, g_strdup (calobj));
657 icalcomponent_free (vfb);
659 return GNOME_Evolution_Calendar_Success;
662 static ECalBackendSyncStatus
663 e_cal_backend_weather_get_changes (ECalBackendSync *backend, EDataCal *cal, const char *change_id, GList **adds, GList **modifies, GList **deletes)
665 return GNOME_Evolution_Calendar_Success;
669 e_cal_backend_weather_is_loaded (ECalBackend *backend)
671 ECalBackendWeather *cbw;
672 ECalBackendWeatherPrivate *priv;
674 cbw = E_CAL_BACKEND_WEATHER (backend);
683 static void e_cal_backend_weather_start_query (ECalBackend *backend, EDataCalView *query)
685 ECalBackendWeather *cbw;
686 ECalBackendWeatherPrivate *priv;
687 ECalBackendSExp *sexp;
688 GList *components, *l, *objects;
690 cbw = E_CAL_BACKEND_WEATHER (backend);
694 e_data_cal_view_notify_done (query, GNOME_Evolution_Calendar_NoSuchCal);
698 sexp = e_data_cal_view_get_object_sexp (query);
700 e_data_cal_view_notify_done (query, GNOME_Evolution_Calendar_InvalidQuery);
705 components = e_cal_backend_cache_get_components (priv->cache);
706 for (l = components; l != NULL; l = g_list_next (l)) {
707 if (e_cal_backend_sexp_match_comp (sexp, E_CAL_COMPONENT (l->data), backend))
708 objects = g_list_append (objects, e_cal_component_get_as_string (l->data));
712 e_data_cal_view_notify_objects_added (query, (const GList *) objects);
714 g_list_foreach (components, (GFunc) g_object_unref, NULL);
715 g_list_free (components);
716 g_list_foreach (objects, (GFunc) g_free, NULL);
717 g_list_free (objects);
718 g_object_unref (sexp);
720 e_data_cal_view_notify_done (query, GNOME_Evolution_Calendar_Success);
724 e_cal_backend_weather_get_mode (ECalBackend *backend)
726 ECalBackendWeather *cbw;
727 ECalBackendWeatherPrivate *priv;
729 cbw = E_CAL_BACKEND_WEATHER (backend);
736 e_cal_backend_weather_set_mode (ECalBackend *backend, CalMode mode)
738 ECalBackendWeather *cbw;
739 ECalBackendWeatherPrivate *priv;
740 GNOME_Evolution_Calendar_CalMode set_mode;
743 cbw = E_CAL_BACKEND_WEATHER (backend);
746 loaded = e_cal_backend_weather_is_loaded (backend);
750 case CAL_MODE_REMOTE:
752 set_mode = cal_mode_to_corba (mode);
753 if (loaded && priv->reload_timeout_id) {
754 g_source_remove (priv->reload_timeout_id);
755 priv->reload_timeout_id = 0;
760 set_mode = cal_mode_to_corba (mode);
762 g_idle_add ((GSourceFunc) begin_retrieval_cb, backend);
765 set_mode = GNOME_Evolution_Calendar_MODE_ANY;
770 if (set_mode == GNOME_Evolution_Calendar_MODE_ANY)
771 e_cal_backend_notify_mode (backend,
772 GNOME_Evolution_Calendar_CalListener_MODE_NOT_SUPPORTED,
773 cal_mode_to_corba (priv->mode));
775 e_cal_backend_notify_mode (backend,
776 GNOME_Evolution_Calendar_CalListener_MODE_SET,
781 static icaltimezone *
782 e_cal_backend_weather_internal_get_default_timezone (ECalBackend *backend)
784 ECalBackendWeather *cbw = E_CAL_BACKEND_WEATHER (backend);
786 return cbw->priv->default_zone;
789 static icaltimezone *
790 e_cal_backend_weather_internal_get_timezone (ECalBackend *backend, const char *tzid)
793 if (!strcmp (tzid, "UTC"))
794 zone = icaltimezone_get_utc_timezone ();
796 zone = icaltimezone_get_builtin_timezone_from_tzid (tzid);
801 free_zone (gpointer data)
803 icaltimezone_free (data, TRUE);
806 /* Finalize handler for the weather backend */
808 e_cal_backend_weather_finalize (GObject *object)
810 ECalBackendWeather *cbw;
811 ECalBackendWeatherPrivate *priv;
813 g_return_if_fail (object != NULL);
814 g_return_if_fail (E_IS_CAL_BACKEND_WEATHER (object));
816 cbw = (ECalBackendWeather *) object;
820 g_object_unref (priv->cache);
824 g_hash_table_destroy (priv->zones);
831 if (priv->default_zone) {
832 icaltimezone_free (priv->default_zone, 1);
833 priv->default_zone = NULL;
839 if (G_OBJECT_CLASS (parent_class)->finalize)
840 (* G_OBJECT_CLASS (parent_class)->finalize) (object);
843 /* Object initialization function for the weather backend */
845 e_cal_backend_weather_init (ECalBackendWeather *cbw, ECalBackendWeatherClass *class)
847 ECalBackendWeatherPrivate *priv;
849 priv = g_new0 (ECalBackendWeatherPrivate, 1);
853 priv->reload_timeout_id = 0;
854 priv->source_changed_id = 0;
855 priv->opened = FALSE;
860 priv->zones = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, free_zone);
862 e_cal_backend_sync_set_lock (E_CAL_BACKEND_SYNC (cbw), TRUE);
865 /* Class initialization function for the weather backend */
867 e_cal_backend_weather_class_init (ECalBackendWeatherClass *class)
869 GObjectClass *object_class;
870 ECalBackendClass *backend_class;
871 ECalBackendSyncClass *sync_class;
873 object_class = (GObjectClass *) class;
874 backend_class = (ECalBackendClass *) class;
875 sync_class = (ECalBackendSyncClass *) class;
877 parent_class = (ECalBackendSyncClass *) g_type_class_peek_parent (class);
879 object_class->finalize = e_cal_backend_weather_finalize;
881 sync_class->is_read_only_sync = e_cal_backend_weather_is_read_only;
882 sync_class->get_cal_address_sync = e_cal_backend_weather_get_cal_address;
883 sync_class->get_alarm_email_address_sync = e_cal_backend_weather_get_alarm_email_address;
884 sync_class->get_ldap_attribute_sync = e_cal_backend_weather_get_ldap_attribute;
885 sync_class->get_static_capabilities_sync = e_cal_backend_weather_get_static_capabilities;
886 sync_class->open_sync = e_cal_backend_weather_open;
887 sync_class->remove_sync = e_cal_backend_weather_remove;
888 sync_class->discard_alarm_sync = e_cal_backend_weather_discard_alarm;
889 sync_class->receive_objects_sync = e_cal_backend_weather_receive_objects;
890 sync_class->get_default_object_sync = e_cal_backend_weather_get_default_object;
891 sync_class->get_object_sync = e_cal_backend_weather_get_object;
892 sync_class->get_object_list_sync = e_cal_backend_weather_get_object_list;
893 sync_class->get_timezone_sync = e_cal_backend_weather_get_timezone;
894 sync_class->add_timezone_sync = e_cal_backend_weather_add_timezone;
895 sync_class->set_default_zone_sync = e_cal_backend_weather_set_default_zone;
896 sync_class->get_freebusy_sync = e_cal_backend_weather_get_free_busy;
897 sync_class->get_changes_sync = e_cal_backend_weather_get_changes;
898 backend_class->is_loaded = e_cal_backend_weather_is_loaded;
899 backend_class->start_query = e_cal_backend_weather_start_query;
900 backend_class->get_mode = e_cal_backend_weather_get_mode;
901 backend_class->set_mode = e_cal_backend_weather_set_mode;
903 backend_class->internal_get_default_timezone = e_cal_backend_weather_internal_get_default_timezone;
904 backend_class->internal_get_timezone = e_cal_backend_weather_internal_get_timezone;
909 * e_cal_backend_weather_get_type:
912 * Registers the #ECalBackendWeather class if necessary, and returns
913 * the type ID associated to it.
915 * Return value: The type ID of the #ECalBackendWeather class.
918 e_cal_backend_weather_get_type (void)
920 static GType e_cal_backend_weather_type = 0;
922 if (!e_cal_backend_weather_type) {
923 static GTypeInfo info = {
924 sizeof (ECalBackendWeatherClass),
925 (GBaseInitFunc) NULL,
926 (GBaseFinalizeFunc) NULL,
927 (GClassInitFunc) e_cal_backend_weather_class_init,
929 sizeof (ECalBackendWeather),
931 (GInstanceInitFunc) e_cal_backend_weather_init
933 e_cal_backend_weather_type = g_type_register_static (E_TYPE_CAL_BACKEND_SYNC, "ECalBackendWeather", &info, 0);
936 return e_cal_backend_weather_type;