1 /*-*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /* Evolution calendar ecal
4 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
5 * Copyright (C) 2009 Intel Corporation
7 * Authors: Federico Mena-Quintero <federico@ximian.com>
8 * Rodrigo Moya <rodrigo@novell.com>
9 * Ross Burton <ross@linux.intel.com>
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of version 2 of the GNU Lesser General Public
13 * License as published by the Free Software Foundation.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
28 * The old signal "cal-opened" is deprecated since 3.0 and is replaced with
29 * its equivalent "cal_opened_ex", which has a detailed #GError structure
30 * as a parameter, instead of a status code only.
32 * Deprecated: 3.2: Use #ECalClient instead.
41 #include <glib/gi18n-lib.h>
43 #include <libical/ical.h>
44 #include <libedataserver/e-url.h>
45 #include <libedataserver/e-data-server-util.h>
46 #include <libedataserver/e-source-calendar.h>
47 #include <libedataserver/e-source-registry.h>
49 #include "libedata-cal/e-data-cal-types.h"
51 #include "e-cal-check-timezones.h"
52 #include "e-cal-marshal.h"
53 #include "e-cal-time-util.h"
54 #include "e-cal-view-private.h"
57 #include "e-gdbus-cal.h"
58 #include "e-gdbus-cal-view.h"
59 #include "e-gdbus-cal-factory.h"
61 #define E_CAL_GET_PRIVATE(obj) \
62 (G_TYPE_INSTANCE_GET_PRIVATE \
63 ((obj), E_TYPE_CAL, ECalPrivate))
65 #define CLIENT_BACKEND_PROPERTY_CACHE_DIR "cache-dir"
66 #define CLIENT_BACKEND_PROPERTY_CAPABILITIES "capabilities"
67 #define CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS "cal-email-address"
68 #define CAL_BACKEND_PROPERTY_ALARM_EMAIL_ADDRESS "alarm-email-address"
69 #define CAL_BACKEND_PROPERTY_DEFAULT_OBJECT "default-object"
71 static guint active_cals = 0, cal_connection_closed_id = 0;
72 static EGdbusCalFactory *cal_factory_proxy = NULL;
73 static GStaticRecMutex cal_factory_proxy_lock = G_STATIC_REC_MUTEX_INIT;
74 #define LOCK_FACTORY() g_static_rec_mutex_lock (&cal_factory_proxy_lock)
75 #define UNLOCK_FACTORY() g_static_rec_mutex_unlock (&cal_factory_proxy_lock)
77 #define LOCK_CACHE() g_static_rec_mutex_lock (&priv->cache_lock)
78 #define UNLOCK_CACHE() g_static_rec_mutex_unlock (&priv->cache_lock)
80 G_DEFINE_TYPE (ECal, e_cal, G_TYPE_OBJECT)
82 static gboolean open_calendar (ECal *ecal, gboolean only_if_exists, GError **error,
83 ECalendarStatus *status,
85 static void e_cal_dispose (GObject *object);
86 static void e_cal_finalize (GObject *object);
88 /* Private part of the ECal structure */
90 GDBusProxy *gdbus_cal;
93 /* Load state to avoid multiple loads */
94 ECalLoadState load_state;
99 /* Email address associated with this calendar, or NULL */
101 gchar *alarm_email_address;
102 gchar *ldap_attribute;
104 /* Scheduling info */
111 /* A cache of timezones retrieved from the server, to avoid getting
112 * them repeatedly for each get_object () call. */
113 GHashTable *timezones;
115 /* The default timezone to use to resolve DATE and floating DATE-TIME
117 icaltimezone *default_zone;
119 gchar *local_attachment_store;
121 /* For locking the operation while localling cache values like
122 * static capabilities, cal address etc. */
123 GStaticRecMutex cache_lock;
125 GList **free_busy_data;
126 GMutex *free_busy_data_lock;
141 static guint e_cal_signals[LAST_SIGNAL];
143 #ifdef __PRETTY_FUNCTION__
144 #define e_return_error_if_fail(expr,error_code) G_STMT_START{ \
145 if G_LIKELY (expr) { } else \
147 g_log (G_LOG_DOMAIN, \
148 G_LOG_LEVEL_CRITICAL, \
149 "file %s: line %d (%s): assertion `%s' failed", \
152 __PRETTY_FUNCTION__, \
154 g_set_error (error, E_CALENDAR_ERROR, (error_code), \
155 "file %s: line %d (%s): assertion `%s' failed", \
158 __PRETTY_FUNCTION__, \
163 #define e_return_error_if_fail(expr,error_code) G_STMT_START{ \
164 if G_LIKELY (expr) { } else \
166 g_log (G_LOG_DOMAIN, \
167 G_LOG_LEVEL_CRITICAL, \
168 "file %s: line %d: assertion `%s' failed", \
172 g_set_error (error, E_CALENDAR_ERROR, (error_code), \
173 "file %s: line %d: assertion `%s' failed", \
181 #define E_CALENDAR_CHECK_STATUS(status,error) \
183 if ((status) == E_CALENDAR_STATUS_OK) \
187 if (error && *error) \
188 return unwrap_gerror (error); \
189 msg = e_cal_get_error_message ((status)); \
190 g_set_error ((error), E_CALENDAR_ERROR, (status), "%s", msg); \
199 e_calendar_error_quark (void)
203 q = g_quark_from_static_string ("e-calendar-error-quark");
209 * If the GError is a remote error, extract the EBookStatus embedded inside.
210 * Otherwise return CORBA_EXCEPTION (I know this is DBus...).
212 static ECalendarStatus
213 get_status_from_error (const GError *error)
215 #define err(a,b) "org.gnome.evolution.dataserver.Calendar." a, b
218 ECalendarStatus err_code;
220 { err ("Success", E_CALENDAR_STATUS_OK) },
221 { err ("Busy", E_CALENDAR_STATUS_BUSY) },
222 { err ("RepositoryOffline", E_CALENDAR_STATUS_REPOSITORY_OFFLINE) },
223 { err ("PermissionDenied", E_CALENDAR_STATUS_PERMISSION_DENIED) },
224 { err ("InvalidRange", E_CALENDAR_STATUS_OTHER_ERROR) },
225 { err ("ObjectNotFound", E_CALENDAR_STATUS_OBJECT_NOT_FOUND) },
226 { err ("InvalidObject", E_CALENDAR_STATUS_INVALID_OBJECT) },
227 { err ("ObjectIdAlreadyExists", E_CALENDAR_STATUS_OBJECT_ID_ALREADY_EXISTS) },
228 { err ("AuthenticationFailed", E_CALENDAR_STATUS_AUTHENTICATION_FAILED) },
229 { err ("AuthenticationRequired", E_CALENDAR_STATUS_AUTHENTICATION_REQUIRED) },
230 { err ("UnsupportedField", E_CALENDAR_STATUS_OTHER_ERROR) },
231 { err ("UnsupportedMethod", E_CALENDAR_STATUS_OTHER_ERROR) },
232 { err ("UnsupportedAuthenticationMethod", E_CALENDAR_STATUS_OTHER_ERROR) },
233 { err ("TLSNotAvailable", E_CALENDAR_STATUS_OTHER_ERROR) },
234 { err ("NoSuchCal", E_CALENDAR_STATUS_NO_SUCH_CALENDAR) },
235 { err ("UnknownUser", E_CALENDAR_STATUS_UNKNOWN_USER) },
236 { err ("OfflineUnavailable", E_CALENDAR_STATUS_OTHER_ERROR) },
237 { err ("SearchSizeLimitExceeded", E_CALENDAR_STATUS_OTHER_ERROR) },
238 { err ("SearchTimeLimitExceeded", E_CALENDAR_STATUS_OTHER_ERROR) },
239 { err ("InvalidQuery", E_CALENDAR_STATUS_OTHER_ERROR) },
240 { err ("QueryRefused", E_CALENDAR_STATUS_OTHER_ERROR) },
241 { err ("CouldNotCancel", E_CALENDAR_STATUS_COULD_NOT_CANCEL) },
242 { err ("OtherError", E_CALENDAR_STATUS_OTHER_ERROR) },
243 { err ("InvalidServerVersion", E_CALENDAR_STATUS_INVALID_SERVER_VERSION) },
244 { err ("InvalidArg", E_CALENDAR_STATUS_INVALID_ARG) },
245 { err ("NotSupported", E_CALENDAR_STATUS_NOT_SUPPORTED) }
249 if G_LIKELY (error == NULL)
252 if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_DBUS_ERROR)) {
256 name = g_dbus_error_get_remote_error (error);
258 for (i = 0; i < G_N_ELEMENTS (errors); i++) {
259 if (g_ascii_strcasecmp (errors[i].name, name) == 0) {
261 return errors[i].err_code;
265 g_warning ("Unmatched error name %s", name);
268 return E_CALENDAR_STATUS_OTHER_ERROR;
269 } else if (error->domain == E_CALENDAR_ERROR) {
272 /* In this case the error was caused by DBus */
273 return E_CALENDAR_STATUS_DBUS_EXCEPTION;
278 * If the specified GError is a remote error, then create a new error
279 * representing the remote error. If the error is anything else, then leave it
283 unwrap_gerror (GError **error)
288 if (g_error_matches (*error, G_IO_ERROR, G_IO_ERROR_DBUS_ERROR)) {
289 GError *new_error = NULL;
292 code = get_status_from_error (*error);
293 g_dbus_error_strip_remote_error (*error);
295 new_error = g_error_new_literal (E_CALENDAR_ERROR, code, (*error)->message);
297 g_error_free (*error);
305 * e_cal_source_type_enum_get_type:
307 * Registers the #ECalSourceTypeEnum type with glib.
309 * Returns: the ID of the #ECalSourceTypeEnum type.
311 * Deprecated: 3.2: Use e_cal_client_source_type_enum_get_type() instead.
314 e_cal_source_type_enum_get_type (void)
316 static volatile gsize enum_type__volatile = 0;
318 if (g_once_init_enter (&enum_type__volatile)) {
320 static GEnumValue values[] = {
321 { E_CAL_SOURCE_TYPE_EVENT, "Event", "Event"},
322 { E_CAL_SOURCE_TYPE_TODO, "ToDo", "ToDo"},
323 { E_CAL_SOURCE_TYPE_JOURNAL, "Journal", "Journal"},
324 { E_CAL_SOURCE_TYPE_LAST, "Invalid", "Invalid"},
328 enum_type = g_enum_register_static ("ECalSourceTypeEnum", values);
329 g_once_init_leave (&enum_type__volatile, enum_type);
332 return enum_type__volatile;
336 * e_cal_set_mode_status_enum_get_type:
338 * Registers the #ECalSetModeStatusEnum type with glib.
340 * Returns: the ID of the #ECalSetModeStatusEnum type.
342 * Deprecated: 3.2: This type has been dropped completely.
345 e_cal_set_mode_status_enum_get_type (void)
347 static volatile gsize enum_type__volatile = 0;
349 if (g_once_init_enter (&enum_type__volatile)) {
351 static GEnumValue values[] = {
352 { E_CAL_SET_MODE_SUCCESS, "ECalSetModeSuccess", "success" },
353 { E_CAL_SET_MODE_ERROR, "ECalSetModeError", "error" },
354 { E_CAL_SET_MODE_NOT_SUPPORTED, "ECalSetModeNotSupported", "unsupported" },
358 enum_type = g_enum_register_static ("ECalSetModeStatusEnum", values);
359 g_once_init_leave (&enum_type__volatile, enum_type);
362 return enum_type__volatile;
366 * cal_mode_enum_get_type:
368 * Registers the #CalModeEnum type with glib.
370 * Returns: the ID of the #CalModeEnum type.
372 * Deprecated: 3.2: This type has been dropped completely.
375 cal_mode_enum_get_type (void)
377 static volatile gsize enum_type__volatile = 0;
379 if (g_once_init_enter (&enum_type__volatile)) {
381 static GEnumValue values[] = {
382 { CAL_MODE_INVALID, "CalModeInvalid", "invalid" },
383 { CAL_MODE_LOCAL, "CalModeLocal", "local" },
384 { CAL_MODE_REMOTE, "CalModeRemote", "remote" },
385 { CAL_MODE_ANY, "CalModeAny", "any" },
389 enum_type = g_enum_register_static ("CalModeEnum", values);
390 g_once_init_leave (&enum_type__volatile, enum_type);
393 return enum_type__volatile;
396 static EDataCalObjType
397 convert_type (ECalSourceType type)
400 case E_CAL_SOURCE_TYPE_EVENT:
402 case E_CAL_SOURCE_TYPE_TODO:
404 case E_CAL_SOURCE_TYPE_JOURNAL:
414 e_cal_init (ECal *ecal)
420 ecal->priv = E_CAL_GET_PRIVATE (ecal);
422 ecal->priv->load_state = E_CAL_LOAD_NOT_LOADED;
423 ecal->priv->local_attachment_store = NULL;
425 ecal->priv->cal_address = NULL;
426 ecal->priv->alarm_email_address = NULL;
427 ecal->priv->ldap_attribute = NULL;
428 ecal->priv->capabilities = NULL;
429 ecal->priv->gdbus_cal = NULL;
430 ecal->priv->timezones = g_hash_table_new (g_str_hash, g_str_equal);
431 ecal->priv->default_zone = icaltimezone_get_utc_timezone ();
432 ecal->priv->free_busy_data_lock = g_mutex_new ();
433 g_static_rec_mutex_init (&ecal->priv->cache_lock);
437 gdbus_cal_disconnect (ECal *ecal);
440 * Called when the calendar server dies.
443 gdbus_cal_closed_cb (GDBusConnection *connection,
444 gboolean remote_peer_vanished,
450 g_return_if_fail (E_IS_CAL (ecal));
453 err = g_error_copy (error);
454 unwrap_gerror (&err);
458 g_debug (G_STRLOC ": ECal GDBus connection is closed%s: %s", remote_peer_vanished ? ", remote peer vanished" : "", err->message);
461 g_debug (G_STRLOC ": ECal GDBus connection is closed%s", remote_peer_vanished ? ", remote peer vanished" : "");
464 gdbus_cal_disconnect (ecal);
466 g_signal_emit (G_OBJECT (ecal), e_cal_signals[BACKEND_DIED], 0);
470 gdbus_cal_connection_gone_cb (GDBusConnection *connection,
471 const gchar *sender_name,
472 const gchar *object_path,
473 const gchar *interface_name,
474 const gchar *signal_name,
475 GVariant *parameters,
478 /* signal subscription takes care of correct parameters,
479 * thus just do what is to be done here */
480 gdbus_cal_closed_cb (connection, TRUE, NULL, user_data);
484 gdbus_cal_disconnect (ECal *ecal)
486 /* Ensure that everything relevant is NULL */
489 if (ecal->priv->gdbus_cal) {
490 GError *error = NULL;
491 GDBusConnection *connection = g_dbus_proxy_get_connection (G_DBUS_PROXY (ecal->priv->gdbus_cal));
493 g_signal_handlers_disconnect_by_func (connection, gdbus_cal_closed_cb, ecal);
494 g_dbus_connection_signal_unsubscribe (connection, ecal->priv->gone_signal_id);
495 ecal->priv->gone_signal_id = 0;
497 e_gdbus_cal_call_close_sync (ecal->priv->gdbus_cal, NULL, &error);
498 g_object_unref (ecal->priv->gdbus_cal);
499 ecal->priv->gdbus_cal = NULL;
502 unwrap_gerror (&error);
504 g_warning ("%s: Failed to close calendar, %s\n", G_STRFUNC, error->message);
505 g_error_free (error);
511 /* Dispose handler for the calendar ecal */
513 e_cal_dispose (GObject *object)
515 ECal *ecal = E_CAL (object);
517 gdbus_cal_disconnect (ecal);
519 /* Chain up to parent's dispose() method. */
520 G_OBJECT_CLASS (e_cal_parent_class)->dispose (object);
524 free_timezone (gpointer key,
528 /* Note that the key comes from within the icaltimezone value, so we
529 * don't free that. */
530 icaltimezone_free (value, TRUE);
533 /* Finalize handler for the calendar ecal */
535 e_cal_finalize (GObject *object)
540 g_return_if_fail (object != NULL);
541 g_return_if_fail (E_IS_CAL (object));
543 ecal = E_CAL (object);
546 priv->load_state = E_CAL_LOAD_NOT_LOADED;
549 g_object_unref (priv->source);
553 if (priv->local_attachment_store) {
554 g_free (priv->local_attachment_store);
555 priv->local_attachment_store = NULL;
558 if (priv->cal_address) {
559 g_free (priv->cal_address);
560 priv->cal_address = NULL;
562 if (priv->alarm_email_address) {
563 g_free (priv->alarm_email_address);
564 priv->alarm_email_address = NULL;
566 if (priv->ldap_attribute) {
567 g_free (priv->ldap_attribute);
568 priv->ldap_attribute = NULL;
570 if (priv->capabilities) {
571 g_free (priv->capabilities);
572 priv->capabilities = NULL;
575 if (priv->free_busy_data) {
576 g_mutex_lock (priv->free_busy_data_lock);
577 g_list_foreach (*priv->free_busy_data, (GFunc) g_object_unref, NULL);
578 g_list_free (*priv->free_busy_data);
579 *priv->free_busy_data = NULL;
580 priv->free_busy_data = NULL;
581 g_mutex_unlock (priv->free_busy_data_lock);
584 g_hash_table_foreach (priv->timezones, free_timezone, NULL);
585 g_hash_table_destroy (priv->timezones);
586 priv->timezones = NULL;
587 g_static_rec_mutex_free (&priv->cache_lock);
588 g_mutex_free (priv->free_busy_data_lock);
590 /* Chain up to parent's finalize() method. */
591 G_OBJECT_CLASS (e_cal_parent_class)->finalize (object);
598 /* Class initialization function for the calendar ecal */
600 e_cal_class_init (ECalClass *class)
602 GObjectClass *object_class;
604 object_class = (GObjectClass *) class;
606 /* XXX The "cal-opened" signal is deprecated. */
607 e_cal_signals[CAL_OPENED] =
608 g_signal_new ("cal_opened",
609 G_TYPE_FROM_CLASS (class),
611 G_STRUCT_OFFSET (ECalClass, cal_opened),
613 g_cclosure_marshal_VOID__INT,
614 G_TYPE_NONE, 1, G_TYPE_INT);
617 * ECal::cal-opened-ex:
619 * @error: (type glong):
621 e_cal_signals[CAL_OPENED_EX] =
622 g_signal_new ("cal_opened_ex",
623 G_TYPE_FROM_CLASS (class),
625 G_STRUCT_OFFSET (ECalClass, cal_opened_ex),
627 g_cclosure_marshal_VOID__POINTER,
628 G_TYPE_NONE, 1, G_TYPE_POINTER);
630 e_cal_signals[CAL_SET_MODE] =
631 g_signal_new ("cal_set_mode",
632 G_TYPE_FROM_CLASS (class),
634 G_STRUCT_OFFSET (ECalClass, cal_set_mode),
636 e_cal_marshal_VOID__ENUM_ENUM,
638 E_CAL_SET_MODE_STATUS_ENUM_TYPE,
640 e_cal_signals[BACKEND_ERROR] =
641 g_signal_new ("backend_error",
642 G_TYPE_FROM_CLASS (class),
644 G_STRUCT_OFFSET (ECalClass, backend_error),
646 g_cclosure_marshal_VOID__STRING,
649 e_cal_signals[BACKEND_DIED] =
650 g_signal_new ("backend_died",
651 G_TYPE_FROM_CLASS (class),
653 G_STRUCT_OFFSET (ECalClass, backend_died),
655 g_cclosure_marshal_VOID__VOID,
658 class->cal_opened = NULL;
659 class->cal_opened_ex = NULL;
660 class->backend_died = NULL;
662 object_class->dispose = e_cal_dispose;
663 object_class->finalize = e_cal_finalize;
665 g_type_class_add_private (class, sizeof (ECalPrivate));
669 cal_factory_proxy_closed_cb (GDBusConnection *connection,
670 gboolean remote_peer_vanished,
678 if (cal_connection_closed_id) {
679 g_dbus_connection_signal_unsubscribe (connection, cal_connection_closed_id);
680 cal_connection_closed_id = 0;
681 g_signal_handlers_disconnect_by_func (connection, cal_factory_proxy_closed_cb, NULL);
684 if (cal_factory_proxy) {
685 g_object_unref (cal_factory_proxy);
686 cal_factory_proxy = NULL;
690 err = g_error_copy (error);
691 unwrap_gerror (&err);
695 g_debug ("GDBus connection is closed%s: %s", remote_peer_vanished ? ", remote peer vanished" : "", err->message);
697 } else if (active_cals) {
698 g_debug ("GDBus connection is closed%s", remote_peer_vanished ? ", remote peer vanished" : "");
705 cal_factory_connection_gone_cb (GDBusConnection *connection,
706 const gchar *sender_name,
707 const gchar *object_path,
708 const gchar *interface_name,
709 const gchar *signal_name,
710 GVariant *parameters,
713 /* signal subscription takes care of correct parameters,
714 * thus just do what is to be done here */
715 cal_factory_proxy_closed_cb (connection, TRUE, NULL, user_data);
718 /* one-time start up for libecal */
720 e_cal_activate (GError **error)
722 GDBusConnection *connection;
725 if (G_LIKELY (cal_factory_proxy)) {
730 cal_factory_proxy = e_gdbus_cal_factory_proxy_new_for_bus_sync (
732 G_DBUS_PROXY_FLAGS_NONE,
733 CALENDAR_DBUS_SERVICE_NAME,
734 "/org/gnome/evolution/dataserver/CalendarFactory",
738 if (!cal_factory_proxy) {
743 connection = g_dbus_proxy_get_connection (G_DBUS_PROXY (cal_factory_proxy));
744 cal_connection_closed_id = g_dbus_connection_signal_subscribe (connection,
746 "org.freedesktop.DBus", /* interface */
747 "NameOwnerChanged", /* member */
748 "/org/freedesktop/DBus", /* object_path */
749 CALENDAR_DBUS_SERVICE_NAME, /* arg0 */
750 G_DBUS_SIGNAL_FLAGS_NONE,
751 cal_factory_connection_gone_cb, NULL, NULL);
753 g_signal_connect (connection, "closed", G_CALLBACK (cal_factory_proxy_closed_cb), NULL);
760 static void async_open_report_result (ECal *ecal, const GError *error);
763 free_busy_data_cb (EGdbusCal *gdbus_cal,
764 const gchar * const *free_busy_strv,
769 g_return_if_fail (E_IS_CAL (cal));
773 g_mutex_lock (priv->free_busy_data_lock);
775 if (priv->free_busy_data) {
777 GList *list = *priv->free_busy_data;
779 for (ii = 0; free_busy_strv[ii]; ii++) {
781 icalcomponent *icalcomp;
782 icalcomponent_kind kind;
784 icalcomp = icalcomponent_new_from_string (free_busy_strv[ii]);
788 kind = icalcomponent_isa (icalcomp);
789 if (kind == ICAL_VFREEBUSY_COMPONENT) {
790 comp = e_cal_component_new ();
791 if (!e_cal_component_set_icalcomponent (comp, icalcomp)) {
792 icalcomponent_free (icalcomp);
793 g_object_unref (G_OBJECT (comp));
797 list = g_list_append (list, comp);
799 icalcomponent_free (icalcomp);
803 *priv->free_busy_data = list;
806 g_mutex_unlock (priv->free_busy_data_lock);
816 backend_error_idle_cb (gpointer data)
818 ECalErrorData *error_data = data;
820 g_signal_emit (G_OBJECT (error_data->ecal), e_cal_signals[BACKEND_ERROR], 0, error_data->message);
822 g_object_unref (error_data->ecal);
823 g_free (error_data->message);
829 /* Handle the error_occurred signal from the listener */
831 backend_error_cb (EGdbusCal *gdbus_cal,
832 const gchar *message,
835 ECalErrorData *error_data;
837 g_return_if_fail (E_IS_CAL (ecal));
839 error_data = g_new0 (ECalErrorData, 1);
841 error_data->ecal = g_object_ref (ecal);
842 error_data->message = g_strdup (message);
844 g_idle_add (backend_error_idle_cb, error_data);
848 readonly_cb (EGdbusCal *gdbus_cal,
854 g_return_if_fail (cal && E_IS_CAL (cal));
857 priv->read_only = read_only;
861 online_cb (EGdbusCal *gdbus_cal,
865 g_return_if_fail (E_IS_CAL (cal));
867 g_signal_emit (G_OBJECT (cal), e_cal_signals[CAL_SET_MODE],
868 0, E_CALENDAR_STATUS_OK, is_online ? Remote : Local);
873 backend_died_cb (EComponentListener *cl,
874 * gpointer user_data)
877 ECal *ecal = (ECal *) user_data;
880 priv->load_state = E_CAL_LOAD_NOT_LOADED;
881 g_signal_emit (G_OBJECT (ecal), e_cal_signals[BACKEND_DIED], 0);
885 set_local_attachment_store (ECal *ecal)
887 gchar *cache_dir = NULL;
888 GError *error = NULL;
890 e_gdbus_cal_call_get_backend_property_sync (
891 ecal->priv->gdbus_cal, CLIENT_BACKEND_PROPERTY_CACHE_DIR, &cache_dir, NULL, &error);
894 ecal->priv->local_attachment_store = cache_dir;
896 unwrap_gerror (&error);
897 g_warning ("%s", error->message);
898 g_error_free (error);
904 * @source: An #ESource to be used for the client.
905 * @type: Type of the client.
907 * Creates a new calendar client. This does not open the calendar itself,
908 * for that, #e_cal_open or #e_cal_open_async needs to be called.
910 * Returns: A newly-created calendar client, or NULL if the client could
911 * not be constructed because it could not contact the calendar server.
913 * Deprecated: 3.2: Use e_cal_client_new() instead.
916 e_cal_new (ESource *source,
924 GError *error = NULL;
925 GDBusConnection *connection;
927 g_return_val_if_fail (source && E_IS_SOURCE (source), NULL);
928 g_return_val_if_fail (type < E_CAL_SOURCE_TYPE_LAST, NULL);
930 if (!e_cal_activate (&error)) {
931 unwrap_gerror (&error);
932 g_warning("Cannot activate ECal: %s\n", error ? error->message : "Unknown error");
934 g_error_free (error);
938 ecal = g_object_new (E_TYPE_CAL, NULL);
941 priv->source = g_object_ref (source);
944 uid = e_source_get_uid (source);
945 strv = e_gdbus_cal_factory_encode_get_cal (uid, convert_type (priv->type));
947 if (!e_gdbus_cal_factory_call_get_cal_sync (G_DBUS_PROXY (cal_factory_proxy), (const gchar * const *) strv, &path, NULL, &error)) {
949 unwrap_gerror (&error);
950 g_warning ("Cannot get cal from factory: %s", error ? error->message : "Unknown error");
952 g_error_free (error);
953 g_object_unref (ecal);
958 priv->gdbus_cal = G_DBUS_PROXY (e_gdbus_cal_proxy_new_sync (g_dbus_proxy_get_connection (G_DBUS_PROXY (cal_factory_proxy)),
959 G_DBUS_PROXY_FLAGS_NONE,
960 CALENDAR_DBUS_SERVICE_NAME,
965 if (!priv->gdbus_cal) {
967 unwrap_gerror (&error);
968 g_warning ("Cannot create cal proxy: %s", error ? error->message : "Unknown error");
970 g_error_free (error);
971 g_object_unref (ecal);
975 connection = g_dbus_proxy_get_connection (G_DBUS_PROXY (priv->gdbus_cal));
976 priv->gone_signal_id = g_dbus_connection_signal_subscribe (connection,
977 "org.freedesktop.DBus", /* sender */
978 "org.freedesktop.DBus", /* interface */
979 "NameOwnerChanged", /* member */
980 "/org/freedesktop/DBus", /* object_path */
981 CALENDAR_DBUS_SERVICE_NAME, /* arg0 */
982 G_DBUS_SIGNAL_FLAGS_NONE,
983 gdbus_cal_connection_gone_cb, ecal, NULL);
984 g_signal_connect (connection, "closed", G_CALLBACK (gdbus_cal_closed_cb), ecal);
986 g_signal_connect (priv->gdbus_cal, "backend-error", G_CALLBACK (backend_error_cb), ecal);
987 g_signal_connect (priv->gdbus_cal, "readonly", G_CALLBACK (readonly_cb), ecal);
988 g_signal_connect (priv->gdbus_cal, "online", G_CALLBACK (online_cb), ecal);
989 g_signal_connect (priv->gdbus_cal, "free-busy-data", G_CALLBACK (free_busy_data_cb), ecal);
991 /* Set the local attachment store path for the calendar */
992 set_local_attachment_store (ecal);
1000 async_open_report_result (ECal *ecal,
1001 const GError *error)
1003 ECalendarStatus status;
1005 g_return_if_fail (ecal && E_IS_CAL (ecal));
1008 ecal->priv->load_state = E_CAL_LOAD_LOADED;
1011 status = get_status_from_error (error);
1013 status = E_CALENDAR_STATUS_OK;
1016 g_signal_emit (G_OBJECT (ecal), e_cal_signals[CAL_OPENED], 0, status);
1017 g_signal_emit (G_OBJECT (ecal), e_cal_signals[CAL_OPENED_EX], 0, error);
1021 async_open_ready_cb (GDBusProxy *gdbus_cal,
1025 GError *error = NULL;
1027 g_return_if_fail (ecal && E_IS_CAL (ecal));
1029 e_gdbus_cal_call_open_finish (gdbus_cal, res, &error);
1031 unwrap_gerror (&error);
1033 async_open_report_result (ecal, error);
1036 g_error_free (error);
1040 open_calendar (ECal *ecal,
1041 gboolean only_if_exists,
1043 ECalendarStatus *status,
1048 g_return_val_if_fail (error != NULL, FALSE);
1050 e_return_error_if_fail (ecal != NULL, E_CALENDAR_STATUS_INVALID_ARG);
1051 e_return_error_if_fail (E_IS_CAL (ecal), E_CALENDAR_STATUS_INVALID_ARG);
1053 e_return_error_if_fail (priv->gdbus_cal, E_CALENDAR_STATUS_REPOSITORY_OFFLINE);
1055 if (priv->load_state == E_CAL_LOAD_LOADED)
1058 priv->load_state = E_CAL_LOAD_LOADING;
1060 *status = E_CALENDAR_STATUS_OK;
1062 if (!e_gdbus_cal_call_open_sync (priv->gdbus_cal, only_if_exists, NULL, error)) {
1063 *status = E_CALENDAR_STATUS_DBUS_EXCEPTION;
1066 priv->load_state = E_CAL_LOAD_LOADED;
1068 e_gdbus_cal_call_open (priv->gdbus_cal, only_if_exists, NULL, (GAsyncReadyCallback) async_open_ready_cb, ecal);
1072 unwrap_gerror (error);
1073 priv->load_state = E_CAL_LOAD_NOT_LOADED;
1076 return *error == NULL;
1081 * @ecal: A calendar client.
1082 * @only_if_exists: FALSE if the calendar should be opened even if there
1083 * was no storage for it, i.e. to create a new calendar or load an existing
1084 * one if it already exists. TRUE if it should only try to load calendars
1085 * that already exist.
1086 * @error: Placeholder for error information.
1088 * Makes a calendar client initiate a request to open a calendar. The calendar
1089 * client will emit the "cal_opened" signal when the response from the server is
1090 * received. Since 3.0 is emitted also "cal_opened_ex" signal, which contains
1091 * a GError pointer from the open operation (NULL when no error occurred).
1092 * New signal deprecates the old "cal_opened" signal.
1094 * Returns: TRUE on success, FALSE on failure to issue the open request.
1096 * Deprecated: 3.2: Use e_client_open_sync() on an #ECalClient object instead.
1099 e_cal_open (ECal *ecal,
1100 gboolean only_if_exists,
1103 ECalendarStatus status;
1107 result = open_calendar (ecal, only_if_exists, &err, &status, FALSE);
1108 g_signal_emit (G_OBJECT (ecal), e_cal_signals[CAL_OPENED], 0, status);
1109 g_signal_emit (G_OBJECT (ecal), e_cal_signals[CAL_OPENED_EX], 0, err);
1112 g_propagate_error (error, err);
1117 struct idle_async_error_reply_data
1119 ECal *ecal; /* ref-ed */
1120 GError *error; /* can be NULL */
1124 idle_async_error_reply_cb (gpointer user_data)
1126 struct idle_async_error_reply_data *data = user_data;
1128 g_return_val_if_fail (data != NULL, FALSE);
1129 g_return_val_if_fail (data->ecal != NULL, FALSE);
1131 async_open_report_result (data->ecal, data->error);
1133 g_object_unref (data->ecal);
1135 g_error_free (data->error);
1141 /* takes ownership of error */
1143 async_report_idle (ECal *ecal,
1146 struct idle_async_error_reply_data *data;
1148 g_return_if_fail (ecal != NULL);
1150 data = g_new0 (struct idle_async_error_reply_data, 1);
1151 data->ecal = g_object_ref (ecal);
1152 data->error = error;
1154 g_idle_add (idle_async_error_reply_cb, data);
1159 * @ecal: A calendar client.
1160 * @only_if_exists: If TRUE, then only open the calendar if it already
1161 * exists. If FALSE, then create a new calendar if it doesn't already
1164 * Open the calendar asynchronously. The calendar will emit the
1165 * "cal_opened" signal when the operation has completed.
1166 * Since 3.0 is emitted also "cal_opened_ex" signal, which contains
1167 * a GError pointer from the open operation (NULL when no error occurred).
1168 * New signal deprecates the old "cal_opened" signal.
1170 * Deprecated: 3.2: Use e_client_open()/e_client_open_finish()
1171 * on an #ECalClient object instead.
1174 e_cal_open_async (ECal *ecal,
1175 gboolean only_if_exists)
1178 GError *error = NULL;
1179 ECalendarStatus status;
1181 g_return_if_fail (ecal != NULL);
1182 g_return_if_fail (E_IS_CAL (ecal));
1186 switch (priv->load_state) {
1187 case E_CAL_LOAD_LOADING :
1188 async_report_idle (ecal, g_error_new_literal (E_CALENDAR_ERROR, E_CALENDAR_STATUS_BUSY, e_cal_get_error_message (E_CALENDAR_STATUS_BUSY)));
1190 case E_CAL_LOAD_LOADED :
1191 async_report_idle (ecal, NULL /* success */);
1194 /* ignore everything else */
1198 open_calendar (ecal, only_if_exists, &error, &status, TRUE);
1201 async_report_idle (ecal, error);
1206 * @ecal: A calendar client.
1207 * @error: Placeholder for error information.
1209 * Invokes refresh on a calendar. See @e_cal_get_refresh_supported.
1211 * Returns: TRUE if calendar supports refresh and it was invoked, FALSE otherwise.
1215 * Deprecated: 3.2: Use e_cal_client_refresh_sync() instead.
1218 e_cal_refresh (ECal *ecal,
1223 e_return_error_if_fail (E_IS_CAL (ecal), E_CALENDAR_STATUS_INVALID_ARG);
1225 e_return_error_if_fail (priv->gdbus_cal, E_CALENDAR_STATUS_REPOSITORY_OFFLINE);
1227 if (!e_gdbus_cal_call_refresh_sync (priv->gdbus_cal, NULL, error)) {
1228 E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_DBUS_EXCEPTION, error);
1236 * @ecal: A calendar client.
1237 * @error: Placeholder for error information.
1239 * Removes a calendar.
1241 * Returns: TRUE if the calendar was removed, FALSE if there was an error.
1243 * Deprecated: 3.2: Use e_client_remove_sync() on an #ECalClient object instead.
1246 e_cal_remove (ECal *ecal,
1251 e_return_error_if_fail (E_IS_CAL (ecal), E_CALENDAR_STATUS_INVALID_ARG);
1253 e_return_error_if_fail (priv->gdbus_cal, E_CALENDAR_STATUS_REPOSITORY_OFFLINE);
1255 if (!e_gdbus_cal_call_remove_sync (priv->gdbus_cal, NULL, error)) {
1256 E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_DBUS_EXCEPTION, error);
1263 /* Builds an URI list out of a CORBA string sequence */
1265 build_uri_list (GNOME_Evolution_Calendar_StringSeq *seq)
1270 for (i = 0; i < seq->_length; i++)
1271 uris = g_list_prepend (uris, g_strdup (seq->_buffer[i]));
1279 * @ecal: A calendar client.
1280 * @mode: Mode of the URIs to get.
1282 * Retrieves a list of all calendar clients for the given mode.
1284 * Returns: list of uris.
1286 * Deprecated: 3.2: This function has been dropped completely.
1289 e_cal_uri_list (ECal *ecal,
1294 GNOME_Evolution_Calendar_StringSeq *uri_seq;
1296 CORBA_Environment ev;
1299 g_return_val_if_fail (ecal != NULL, NULL);
1300 g_return_val_if_fail (E_IS_CAL (ecal), NULL);
1304 for (f = priv->factories; f; f = f->next) {
1305 CORBA_exception_init (&ev);
1306 uri_seq = GNOME_Evolution_Calendar_CalFactory_uriList (f->data, mode, &ev);
1308 if (BONOBO_EX (&ev)) {
1309 g_message ("e_cal_uri_list(): request failed");
1311 /* free memory and return */
1312 g_list_foreach (uris, (GFunc) g_free, NULL);
1318 uris = g_list_concat (uris, build_uri_list (uri_seq));
1319 CORBA_free (uri_seq);
1322 CORBA_exception_free (&ev);
1332 * e_cal_get_source_type:
1333 * @ecal: A calendar client.
1335 * Gets the type of the calendar client.
1337 * Returns: an #ECalSourceType value corresponding to the type
1338 * of the calendar client.
1340 * Deprecated: 3.2: Use e_cal_client_get_source_type() instead.
1343 e_cal_get_source_type (ECal *ecal)
1347 g_return_val_if_fail (ecal != NULL, E_CAL_SOURCE_TYPE_LAST);
1348 g_return_val_if_fail (E_IS_CAL (ecal), E_CAL_SOURCE_TYPE_LAST);
1356 * e_cal_get_load_state:
1357 * @ecal: A calendar client.
1359 * Queries the state of loading of a calendar client.
1361 * Returns: A #ECalLoadState value indicating whether the client has
1362 * not been loaded with #e_cal_open yet, whether it is being
1363 * loaded, or whether it is already loaded.
1365 * Deprecated: 3.2: Use e_client_is_opened() on an #ECalClient instead.
1368 e_cal_get_load_state (ECal *ecal)
1372 g_return_val_if_fail (ecal != NULL, E_CAL_LOAD_NOT_LOADED);
1373 g_return_val_if_fail (E_IS_CAL (ecal), E_CAL_LOAD_NOT_LOADED);
1376 return priv->load_state;
1381 * @ecal: A calendar client.
1383 * Queries the source that is open in a calendar client.
1385 * Returns: The source of the calendar that is already loaded or is being
1386 * loaded, or NULL if the ecal has not started a load request yet.
1388 * Deprecated: 3.2: Use e_client_get_source() on an #ECalClient object instead.
1391 e_cal_get_source (ECal *ecal)
1395 g_return_val_if_fail (ecal != NULL, NULL);
1396 g_return_val_if_fail (E_IS_CAL (ecal), NULL);
1399 return priv->source;
1403 * e_cal_get_local_attachment_store
1404 * @ecal: A calendar client.
1406 * Queries the URL where the calendar attachments are
1407 * serialized in the local filesystem. This enable clients
1408 * to operate with the reference to attachments rather than the data itself
1409 * unless it specifically uses the attachments for open/sending
1412 * Returns: The URL where the attachments are serialized in the
1415 * Deprecated: 3.2: Use e_cal_client_get_local_attachment_store() instead.
1418 e_cal_get_local_attachment_store (ECal *ecal)
1422 g_return_val_if_fail (ecal != NULL, NULL);
1423 g_return_val_if_fail (E_IS_CAL (ecal), NULL);
1426 return (const gchar *) priv->local_attachment_store;
1430 * e_cal_is_read_only:
1431 * @ecal: A calendar client.
1432 * @read_only: Return value for read only status.
1433 * @error: Placeholder for error information.
1435 * Queries whether the calendar client can perform modifications
1436 * on the calendar or not. Whether the backend is read only or not
1437 * is specified, on exit, in the @read_only argument.
1439 * Returns: TRUE if the call was successful, FALSE if there was an error.
1441 * Deprecated: 3.2: Use e_cal_client_is_readonly() on an #ECalClient object instead.
1444 e_cal_is_read_only (ECal *ecal,
1445 gboolean *read_only,
1450 if (!(ecal && E_IS_CAL (ecal)))
1451 E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_INVALID_ARG, error);
1454 *read_only = priv->read_only;
1460 * e_cal_get_cal_address:
1461 * @ecal: A calendar client.
1462 * @cal_address: Return value for address information.
1463 * @error: Placeholder for error information.
1465 * Queries the calendar address associated with a calendar client.
1467 * Returns: TRUE if the operation was successful, FALSE if there
1470 * Deprecated: 3.2: Use e_client_get_backend_property_sync()
1471 * with #CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS instead.
1474 e_cal_get_cal_address (ECal *ecal,
1475 gchar **cal_address,
1480 e_return_error_if_fail (E_IS_CAL (ecal), E_CALENDAR_STATUS_INVALID_ARG);
1481 e_return_error_if_fail (cal_address != NULL, E_CALENDAR_STATUS_INVALID_ARG);
1483 e_return_error_if_fail (priv->gdbus_cal, E_CALENDAR_STATUS_REPOSITORY_OFFLINE);
1484 *cal_address = NULL;
1487 if (priv->cal_address == NULL) {
1488 e_return_error_if_fail (priv->gdbus_cal, E_CALENDAR_STATUS_REPOSITORY_OFFLINE);
1489 if (priv->load_state != E_CAL_LOAD_LOADED) {
1491 E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error);
1494 if (!e_gdbus_cal_call_get_backend_property_sync (priv->gdbus_cal, CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS, &priv->cal_address, NULL, error)) {
1496 E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_DBUS_EXCEPTION, error);
1500 *cal_address = g_strdup (priv->cal_address);
1507 * e_cal_get_alarm_email_address:
1508 * @ecal: A calendar client.
1509 * @alarm_address: Return value for alarm address.
1510 * @error: Placeholder for error information.
1512 * Queries the address to be used for alarms in a calendar client.
1514 * Returns: TRUE if the operation was successful, FALSE if there was
1515 * an error while contacting the backend.
1517 * Deprecated: 3.2: Use e_client_get_backend_property_sync()
1518 * with #CAL_BACKEND_PROPERTY_ALARM_EMAIL_ADDRESS instead.
1521 e_cal_get_alarm_email_address (ECal *ecal,
1522 gchar **alarm_address,
1527 e_return_error_if_fail (alarm_address != NULL, E_CALENDAR_STATUS_INVALID_ARG);
1528 e_return_error_if_fail (E_IS_CAL (ecal), E_CALENDAR_STATUS_INVALID_ARG);
1530 e_return_error_if_fail (priv->gdbus_cal, E_CALENDAR_STATUS_REPOSITORY_OFFLINE);
1531 *alarm_address = NULL;
1533 if (priv->load_state != E_CAL_LOAD_LOADED) {
1534 E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error);
1537 if (!e_gdbus_cal_call_get_backend_property_sync (priv->gdbus_cal, CAL_BACKEND_PROPERTY_ALARM_EMAIL_ADDRESS, alarm_address, NULL, error)) {
1538 E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_DBUS_EXCEPTION, error);
1545 * e_cal_get_ldap_attribute:
1546 * @ecal: A calendar client.
1547 * @ldap_attribute: Return value for the LDAP attribute.
1548 * @error: Placeholder for error information.
1550 * Queries the LDAP attribute for a calendar client.
1552 * Returns: TRUE if the call was successful, FALSE if there was an
1553 * error contacting the backend.
1555 * Deprecated: 3.2: This function has been dropped completely.
1558 e_cal_get_ldap_attribute (ECal *ecal,
1559 gchar **ldap_attribute,
1564 e_return_error_if_fail (ldap_attribute != NULL, E_CALENDAR_STATUS_INVALID_ARG);
1565 e_return_error_if_fail (E_IS_CAL (ecal), E_CALENDAR_STATUS_INVALID_ARG);
1567 e_return_error_if_fail (priv->gdbus_cal, E_CALENDAR_STATUS_REPOSITORY_OFFLINE);
1568 *ldap_attribute = NULL;
1570 E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_NOT_SUPPORTED, error);
1574 load_capabilities (ECal *ecal,
1580 e_return_error_if_fail (priv->gdbus_cal, E_CALENDAR_STATUS_REPOSITORY_OFFLINE);
1582 if (priv->load_state != E_CAL_LOAD_LOADED) {
1583 E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error);
1588 if (priv->capabilities) {
1590 E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_OK, error);
1593 if (!e_gdbus_cal_call_get_backend_property_sync (priv->gdbus_cal, CLIENT_BACKEND_PROPERTY_CAPABILITIES, &priv->capabilities, NULL, error)) {
1595 E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_DBUS_EXCEPTION, error);
1604 check_capability (ECal *ecal,
1611 /* FIXME Check result */
1612 load_capabilities (ecal, NULL);
1613 if (priv->capabilities && strstr (priv->capabilities, cap))
1620 * e_cal_get_one_alarm_only:
1621 * @ecal: A calendar client.
1623 * Checks if a calendar supports only one alarm per component.
1625 * Returns: TRUE if the calendar allows only one alarm, FALSE otherwise.
1627 * Deprecated: 3.2: Use e_cal_client_check_one_alarm_only() instead.
1630 e_cal_get_one_alarm_only (ECal *ecal)
1632 g_return_val_if_fail (ecal != NULL, FALSE);
1633 g_return_val_if_fail (ecal && E_IS_CAL (ecal), FALSE);
1635 return check_capability (ecal, CAL_STATIC_CAPABILITY_ONE_ALARM_ONLY);
1639 * e_cal_get_organizer_must_attend:
1640 * @ecal: A calendar client.
1642 * Checks if a calendar forces organizers of meetings to be also attendees.
1644 * Returns: TRUE if the calendar forces organizers to attend meetings,
1647 * Deprecated: 3.2: Use e_cal_client_check_organizer_must_attend() instead.
1650 e_cal_get_organizer_must_attend (ECal *ecal)
1652 g_return_val_if_fail (ecal != NULL, FALSE);
1653 g_return_val_if_fail (E_IS_CAL (ecal), FALSE);
1655 return check_capability (ecal, CAL_STATIC_CAPABILITY_ORGANIZER_MUST_ATTEND);
1659 * e_cal_get_recurrences_no_master:
1660 * @ecal: A calendar client.
1662 * Checks if the calendar has a master object for recurrences.
1664 * Returns: TRUE if the calendar has a master object for recurrences,
1667 * Deprecated: 3.2: Use e_cal_client_check_recurrences_no_master() instead.
1670 e_cal_get_recurrences_no_master (ECal *ecal)
1672 g_return_val_if_fail (ecal != NULL, FALSE);
1673 g_return_val_if_fail (E_IS_CAL (ecal), FALSE);
1675 return check_capability (ecal, CAL_STATIC_CAPABILITY_RECURRENCES_NO_MASTER);
1679 * e_cal_get_static_capability:
1680 * @ecal: A calendar client.
1681 * @cap: Name of the static capability to check.
1683 * Queries the calendar for static capabilities.
1685 * Returns: TRUE if the capability is supported, FALSE otherwise.
1687 * Deprecated: 3.2: Use e_client_check_capability() on an #ECalClient object instead.
1690 e_cal_get_static_capability (ECal *ecal,
1693 g_return_val_if_fail (ecal != NULL, FALSE);
1694 g_return_val_if_fail (E_IS_CAL (ecal), FALSE);
1696 return check_capability (ecal, cap);
1700 * e_cal_get_save_schedules:
1701 * @ecal: A calendar client.
1703 * Checks whether the calendar saves schedules.
1705 * Returns: TRUE if it saves schedules, FALSE otherwise.
1707 * Deprecated: 3.2: Use e_cal_client_check_save_schedules() instead.
1710 e_cal_get_save_schedules (ECal *ecal)
1712 g_return_val_if_fail (ecal != NULL, FALSE);
1713 g_return_val_if_fail (E_IS_CAL (ecal), FALSE);
1715 return check_capability (ecal, CAL_STATIC_CAPABILITY_SAVE_SCHEDULES);
1719 * e_cal_get_organizer_must_accept:
1720 * @ecal: A calendar client.
1722 * Checks whether a calendar requires organizer to accept their attendance to
1725 * Returns: TRUE if the calendar requires organizers to accept, FALSE
1728 * Deprecated: 3.2: Use e_cal_client_check_organizer_must_accept() instead.
1731 e_cal_get_organizer_must_accept (ECal *ecal)
1733 g_return_val_if_fail (ecal != NULL, FALSE);
1734 g_return_val_if_fail (E_IS_CAL (ecal), FALSE);
1736 return check_capability (ecal, CAL_STATIC_CAPABILITY_ORGANIZER_MUST_ACCEPT);
1740 * e_cal_get_refresh_supported:
1741 * @ecal: A calendar client.
1743 * Checks whether a calendar supports explicit refreshing (see @e_cal_refresh).
1745 * Returns: TRUE if the calendar supports refreshing, FALSE otherwise.
1749 * Deprecated: 3.2: Use e_client_check_refresh_supported() instead.
1752 e_cal_get_refresh_supported (ECal *ecal)
1754 g_return_val_if_fail (ecal != NULL, FALSE);
1755 g_return_val_if_fail (E_IS_CAL (ecal), FALSE);
1757 return check_capability (ecal, CAL_STATIC_CAPABILITY_REFRESH_SUPPORTED);
1762 * @ecal: A calendar client.
1763 * @mode: Mode to switch to.
1765 * Switches online/offline mode on the calendar.
1767 * Returns: TRUE if the switch was successful, FALSE if there was an error.
1769 * Deprecated: 3.2: This function has been dropped completely.
1772 e_cal_set_mode (ECal *ecal,
1777 g_return_val_if_fail (ecal != NULL, FALSE);
1778 g_return_val_if_fail (E_IS_CAL (ecal), FALSE);
1779 g_return_val_if_fail (mode & CAL_MODE_ANY, FALSE);
1782 g_return_val_if_fail (priv->gdbus_cal, FALSE);
1783 g_return_val_if_fail (priv->load_state == E_CAL_LOAD_LOADED, FALSE);
1785 g_debug ("%s: This function is not supported since 3.2", G_STRFUNC);
1790 /* This is used in the callback which fetches all the timezones needed for an
1792 typedef struct _ECalGetTimezonesData ECalGetTimezonesData;
1793 struct _ECalGetTimezonesData {
1796 /* This starts out at E_CALENDAR_STATUS_OK. If an error occurs this
1797 * contains the last error. */
1798 ECalendarStatus status;
1802 * e_cal_get_default_object:
1803 * @ecal: A calendar client.
1804 * @icalcomp: Return value for the default object.
1805 * @error: Placeholder for error information.
1807 * Retrives an #icalcomponent from the backend that contains the default
1808 * values for properties needed.
1810 * Returns: TRUE if the call was successful, FALSE otherwise.
1812 * Deprecated: 3.2: Use e_cal_client_get_default_object_sync() instead.
1815 e_cal_get_default_object (ECal *ecal,
1816 icalcomponent **icalcomp,
1820 ECalendarStatus status;
1821 gchar *object = NULL;
1823 e_return_error_if_fail (icalcomp != NULL, E_CALENDAR_STATUS_INVALID_ARG);
1824 e_return_error_if_fail (E_IS_CAL (ecal), E_CALENDAR_STATUS_INVALID_ARG);
1826 e_return_error_if_fail (priv->gdbus_cal, E_CALENDAR_STATUS_REPOSITORY_OFFLINE);
1829 if (priv->load_state != E_CAL_LOAD_LOADED) {
1830 E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error);
1833 if (!e_gdbus_cal_call_get_backend_property_sync (priv->gdbus_cal, CAL_BACKEND_PROPERTY_DEFAULT_OBJECT, &object, NULL, error)) {
1834 E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_DBUS_EXCEPTION, error);
1838 *icalcomp = icalparser_parse_string (object);
1842 status = E_CALENDAR_STATUS_INVALID_OBJECT;
1844 status = E_CALENDAR_STATUS_OK;
1846 E_CALENDAR_CHECK_STATUS (status, error);
1848 status = E_CALENDAR_STATUS_OTHER_ERROR;
1850 E_CALENDAR_CHECK_STATUS (status, error);
1854 * e_cal_get_attachments_for_comp:
1855 * @ecal: A calendar client.
1856 * @uid: Unique identifier for a calendar component.
1857 * @rid: Recurrence identifier.
1858 * @list: Return the list of attachment uris.
1859 * @error: Placeholder for error information.
1861 * Queries a calendar for a calendar component object based on its unique
1862 * identifier and gets the attachments for the component.
1864 * Returns: TRUE if the call was successful, FALSE otherwise.
1866 * Deprecated: 3.2: Use e_cal_client_get_attachment_uris_sync() instead.
1869 e_cal_get_attachments_for_comp (ECal *ecal,
1876 ECalendarStatus status;
1880 e_return_error_if_fail (uid != NULL, E_CALENDAR_STATUS_INVALID_ARG);
1881 e_return_error_if_fail (list != NULL, E_CALENDAR_STATUS_INVALID_ARG);
1882 e_return_error_if_fail (E_IS_CAL (ecal), E_CALENDAR_STATUS_INVALID_ARG);
1884 e_return_error_if_fail (priv->gdbus_cal, E_CALENDAR_STATUS_REPOSITORY_OFFLINE);
1887 if (priv->load_state != E_CAL_LOAD_LOADED) {
1888 E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error);
1891 strv = e_gdbus_cal_encode_get_attachment_uris (uid, rid);
1892 if (!e_gdbus_cal_call_get_attachment_uris_sync (priv->gdbus_cal, (const gchar * const *) strv, &list_array, NULL, error)) {
1895 E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_DBUS_EXCEPTION, error);
1902 for (string = list_array; *string; string++) {
1903 *list = g_slist_append (*list, g_strdup (*string));
1905 g_strfreev (list_array);
1906 status = E_CALENDAR_STATUS_OK;
1908 status = E_CALENDAR_STATUS_OTHER_ERROR;
1910 E_CALENDAR_CHECK_STATUS (status, error);
1915 * @ecal: A calendar client.
1916 * @uid: Unique identifier for a calendar component.
1917 * @rid: Recurrence identifier.
1918 * @icalcomp: Return value for the calendar component object.
1919 * @error: Placeholder for error information.
1921 * Queries a calendar for a calendar component object based on its unique
1924 * Returns: TRUE if the call was successful, FALSE otherwise.
1926 * Deprecated: 3.2: Use e_cal_client_get_object_sync() instead.
1929 e_cal_get_object (ECal *ecal,
1932 icalcomponent **icalcomp,
1936 ECalendarStatus status;
1937 gchar *object = NULL, **strv;
1938 icalcomponent *tmp_icalcomp;
1939 icalcomponent_kind kind;
1941 e_return_error_if_fail (uid != NULL, E_CALENDAR_STATUS_INVALID_ARG);
1942 e_return_error_if_fail (icalcomp != NULL, E_CALENDAR_STATUS_INVALID_ARG);
1943 e_return_error_if_fail (E_IS_CAL (ecal), E_CALENDAR_STATUS_INVALID_ARG);
1945 e_return_error_if_fail (priv->gdbus_cal, E_CALENDAR_STATUS_REPOSITORY_OFFLINE);
1948 if (priv->load_state != E_CAL_LOAD_LOADED) {
1949 E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error);
1952 strv = e_gdbus_cal_encode_get_object (uid, rid);
1953 if (!e_gdbus_cal_call_get_object_sync (priv->gdbus_cal, (const gchar * const *) strv, &object, NULL, error)) {
1956 E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_DBUS_EXCEPTION, error);
1961 status = E_CALENDAR_STATUS_OK;
1962 tmp_icalcomp = icalparser_parse_string (object);
1963 if (!tmp_icalcomp) {
1964 status = E_CALENDAR_STATUS_INVALID_OBJECT;
1967 kind = icalcomponent_isa (tmp_icalcomp);
1968 if ((kind == ICAL_VEVENT_COMPONENT && priv->type == E_CAL_SOURCE_TYPE_EVENT) ||
1969 (kind == ICAL_VTODO_COMPONENT && priv->type == E_CAL_SOURCE_TYPE_TODO) ||
1970 (kind == ICAL_VJOURNAL_COMPONENT && priv->type == E_CAL_SOURCE_TYPE_JOURNAL)) {
1971 *icalcomp = icalcomponent_new_clone (tmp_icalcomp);
1972 } else if (kind == ICAL_VCALENDAR_COMPONENT) {
1973 icalcomponent *subcomp = NULL;
1975 switch (priv->type) {
1976 case E_CAL_SOURCE_TYPE_EVENT :
1977 subcomp = icalcomponent_get_first_component (tmp_icalcomp, ICAL_VEVENT_COMPONENT);
1979 case E_CAL_SOURCE_TYPE_TODO :
1980 subcomp = icalcomponent_get_first_component (tmp_icalcomp, ICAL_VTODO_COMPONENT);
1982 case E_CAL_SOURCE_TYPE_JOURNAL :
1983 subcomp = icalcomponent_get_first_component (tmp_icalcomp, ICAL_VJOURNAL_COMPONENT);
1986 /* ignore everything else */
1990 /* we are only interested in the first component */
1992 *icalcomp = icalcomponent_new_clone (subcomp);
1995 icalcomponent_free (tmp_icalcomp);
2000 E_CALENDAR_CHECK_STATUS (status, error);
2004 * e_cal_get_objects_for_uid:
2005 * @ecal: A calendar client.
2006 * @uid: Unique identifier for a calendar component.
2007 * @objects: Return value for the list of objects obtained from the backend.
2008 * @error: Placeholder for error information.
2010 * Queries a calendar for all calendar components with the given unique
2011 * ID. This will return any recurring event and all its detached recurrences.
2012 * For non-recurring events, it will just return the object with that ID.
2014 * Returns: TRUE if the call was successful, FALSE otherwise.
2016 * Deprecated: 3.2: Use e_cal_client_get_objects_for_uid_sync() instead.
2019 e_cal_get_objects_for_uid (ECal *ecal,
2025 ECalendarStatus status;
2026 gchar *object = NULL, **strv;
2028 e_return_error_if_fail (uid != NULL, E_CALENDAR_STATUS_INVALID_ARG);
2029 e_return_error_if_fail (objects != NULL, E_CALENDAR_STATUS_INVALID_ARG);
2030 e_return_error_if_fail (E_IS_CAL (ecal), E_CALENDAR_STATUS_INVALID_ARG);
2032 e_return_error_if_fail (priv->gdbus_cal, E_CALENDAR_STATUS_REPOSITORY_OFFLINE);
2035 if (priv->load_state != E_CAL_LOAD_LOADED) {
2036 E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error);
2039 strv = e_gdbus_cal_encode_get_object (uid, "");
2040 if (!e_gdbus_cal_call_get_object_sync (priv->gdbus_cal, (const gchar * const *) strv, &object, NULL, error)) {
2043 E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_DBUS_EXCEPTION, error);
2048 status = E_CALENDAR_STATUS_OK;
2050 icalcomponent *icalcomp;
2051 icalcomponent_kind kind;
2053 icalcomp = icalparser_parse_string (object);
2055 status = E_CALENDAR_STATUS_INVALID_OBJECT;
2058 ECalComponent *comp;
2060 kind = icalcomponent_isa (icalcomp);
2061 if ((kind == ICAL_VEVENT_COMPONENT && priv->type == E_CAL_SOURCE_TYPE_EVENT) ||
2062 (kind == ICAL_VTODO_COMPONENT && priv->type == E_CAL_SOURCE_TYPE_TODO) ||
2063 (kind == ICAL_VJOURNAL_COMPONENT && priv->type == E_CAL_SOURCE_TYPE_JOURNAL)) {
2064 comp = e_cal_component_new ();
2065 e_cal_component_set_icalcomponent (comp, icalcomponent_new_clone (icalcomp));
2066 *objects = g_list_append (NULL, comp);
2067 } else if (kind == ICAL_VCALENDAR_COMPONENT) {
2068 icalcomponent *subcomp;
2069 icalcomponent_kind kind_to_find;
2071 switch (priv->type) {
2072 case E_CAL_SOURCE_TYPE_TODO :
2073 kind_to_find = ICAL_VTODO_COMPONENT;
2075 case E_CAL_SOURCE_TYPE_JOURNAL :
2076 kind_to_find = ICAL_VJOURNAL_COMPONENT;
2078 case E_CAL_SOURCE_TYPE_EVENT :
2080 kind_to_find = ICAL_VEVENT_COMPONENT;
2085 subcomp = icalcomponent_get_first_component (icalcomp, kind_to_find);
2087 comp = e_cal_component_new ();
2088 e_cal_component_set_icalcomponent (comp, icalcomponent_new_clone (subcomp));
2089 *objects = g_list_append (*objects, comp);
2090 subcomp = icalcomponent_get_next_component (icalcomp, kind_to_find);
2094 icalcomponent_free (icalcomp);
2099 E_CALENDAR_CHECK_STATUS (status, error);
2103 * e_cal_resolve_tzid_cb:
2104 * @tzid: ID of the timezone to resolve.
2105 * @data: Closure data for the callback.
2107 * Resolves TZIDs for the recurrence generator.
2109 * Returns: The timezone identified by the @tzid argument, or %NULL if
2110 * it could not be found.
2112 * Deprecated: 3.2: Use e_cal_client_resolve_tzid_cb() instead.
2115 e_cal_resolve_tzid_cb (const gchar *tzid,
2119 icaltimezone *zone = NULL;
2121 g_return_val_if_fail (data != NULL, NULL);
2122 g_return_val_if_fail (E_IS_CAL (data), NULL);
2124 ecal = E_CAL (data);
2126 /* FIXME: Handle errors. */
2127 e_cal_get_timezone (ecal, tzid, &zone, NULL);
2133 * e_cal_get_changes:
2134 * @ecal: A calendar client.
2135 * @change_id: ID to use for comparing changes.
2136 * @changes: Return value for the list of changes.
2137 * @error: Placeholder for error information.
2139 * Returns a list of changes made to the calendar since a specific time. That time
2140 * is identified by the @change_id argument, which is used by the backend to
2141 * compute the changes done.
2143 * Returns: TRUE if the call was successful, FALSE otherwise.
2145 * Deprecated: 3.2: This function has been dropped completely.
2148 e_cal_get_changes (ECal *ecal,
2149 const gchar *change_id,
2155 e_return_error_if_fail (changes != NULL, E_CALENDAR_STATUS_INVALID_ARG);
2156 e_return_error_if_fail (change_id != NULL, E_CALENDAR_STATUS_INVALID_ARG);
2157 e_return_error_if_fail (E_IS_CAL (ecal), E_CALENDAR_STATUS_INVALID_ARG);
2159 e_return_error_if_fail (priv->gdbus_cal, E_CALENDAR_STATUS_REPOSITORY_OFFLINE);
2162 E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_NOT_SUPPORTED, error);
2166 * e_cal_free_change_list:
2167 * @list: List of changes to be freed.
2169 * Free a list of changes as returned by #e_cal_get_changes.
2171 * Deprecated: 3.2: Use () instead.
2174 e_cal_free_change_list (GList *list)
2179 for (l = list; l; l = l->next) {
2182 if (c != NULL && c->comp != NULL) {
2183 g_object_unref (G_OBJECT (c->comp));
2186 g_warn_if_reached ();
2193 * e_cal_get_object_list:
2194 * @ecal: A calendar client.
2195 * @query: Query string.
2196 * @objects: (out) (element-type long): Return value for list of objects.
2197 * @error: Placeholder for error information.
2199 * Gets a list of objects from the calendar that match the query specified
2200 * by the @query argument. The objects will be returned in the @objects
2201 * argument, which is a list of #icalcomponent. When done, this list
2202 * should be freed by using the #e_cal_free_object_list function.
2204 * Returns: TRUE if the operation was successful, FALSE otherwise.
2206 * Deprecated: 3.2: Use e_cal_client_get_object_list_sync() instead.
2209 e_cal_get_object_list (ECal *ecal,
2215 gchar **object_array = NULL, *gdbus_query = NULL;
2217 e_return_error_if_fail (objects != NULL, E_CALENDAR_STATUS_INVALID_ARG);
2218 e_return_error_if_fail (query, E_CALENDAR_STATUS_INVALID_ARG);
2219 e_return_error_if_fail (E_IS_CAL (ecal), E_CALENDAR_STATUS_INVALID_ARG);
2221 e_return_error_if_fail (priv->gdbus_cal, E_CALENDAR_STATUS_REPOSITORY_OFFLINE);
2224 if (priv->load_state != E_CAL_LOAD_LOADED) {
2225 E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error);
2228 if (!e_gdbus_cal_call_get_object_list_sync (priv->gdbus_cal, e_util_ensure_gdbus_string (query, &gdbus_query), &object_array, NULL, error)) {
2229 g_free (gdbus_query);
2231 E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_DBUS_EXCEPTION, error);
2234 g_free (gdbus_query);
2237 icalcomponent *comp;
2239 for (object = object_array; *object; object++) {
2240 comp = icalcomponent_new_from_string (*object);
2241 if (!comp) continue;
2242 *objects = g_list_prepend (*objects, comp);
2245 g_strfreev (object_array);
2247 E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_OK, error);
2250 E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_OTHER_ERROR, error);
2254 * e_cal_get_object_list_as_comp:
2255 * @ecal: A calendar client.
2256 * @query: Query string.
2257 * @objects: Return value for list of objects.
2258 * @error: Placeholder for error information.
2260 * Gets a list of objects from the calendar that match the query specified
2261 * by the @query argument. The objects will be returned in the @objects
2262 * argument, which is a list of #ECalComponent.
2264 * Returns: TRUE if the operation was successful, FALSE otherwise.
2266 * Deprecated: 3.2: Use e_cal_client_get_object_list_as_comps_sync() instead.
2269 e_cal_get_object_list_as_comp (ECal *ecal,
2274 GList *ical_objects = NULL;
2277 e_return_error_if_fail (objects != NULL, E_CALENDAR_STATUS_INVALID_ARG);
2280 e_return_error_if_fail (ecal && E_IS_CAL (ecal), E_CALENDAR_STATUS_INVALID_ARG);
2281 e_return_error_if_fail (query, E_CALENDAR_STATUS_INVALID_ARG);
2283 if (!e_cal_get_object_list (ecal, query, &ical_objects, error))
2286 for (l = ical_objects; l; l = l->next) {
2287 ECalComponent *comp;
2289 comp = e_cal_component_new ();
2290 e_cal_component_set_icalcomponent (comp, l->data);
2291 *objects = g_list_prepend (*objects, comp);
2294 g_list_free (ical_objects);
2300 * e_cal_free_object_list:
2301 * @objects: List of objects to be freed.
2303 * Frees a list of objects as returned by #e_cal_get_object_list.
2305 * Deprecated: 3.2: Use e_cal_client_free_icalcomp_slist() instead.
2308 e_cal_free_object_list (GList *objects)
2312 for (l = objects; l; l = l->next)
2313 icalcomponent_free (l->data);
2315 g_list_free (objects);
2319 * e_cal_get_free_busy
2320 * @ecal: A calendar client.
2321 * @users: List of users to retrieve free/busy information for.
2322 * @start: Start time for query.
2323 * @end: End time for query.
2324 * @freebusy: Return value for VFREEBUSY objects.
2325 * @error: Placeholder for error information.
2327 * Gets free/busy information from the calendar server.
2329 * Returns: TRUE if the operation was successful, FALSE otherwise.
2331 * Deprecated: 3.2: Use e_cal_client_get_free_busy_sync() instead.
2334 e_cal_get_free_busy (ECal *ecal,
2346 e_return_error_if_fail (users != NULL, E_CALENDAR_STATUS_INVALID_ARG);
2347 e_return_error_if_fail (freebusy != NULL, E_CALENDAR_STATUS_INVALID_ARG);
2348 e_return_error_if_fail (E_IS_CAL (ecal), E_CALENDAR_STATUS_INVALID_ARG);
2350 e_return_error_if_fail (priv->gdbus_cal, E_CALENDAR_STATUS_REPOSITORY_OFFLINE);
2353 if (priv->load_state != E_CAL_LOAD_LOADED) {
2354 E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error);
2358 for (l = users; l; l = l->next) {
2359 susers = g_slist_prepend (susers, l->data);
2361 susers = g_slist_reverse (susers);
2362 strv = e_gdbus_cal_encode_get_free_busy (start, end, susers);
2363 g_slist_free (susers);
2365 g_mutex_lock (priv->free_busy_data_lock);
2366 priv->free_busy_data = freebusy;
2367 g_mutex_unlock (priv->free_busy_data_lock);
2369 if (!e_gdbus_cal_call_get_free_busy_sync (priv->gdbus_cal, (const gchar * const *) strv, NULL, error)) {
2371 g_mutex_lock (priv->free_busy_data_lock);
2372 priv->free_busy_data = NULL;
2373 g_mutex_unlock (priv->free_busy_data_lock);
2375 E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_DBUS_EXCEPTION, error);
2379 g_mutex_lock (priv->free_busy_data_lock);
2380 priv->free_busy_data = NULL;
2381 g_mutex_unlock (priv->free_busy_data_lock);
2383 E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_OK, error);
2386 struct comp_instance {
2387 ECalComponent *comp;
2392 struct instances_info {
2394 icaltimezone *start_zone;
2397 /* Called from cal_recur_generate_instances(); adds an instance to the list */
2399 add_instance (ECalComponent *comp,
2405 struct comp_instance *ci;
2406 struct icaltimetype itt;
2407 icalcomponent *icalcomp;
2408 struct instances_info *instances_hold;
2410 instances_hold = data;
2411 list = instances_hold->instances;
2413 ci = g_new (struct comp_instance, 1);
2415 icalcomp = icalcomponent_new_clone (e_cal_component_get_icalcomponent (comp));
2417 /* add the instance to the list */
2418 ci->comp = e_cal_component_new ();
2419 e_cal_component_set_icalcomponent (ci->comp, icalcomp);
2421 /* set the RECUR-ID for the instance */
2422 if (e_cal_util_component_has_recurrences (icalcomp)) {
2423 if (!(icalcomponent_get_first_property (icalcomp, ICAL_RECURRENCEID_PROPERTY))) {
2424 ECalComponentRange *range;
2425 ECalComponentDateTime datetime;
2427 e_cal_component_get_dtstart (comp, &datetime);
2429 if (instances_hold->start_zone)
2430 itt = icaltime_from_timet_with_zone (start, datetime.value->is_date, instances_hold->start_zone);
2432 itt = icaltime_from_timet (start, datetime.value->is_date);
2434 if (datetime.tzid) {
2435 g_free ((gchar *) datetime.tzid);
2436 datetime.tzid = NULL;
2440 g_free (datetime.value);
2441 datetime.value = &itt;
2443 range = g_new0 (ECalComponentRange, 1);
2444 range->type = E_CAL_COMPONENT_RANGE_SINGLE;
2445 range->datetime = datetime;
2447 e_cal_component_set_recurid (ci->comp, range);
2450 g_free ((gchar *) datetime.tzid);
2458 *list = g_list_prepend (*list, ci);
2463 /* Used from g_list_sort(); compares two struct comp_instance structures */
2465 compare_comp_instance (gconstpointer a,
2468 const struct comp_instance *cia, *cib;
2474 diff = cia->start - cib->start;
2475 return (diff < 0) ? -1 : (diff > 0) ? 1 : 0;
2479 process_detached_instances (GList *instances,
2480 GList *detached_instances)
2482 struct comp_instance *ci, *cid;
2483 GList *dl, *unprocessed_instances = NULL;
2485 for (dl = detached_instances; dl != NULL; dl = dl->next) {
2489 ECalComponentRange recur_id, instance_recur_id;
2492 recur_id.type = E_CAL_COMPONENT_RANGE_SINGLE;
2493 instance_recur_id.type = E_CAL_COMPONENT_RANGE_SINGLE;
2496 e_cal_component_get_uid (cid->comp, &uid);
2497 e_cal_component_get_recurid (cid->comp, &recur_id);
2499 /* search for coincident instances already expanded */
2500 for (il = instances; il != NULL; il = il->next) {
2501 const gchar *instance_uid;
2505 e_cal_component_get_uid (ci->comp, &instance_uid);
2506 e_cal_component_get_recurid (ci->comp, &instance_recur_id);
2507 if (strcmp (uid, instance_uid) == 0) {
2508 gchar *i_rid = NULL, *d_rid = NULL;
2510 i_rid = e_cal_component_get_recurid_as_string (ci->comp);
2511 d_rid = e_cal_component_get_recurid_as_string (cid->comp);
2513 if (i_rid && d_rid && strcmp (i_rid, d_rid) == 0) {
2514 g_object_unref (ci->comp);
2515 ci->comp = g_object_ref (cid->comp);
2516 ci->start = cid->start;
2521 if (!instance_recur_id.datetime.value ||
2522 !recur_id.datetime.value) {
2524 * Prevent obvious segfault by ignoring missing
2525 * recurrency ids. Real problem might be elsewhere,
2526 * but anything is better than crashing...
2528 g_log (G_LOG_DOMAIN,
2529 G_LOG_LEVEL_CRITICAL,
2530 "UID %s: instance RECURRENCE-ID %s + detached instance RECURRENCE-ID %s: cannot compare",
2535 e_cal_component_free_datetime (&instance_recur_id.datetime);
2540 cmp = icaltime_compare (*instance_recur_id.datetime.value,
2541 *recur_id.datetime.value);
2542 if ((recur_id.type == E_CAL_COMPONENT_RANGE_THISPRIOR && cmp <= 0) ||
2543 (recur_id.type == E_CAL_COMPONENT_RANGE_THISFUTURE && cmp >= 0)) {
2544 ECalComponent *comp;
2546 comp = e_cal_component_new ();
2547 e_cal_component_set_icalcomponent (
2549 icalcomponent_new_clone (e_cal_component_get_icalcomponent (cid->comp)));
2550 e_cal_component_set_recurid (comp, &instance_recur_id);
2552 /* replace the generated instances */
2553 g_object_unref (ci->comp);
2560 e_cal_component_free_datetime (&instance_recur_id.datetime);
2563 e_cal_component_free_datetime (&recur_id.datetime);
2566 unprocessed_instances = g_list_prepend (unprocessed_instances, cid);
2569 /* add the unprocessed instances (ie, detached instances with no master object */
2570 while (unprocessed_instances != NULL) {
2571 cid = unprocessed_instances->data;
2572 ci = g_new0 (struct comp_instance, 1);
2573 ci->comp = g_object_ref (cid->comp);
2574 ci->start = cid->start;
2576 instances = g_list_append (instances, ci);
2578 unprocessed_instances = g_list_remove (unprocessed_instances, cid);
2585 generate_instances (ECal *ecal,
2589 ECalRecurInstanceFn cb,
2592 GList *objects = NULL;
2593 GList *instances, *detached_instances = NULL;
2596 gchar *iso_start, *iso_end;
2601 /* Generate objects */
2603 GError *error = NULL;
2607 if (!e_cal_get_objects_for_uid (ecal, uid, &objects, &error)) {
2608 if (error->code == E_CALENDAR_STATUS_BUSY && tries >= 10) {
2611 g_clear_error (&error);
2616 unwrap_gerror (&error);
2617 g_message ("Failed to get recurrence objects for uid %s \n", error ? error->message : "Unknown error");
2618 g_clear_error (&error);
2623 iso_start = isodate_from_time_t (start);
2627 iso_end = isodate_from_time_t (end);
2633 query = g_strdup_printf ("(occur-in-time-range? (make-time \"%s\") (make-time \"%s\"))",
2634 iso_start, iso_end);
2637 if (!e_cal_get_object_list_as_comp (ecal, query, &objects, NULL)) {
2646 for (l = objects; l; l = l->next) {
2647 ECalComponent *comp;
2648 icaltimezone *default_zone;
2650 if (priv->default_zone)
2651 default_zone = priv->default_zone;
2653 default_zone = icaltimezone_get_utc_timezone ();
2656 if (e_cal_component_is_instance (comp)) {
2657 struct comp_instance *ci;
2658 ECalComponentDateTime dtstart, dtend;
2659 icaltimezone *start_zone = NULL, *end_zone = NULL;
2661 /* keep the detached instances apart */
2662 ci = g_new0 (struct comp_instance, 1);
2665 e_cal_component_get_dtstart (comp, &dtstart);
2666 e_cal_component_get_dtend (comp, &dtend);
2668 /* For DATE-TIME values with a TZID, we use
2669 * e_cal_resolve_tzid_cb to resolve the TZID.
2670 * For DATE values and DATE-TIME values without a
2671 * TZID (i.e. floating times) we use the default
2673 if (dtstart.tzid && !dtstart.value->is_date) {
2674 start_zone = e_cal_resolve_tzid_cb (dtstart.tzid, ecal);
2676 start_zone = default_zone;
2678 start_zone = default_zone;
2681 if (dtend.tzid && !dtend.value->is_date) {
2682 end_zone = e_cal_resolve_tzid_cb (dtend.tzid, ecal);
2684 end_zone = default_zone;
2686 end_zone = default_zone;
2689 ci->start = icaltime_as_timet_with_zone (*dtstart.value, start_zone);
2692 ci->end = icaltime_as_timet_with_zone (*dtend.value, end_zone);
2693 else if (icaltime_is_date (*dtstart.value))
2694 ci->end = time_day_end (ci->start);
2696 ci->end = ci->start;
2698 e_cal_component_free_datetime (&dtstart);
2699 e_cal_component_free_datetime (&dtend);
2701 if (ci->start <= end && ci->end >= start) {
2702 detached_instances = g_list_prepend (detached_instances, ci);
2704 /* it doesn't fit to our time range, thus skip it */
2705 g_object_unref (G_OBJECT (ci->comp));
2709 ECalComponentDateTime datetime;
2710 icaltimezone *start_zone = NULL;
2711 struct instances_info *instances_hold;
2713 /* Get the start timezone */
2714 e_cal_component_get_dtstart (comp, &datetime);
2716 e_cal_get_timezone (ecal, datetime.tzid, &start_zone, NULL);
2719 e_cal_component_free_datetime (&datetime);
2721 instances_hold = g_new0 (struct instances_info, 1);
2722 instances_hold->instances = &instances;
2723 instances_hold->start_zone = start_zone;
2725 e_cal_recur_generate_instances (comp, start, end, add_instance, instances_hold,
2726 e_cal_resolve_tzid_cb, ecal,
2729 g_free (instances_hold);
2730 g_object_unref (comp);
2734 g_list_free (objects);
2736 /* Generate instances and spew them out */
2738 instances = g_list_sort (instances, compare_comp_instance);
2739 instances = process_detached_instances (instances, detached_instances);
2741 for (l = instances; l; l = l->next) {
2742 struct comp_instance *ci;
2747 result = (* cb) (ci->comp, ci->start, ci->end, cb_data);
2755 for (l = instances; l; l = l->next) {
2756 struct comp_instance *ci;
2759 g_object_unref (G_OBJECT (ci->comp));
2763 g_list_free (instances);
2765 for (l = detached_instances; l; l = l->next) {
2766 struct comp_instance *ci;
2769 g_object_unref (G_OBJECT (ci->comp));
2773 g_list_free (detached_instances);
2778 * e_cal_generate_instances:
2779 * @ecal: A calendar client.
2780 * @start: Start time for query.
2781 * @end: End time for query.
2782 * @cb: Callback for each generated instance.
2783 * @cb_data: Closure data for the callback.
2785 * Does a combination of #e_cal_get_object_list () and
2786 * #e_cal_recur_generate_instances().
2788 * The callback function should do a g_object_ref() of the calendar component
2789 * it gets passed if it intends to keep it around, since it will be unref'ed
2790 * as soon as the callback returns.
2792 * Deprecated: 3.2: Use e_cal_client_generate_instances() instead.
2795 e_cal_generate_instances (ECal *ecal,
2798 ECalRecurInstanceFn cb,
2803 g_return_if_fail (ecal != NULL);
2804 g_return_if_fail (E_IS_CAL (ecal));
2807 g_return_if_fail (priv->load_state == E_CAL_LOAD_LOADED);
2809 g_return_if_fail (start >= 0);
2810 g_return_if_fail (end >= 0);
2811 g_return_if_fail (cb != NULL);
2813 generate_instances (ecal, start, end, NULL, cb, cb_data);
2817 * e_cal_generate_instances_for_object:
2818 * @ecal: A calendar client.
2819 * @icalcomp: Object to generate instances from.
2820 * @start: Start time for query.
2821 * @end: End time for query.
2822 * @cb: Callback for each generated instance.
2823 * @cb_data: Closure data for the callback.
2825 * Does a combination of #e_cal_get_object_list () and
2826 * #e_cal_recur_generate_instances(), like #e_cal_generate_instances(), but
2827 * for a single object.
2829 * The callback function should do a g_object_ref() of the calendar component
2830 * it gets passed if it intends to keep it around, since it will be unref'ed
2831 * as soon as the callback returns.
2833 * Deprecated: 3.2: Use e_cal_client_generate_instances_for_object() instead.
2836 e_cal_generate_instances_for_object (ECal *ecal,
2837 icalcomponent *icalcomp,
2840 ECalRecurInstanceFn cb,
2843 ECalComponent *comp;
2847 GList *instances = NULL;
2848 ECalComponentDateTime datetime;
2849 icaltimezone *start_zone = NULL;
2850 struct instances_info *instances_hold;
2851 gboolean is_single_instance = FALSE;
2853 g_return_if_fail (E_IS_CAL (ecal));
2854 g_return_if_fail (start >= 0);
2855 g_return_if_fail (end >= 0);
2856 g_return_if_fail (cb != NULL);
2858 comp = e_cal_component_new ();
2859 e_cal_component_set_icalcomponent (comp, icalcomponent_new_clone (icalcomp));
2861 if (!e_cal_component_has_recurrences (comp))
2862 is_single_instance = TRUE;
2864 /*If the backend stores it as individual instances and does not
2865 * have a master object - do not expand*/
2866 if (is_single_instance || e_cal_get_static_capability (ecal, CAL_STATIC_CAPABILITY_RECURRENCES_NO_MASTER)) {
2868 /*return the same instance */
2869 result = (* cb) (comp, icaltime_as_timet_with_zone (icalcomponent_get_dtstart (icalcomp), ecal->priv->default_zone),
2870 icaltime_as_timet_with_zone (icalcomponent_get_dtend (icalcomp), ecal->priv->default_zone), cb_data);
2871 g_object_unref (comp);
2875 e_cal_component_get_uid (comp, &uid);
2876 rid = e_cal_component_get_recurid_as_string (comp);
2878 /* Get the start timezone */
2879 e_cal_component_get_dtstart (comp, &datetime);
2881 e_cal_get_timezone (ecal, datetime.tzid, &start_zone, NULL);
2884 e_cal_component_free_datetime (&datetime);
2886 instances_hold = g_new0 (struct instances_info, 1);
2887 instances_hold->instances = &instances;
2888 instances_hold->start_zone = start_zone;
2890 /* generate all instances in the given time range */
2891 generate_instances (ecal, start, end, uid, add_instance, instances_hold);
2893 instances = *(instances_hold->instances);
2894 /* now only return back the instances for the given object */
2896 while (instances != NULL) {
2897 struct comp_instance *ci;
2898 gchar *instance_rid = NULL;
2900 ci = instances->data;
2903 instance_rid = e_cal_component_get_recurid_as_string (ci->comp);
2906 if (instance_rid && *instance_rid && strcmp (rid, instance_rid) == 0)
2907 result = (* cb) (ci->comp, ci->start, ci->end, cb_data);
2909 result = (* cb) (ci->comp, ci->start, ci->end, cb_data);
2912 /* remove instance from list */
2913 instances = g_list_remove (instances, ci);
2914 g_object_unref (ci->comp);
2916 g_free (instance_rid);
2920 g_object_unref (comp);
2921 g_free (instances_hold);
2925 /* Builds a list of ECalComponentAlarms structures */
2927 build_component_alarms_list (ECal *ecal,
2932 GSList *comp_alarms;
2937 for (l = object_list; l != NULL; l = l->next) {
2938 ECalComponent *comp;
2939 ECalComponentAlarms *alarms;
2940 ECalComponentAlarmAction omit[] = {-1};
2942 comp = e_cal_component_new ();
2943 if (!e_cal_component_set_icalcomponent (comp, icalcomponent_new_clone (l->data))) {
2944 g_object_unref (G_OBJECT (comp));
2948 alarms = e_cal_util_generate_alarms_for_comp (comp, start, end, omit, e_cal_resolve_tzid_cb,
2949 ecal, ecal->priv->default_zone);
2951 comp_alarms = g_slist_prepend (comp_alarms, alarms);
2958 * e_cal_get_alarms_in_range:
2959 * @ecal: A calendar client.
2960 * @start: Start time for query.
2961 * @end: End time for query.
2963 * Queries a calendar for the alarms that trigger in the specified range of
2966 * Returns: A list of #ECalComponentAlarms structures. This should be freed
2967 * using the #e_cal_free_alarms() function, or by freeing each element
2968 * separately with #e_cal_component_alarms_free() and then freeing the list with
2971 * Deprecated: 3.2: This function has been dropped completely.
2974 e_cal_get_alarms_in_range (ECal *ecal,
2980 gchar *sexp, *iso_start, *iso_end;
2981 GList *object_list = NULL;
2983 g_return_val_if_fail (ecal != NULL, NULL);
2984 g_return_val_if_fail (E_IS_CAL (ecal), NULL);
2987 g_return_val_if_fail (priv->load_state == E_CAL_LOAD_LOADED, NULL);
2989 g_return_val_if_fail (start >= 0 && end >= 0, NULL);
2990 g_return_val_if_fail (start <= end, NULL);
2992 iso_start = isodate_from_time_t (start);
2996 iso_end = isodate_from_time_t (end);
3002 /* build the query string */
3003 sexp = g_strdup_printf ("(has-alarms-in-range? (make-time \"%s\") (make-time \"%s\"))",
3004 iso_start, iso_end);
3008 /* execute the query on the server */
3009 if (!e_cal_get_object_list (ecal, sexp, &object_list, NULL)) {
3014 alarms = build_component_alarms_list (ecal, object_list, start, end);
3016 g_list_foreach (object_list, (GFunc) icalcomponent_free, NULL);
3017 g_list_free (object_list);
3024 * e_cal_free_alarms:
3025 * @comp_alarms: A list of #ECalComponentAlarms structures.
3027 * Frees a list of #ECalComponentAlarms structures as returned by
3028 * e_cal_get_alarms_in_range().
3030 * Deprecated: 3.2: This function has been dropped completely.
3033 e_cal_free_alarms (GSList *comp_alarms)
3037 for (l = comp_alarms; l; l = l->next) {
3038 ECalComponentAlarms *alarms;
3042 e_cal_component_alarms_free (alarms);
3044 g_warn_if_reached ();
3047 g_slist_free (comp_alarms);
3051 * e_cal_get_alarms_for_object:
3052 * @ecal: A calendar client.
3053 * @id: Unique identifier for a calendar component.
3054 * @start: Start time for query.
3055 * @end: End time for query.
3056 * @alarms: Return value for the component's alarm instances. Will return NULL
3057 * if no instances occur within the specified time range. This should be freed
3058 * using the e_cal_component_alarms_free() function.
3060 * Queries a calendar for the alarms of a particular object that trigger in the
3061 * specified range of time.
3063 * Returns: TRUE on success, FALSE if the object was not found.
3065 * Deprecated: 3.2: This function has been dropped completely.
3068 e_cal_get_alarms_for_object (ECal *ecal,
3069 const ECalComponentId *id,
3072 ECalComponentAlarms **alarms)
3075 icalcomponent *icalcomp;
3076 ECalComponent *comp;
3077 ECalComponentAlarmAction omit[] = {-1};
3079 g_return_val_if_fail (alarms != NULL, FALSE);
3082 g_return_val_if_fail (ecal != NULL, FALSE);
3083 g_return_val_if_fail (E_IS_CAL (ecal), FALSE);
3086 g_return_val_if_fail (priv->load_state == E_CAL_LOAD_LOADED, FALSE);
3088 g_return_val_if_fail (id != NULL, FALSE);
3089 g_return_val_if_fail (start >= 0 && end >= 0, FALSE);
3090 g_return_val_if_fail (start <= end, FALSE);
3092 if (!e_cal_get_object (ecal, id->uid, id->rid, &icalcomp, NULL))
3097 comp = e_cal_component_new ();
3098 if (!e_cal_component_set_icalcomponent (comp, icalcomp)) {
3099 icalcomponent_free (icalcomp);
3100 g_object_unref (G_OBJECT (comp));
3104 *alarms = e_cal_util_generate_alarms_for_comp (comp, start, end, omit, e_cal_resolve_tzid_cb,
3105 ecal, priv->default_zone);
3111 * e_cal_discard_alarm
3112 * @ecal: A calendar ecal.
3113 * @comp: The component to discard the alarm from.
3114 * @auid: Unique identifier of the alarm to be discarded.
3115 * @error: Placeholder for error information.
3117 * Tells the calendar backend to get rid of the alarm identified by the
3118 * @auid argument in @comp. Some backends might remove the alarm or
3119 * update internal information about the alarm be discarded, or, like
3120 * the file backend does, ignore the operation.
3122 * CALOBJ_MOD_ONLY_THIS is not supported in this call.
3124 * Returns: TRUE if the operation was successful, FALSE otherwise.
3126 * Deprecated: 3.2: Use e_cal_client_discard_alarm_sync() instead.
3129 e_cal_discard_alarm (ECal *ecal,
3130 ECalComponent *comp,
3136 e_return_error_if_fail (ecal != NULL, E_CALENDAR_STATUS_INVALID_ARG);
3137 e_return_error_if_fail (E_IS_CAL (ecal), E_CALENDAR_STATUS_INVALID_ARG);
3138 e_return_error_if_fail (comp != NULL, E_CALENDAR_STATUS_INVALID_ARG);
3139 e_return_error_if_fail (E_IS_CAL_COMPONENT (comp), E_CALENDAR_STATUS_INVALID_ARG);
3140 e_return_error_if_fail (auid != NULL, E_CALENDAR_STATUS_INVALID_ARG);
3142 e_return_error_if_fail (priv->gdbus_cal, E_CALENDAR_STATUS_REPOSITORY_OFFLINE);
3144 if (priv->load_state != E_CAL_LOAD_LOADED) {
3145 E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error);
3148 E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_NOT_SUPPORTED, error);
3151 typedef struct _ForeachTZIDCallbackData ForeachTZIDCallbackData;
3152 struct _ForeachTZIDCallbackData {
3154 GHashTable *timezone_hash;
3155 gboolean include_all_timezones;
3159 /* This adds the VTIMEZONE given by the TZID parameter to the GHashTable in
3162 foreach_tzid_callback (icalparameter *param,
3165 ForeachTZIDCallbackData *data = cbdata;
3168 icaltimezone *zone = NULL;
3169 icalcomponent *vtimezone_comp;
3170 gchar *vtimezone_as_string;
3172 priv = data->ecal->priv;
3174 /* Get the TZID string from the parameter. */
3175 tzid = icalparameter_get_tzid (param);
3179 /* Check if we've already added it to the GHashTable. */
3180 if (g_hash_table_lookup (data->timezone_hash, tzid))
3183 if (data->include_all_timezones) {
3184 if (!e_cal_get_timezone (data->ecal, tzid, &zone, NULL)) {
3185 data->success = FALSE;
3189 /* Check if it is in our cache. If it is, it must already be
3190 * on the server so return. */
3191 if (g_hash_table_lookup (priv->timezones, tzid))
3194 /* Check if it is a builtin timezone. If it isn't, return. */
3195 zone = icaltimezone_get_builtin_timezone_from_tzid (tzid);
3200 /* Convert it to a string and add it to the hash. */
3201 vtimezone_comp = icaltimezone_get_component (zone);
3202 if (!vtimezone_comp)
3205 vtimezone_as_string = icalcomponent_as_ical_string_r (vtimezone_comp);
3207 g_hash_table_insert (data->timezone_hash, (gchar *) tzid,
3208 vtimezone_as_string);
3211 /* This appends the value string to the GString given in data. */
3213 append_timezone_string (gpointer key,
3217 GString *vcal_string = data;
3219 g_string_append (vcal_string, value);
3223 /* This simply frees the hash values. */
3225 free_timezone_string (gpointer key,
3232 /* This converts the VEVENT/VTODO to a string. If include_all_timezones is
3233 * TRUE, it includes all the VTIMEZONE components needed for the VEVENT/VTODO.
3234 * If not, it only includes builtin timezones that may not be on the server.
3236 * To do that we check every TZID in the component to see if it is a builtin
3237 * timezone. If it is, we see if it it in our cache. If it is in our cache,
3238 * then we know the server already has it and we don't need to send it.
3239 * If it isn't in our cache, then we need to send it to the server.
3240 * If we need to send any timezones to the server, then we have to create a
3241 * complete VCALENDAR object, otherwise we can just send a single VEVENT/VTODO
3244 e_cal_get_component_as_string_internal (ECal *ecal,
3245 icalcomponent *icalcomp,
3246 gboolean include_all_timezones)
3248 GHashTable *timezone_hash;
3249 GString *vcal_string;
3250 gint initial_vcal_string_len;
3251 ForeachTZIDCallbackData cbdata;
3254 timezone_hash = g_hash_table_new (g_str_hash, g_str_equal);
3256 /* Add any timezones needed to the hash. We use a hash since we only
3257 * want to add each timezone once at most. */
3259 cbdata.timezone_hash = timezone_hash;
3260 cbdata.include_all_timezones = include_all_timezones;
3261 cbdata.success = TRUE;
3262 icalcomponent_foreach_tzid (icalcomp, foreach_tzid_callback, &cbdata);
3263 if (!cbdata.success) {
3264 g_hash_table_foreach (timezone_hash, free_timezone_string,
3269 /* Create the start of a VCALENDAR, to add the VTIMEZONES to,
3270 * and remember its length so we know if any VTIMEZONEs get added. */
3271 vcal_string = g_string_new (NULL);
3272 g_string_append (vcal_string,
3274 "PRODID:-//Ximian//NONSGML Evolution Calendar//EN\n"
3276 "METHOD:PUBLISH\n");
3277 initial_vcal_string_len = vcal_string->len;
3279 /* Now concatenate all the timezone strings. This also frees the
3280 * timezone strings as it goes. */
3281 g_hash_table_foreach (timezone_hash, append_timezone_string,
3284 /* Get the string for the VEVENT/VTODO. */
3285 obj_string = icalcomponent_as_ical_string_r (icalcomp);
3287 /* If there were any timezones to send, create a complete VCALENDAR,
3288 * else just send the VEVENT / VTODO string. */
3289 if (!include_all_timezones
3290 && vcal_string->len == initial_vcal_string_len) {
3291 g_string_free (vcal_string, TRUE);
3293 g_string_append (vcal_string, obj_string);
3294 g_string_append (vcal_string, "END:VCALENDAR\n");
3295 g_free (obj_string);
3296 obj_string = vcal_string->str;
3297 g_string_free (vcal_string, FALSE);
3300 g_hash_table_destroy (timezone_hash);
3306 * e_cal_get_component_as_string:
3307 * @ecal: A calendar client.
3308 * @icalcomp: A calendar component object.
3310 * Gets a calendar component as an iCalendar string, with a toplevel
3311 * VCALENDAR component and all VTIMEZONEs needed for the component.
3313 * Returns: the component as a complete iCalendar string, or NULL on
3314 * failure. The string should be freed after use.
3316 * Deprecated: 3.2: Use e_cal_client_get_component_as_string() instead.
3319 e_cal_get_component_as_string (ECal *ecal,
3320 icalcomponent *icalcomp)
3322 return e_cal_get_component_as_string_internal (ecal, icalcomp, TRUE);
3326 * e_cal_create_object:
3327 * @ecal: A calendar client.
3328 * @icalcomp: The component to create.
3329 * @uid: Return value for the UID assigned to the new component by the calendar backend.
3330 * @error: Placeholder for error information.
3332 * Requests the calendar backend to create the object specified by the @icalcomp
3333 * argument. Some backends would assign a specific UID to the newly created object,
3334 * in those cases that UID would be returned in the @uid argument.
3336 * Returns: TRUE if the operation was successful, FALSE otherwise.
3338 * Deprecated: 3.2: Use e_cal_client_create_object_sync() instead.
3341 e_cal_create_object (ECal *ecal,
3342 icalcomponent *icalcomp,
3347 gchar *obj, *gdbus_obj = NULL;
3348 const gchar *strv[2];
3349 gchar **muids = NULL;
3351 e_return_error_if_fail (E_IS_CAL (ecal), E_CALENDAR_STATUS_INVALID_ARG);
3352 e_return_error_if_fail (icalcomp != NULL, E_CALENDAR_STATUS_INVALID_ARG);
3353 e_return_error_if_fail (icalcomponent_is_valid (icalcomp), E_CALENDAR_STATUS_INVALID_ARG);
3355 e_return_error_if_fail (priv->gdbus_cal, E_CALENDAR_STATUS_REPOSITORY_OFFLINE);
3357 if (priv->load_state != E_CAL_LOAD_LOADED) {
3358 E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error);
3361 obj = icalcomponent_as_ical_string_r (icalcomp);
3362 strv[0] = e_util_ensure_gdbus_string (obj, &gdbus_obj);
3365 if (!e_gdbus_cal_call_create_objects_sync (priv->gdbus_cal, strv, &muids, NULL, error)) {
3369 E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_DBUS_EXCEPTION, error);
3376 E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_OTHER_ERROR, error);
3378 icalcomponent_set_uid (icalcomp, muids[0]);
3381 *uid = g_strdup (muids[0]);
3385 E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_OK, error);
3390 * e_cal_modify_object:
3391 * @ecal: A calendar client.
3392 * @icalcomp: Component to modify.
3393 * @mod: Type of modification.
3394 * @error: Placeholder for error information.
3396 * Requests the calendar backend to modify an existing object. If the object
3397 * does not exist on the calendar, an error will be returned.
3399 * For recurrent appointments, the @mod argument specifies what to modify,
3400 * if all instances (CALOBJ_MOD_ALL), a single instance (CALOBJ_MOD_THIS),
3401 * or a specific set of instances (CALOBJ_MOD_THISNADPRIOR and
3402 * CALOBJ_MOD_THISANDFUTURE).
3404 * Returns: TRUE if the operation was successful, FALSE otherwise.
3406 * Deprecated: 3.2: Use e_cal_client_modify_object_sync() instead.
3409 e_cal_modify_object (ECal *ecal,
3410 icalcomponent *icalcomp,
3418 e_return_error_if_fail (E_IS_CAL (ecal), E_CALENDAR_STATUS_INVALID_ARG);
3419 e_return_error_if_fail (icalcomp, E_CALENDAR_STATUS_INVALID_ARG);
3420 e_return_error_if_fail (icalcomponent_is_valid (icalcomp), E_CALENDAR_STATUS_INVALID_ARG);
3422 case CALOBJ_MOD_THIS:
3423 case CALOBJ_MOD_THISANDPRIOR:
3424 case CALOBJ_MOD_THISANDFUTURE:
3425 case CALOBJ_MOD_ALL:
3428 e_return_error_if_fail ("valid CalObjModType" && FALSE, E_CALENDAR_STATUS_INVALID_ARG);
3431 e_return_error_if_fail (priv->gdbus_cal, E_CALENDAR_STATUS_REPOSITORY_OFFLINE);
3433 if (priv->load_state != E_CAL_LOAD_LOADED) {
3434 E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error);
3437 obj = icalcomponent_as_ical_string_r (icalcomp);
3439 strv = e_gdbus_cal_encode_modify_objects (&objs, mod);
3440 if (!e_gdbus_cal_call_modify_objects_sync (priv->gdbus_cal, (const gchar * const *) strv, NULL, error)) {
3444 E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_DBUS_EXCEPTION, error);
3450 E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_OK, error);
3454 * e_cal_remove_object_with_mod:
3455 * @ecal: A calendar client.
3456 * @uid: UID of the object to remove.
3457 * @rid: Recurrence ID of the specific recurrence to remove.
3458 * @mod: Type of removal.
3459 * @error: Placeholder for error information.
3461 * This function allows the removal of instances of a recurrent
3462 * appointment. If what you want is to remove all instances, use
3463 * e_cal_remove_object instead.
3465 * By using a combination of the @uid, @rid and @mod arguments, you
3466 * can remove specific instances. @uid is mandatory. Empty or NULL
3467 * @rid selects the parent appointment (the one with the recurrence
3468 * rule). A non-empty @rid selects the recurrence at the time specified
3469 * in @rid, using the same time zone as the parent appointment's start
3472 * The exact semantic then depends on @mod. CALOBJ_MOD_THIS,
3473 * CALOBJ_MOD_THISANDPRIOR, CALOBJ_MOD_THISANDFUTURE and
3474 * CALOBJ_MOD_ALL ensure that the event does not recur at the selected
3475 * instance(s). This is done by removing any detached recurrence
3476 * matching the selection criteria and modifying the parent
3477 * appointment (adding EXDATE, adjusting recurrence rules, etc.). It
3478 * is not an error if @uid+@rid do not match an existing instance.
3480 * If not all instances are removed, the client will get a
3481 * "obj_modified" signal for the parent appointment, while it will get
3482 * an "obj_removed" signal when all instances are removed.
3484 * CALOBJ_MOD_ONLY_THIS changes the semantic of CALOBJ_MOD_THIS: @uid
3485 * and @rid must select an existing instance. That instance is
3486 * removed without modifying the parent appointment. In other words,
3487 * e_cal_remove_object_with_mod(CALOBJ_MOD_ONLY_THIS) is the inverse
3488 * operation for adding a detached recurrence. The client is
3489 * always sent an "obj_removed" signal.
3491 * Note that not all backends support CALOBJ_MOD_ONLY_THIS. Check for
3492 * the CAL_STATIC_CAPABILITY_REMOVE_ONLY_THIS capability before using
3493 * it. Previous releases did not check consistently for unknown
3494 * @mod values, using it with them may have had unexpected results.
3496 * Returns: TRUE if the operation was successful, FALSE otherwise.
3498 * Deprecated: 3.2: Use e_cal_client_remove_object_sync() instead.
3501 e_cal_remove_object_with_mod (ECal *ecal,
3512 e_return_error_if_fail (E_IS_CAL (ecal), E_CALENDAR_STATUS_INVALID_ARG);
3513 e_return_error_if_fail (uid, E_CALENDAR_STATUS_INVALID_ARG);
3515 case CALOBJ_MOD_THIS:
3516 case CALOBJ_MOD_THISANDPRIOR:
3517 case CALOBJ_MOD_THISANDFUTURE:
3518 case CALOBJ_MOD_ONLY_THIS:
3519 case CALOBJ_MOD_ALL:
3522 e_return_error_if_fail ("valid CalObjModType" && FALSE, E_CALENDAR_STATUS_INVALID_ARG);
3525 e_return_error_if_fail (priv->gdbus_cal, E_CALENDAR_STATUS_REPOSITORY_OFFLINE);
3527 if (priv->load_state != E_CAL_LOAD_LOADED) {
3528 E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error);
3531 id.uid = (gchar *) uid;
3532 id.rid = (gchar *) rid;
3534 strv = e_gdbus_cal_encode_remove_objects (&ids, mod);
3535 if (!e_gdbus_cal_call_remove_objects_sync (priv->gdbus_cal, (const gchar * const *) strv, NULL, error)) {
3538 E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_DBUS_EXCEPTION, error);
3543 E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_OK, error);
3547 * e_cal_remove_object:
3548 * @ecal: A calendar client.
3549 * @uid: Unique identifier of the calendar component to remove.
3550 * @error: Placeholder for error information.
3552 * Asks a calendar to remove all components with the given UID.
3553 * If more control of the removal is desired, then use e_cal_remove_object_with_mod().
3554 * If the server is able to remove the component(s), all clients will
3555 * be notified and they will emit the "obj_removed" signal.
3557 * Returns: %TRUE if successful, %FALSE otherwise.
3559 * Deprecated: 3.2: Use e_cal_client_remove_object_sync() instead, with rid set to NULL and mod set to CALOBJ_MOD_ALL.
3562 e_cal_remove_object (ECal *ecal,
3566 e_return_error_if_fail (ecal && E_IS_CAL (ecal), E_CALENDAR_STATUS_INVALID_ARG);
3567 e_return_error_if_fail (uid, E_CALENDAR_STATUS_INVALID_ARG);
3569 return e_cal_remove_object_with_mod (ecal, uid, NULL, CALOBJ_MOD_ALL, error);
3573 * e_cal_receive_objects:
3574 * @ecal: A calendar client.
3575 * @icalcomp: An icalcomponent.
3576 * @error: Placeholder for error information.
3578 * Makes the backend receive the set of iCalendar objects specified in the
3579 * @icalcomp argument. This is used for iTIP confirmation/cancellation
3580 * messages for scheduled meetings.
3582 * Returns: %TRUE if successful, %FALSE otherwise.
3584 * Deprecated: 3.2: Use e_cal_client_receive_objects_sync() instead.
3587 e_cal_receive_objects (ECal *ecal,
3588 icalcomponent *icalcomp,
3592 gchar *obj, *gdbus_obj = NULL;
3594 e_return_error_if_fail (E_IS_CAL (ecal), E_CALENDAR_STATUS_INVALID_ARG);
3595 e_return_error_if_fail (icalcomp, E_CALENDAR_STATUS_INVALID_ARG);
3596 e_return_error_if_fail (icalcomponent_is_valid (icalcomp), E_CALENDAR_STATUS_INVALID_ARG);
3598 e_return_error_if_fail (priv->gdbus_cal, E_CALENDAR_STATUS_REPOSITORY_OFFLINE);
3600 if (priv->load_state != E_CAL_LOAD_LOADED) {
3601 E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error);
3604 obj = icalcomponent_as_ical_string_r (icalcomp);
3605 if (!e_gdbus_cal_call_receive_objects_sync (priv->gdbus_cal, e_util_ensure_gdbus_string (obj, &gdbus_obj), NULL, error)) {
3609 E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_DBUS_EXCEPTION, error);
3615 E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_OK, error);
3619 * e_cal_send_objects:
3620 * @ecal: A calendar client.
3621 * @icalcomp: An icalcomponent.
3622 * @users: List of users to send the objects to.
3623 * @modified_icalcomp: Return value for the icalcomponent after all the operations
3625 * @error: Placeholder for error information.
3627 * Requests a calendar backend to send meeting information to the specified list
3630 * Returns: TRUE if the operation was successful, FALSE otherwise.
3632 * Deprecated: 3.2: Use e_cal_client_send_objects_sync() instead.
3635 e_cal_send_objects (ECal *ecal,
3636 icalcomponent *icalcomp,
3638 icalcomponent **modified_icalcomp,
3642 ECalendarStatus status;
3643 gchar **out_array = NULL;
3644 gchar *obj, *gdbus_obj = NULL;
3646 e_return_error_if_fail (users != NULL, E_CALENDAR_STATUS_INVALID_ARG);
3647 e_return_error_if_fail (modified_icalcomp != NULL, E_CALENDAR_STATUS_INVALID_ARG);
3648 e_return_error_if_fail (icalcomp != NULL, E_CALENDAR_STATUS_INVALID_ARG);
3649 e_return_error_if_fail (icalcomponent_is_valid (icalcomp), E_CALENDAR_STATUS_INVALID_ARG);
3650 e_return_error_if_fail (E_IS_CAL (ecal), E_CALENDAR_STATUS_INVALID_ARG);
3652 e_return_error_if_fail (priv->gdbus_cal, E_CALENDAR_STATUS_REPOSITORY_OFFLINE);
3654 *modified_icalcomp = NULL;
3656 if (priv->load_state != E_CAL_LOAD_LOADED) {
3657 E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error);
3660 obj = icalcomponent_as_ical_string_r (icalcomp);
3661 if (!e_gdbus_cal_call_send_objects_sync (priv->gdbus_cal, e_util_ensure_gdbus_string (obj, &gdbus_obj), &out_array, NULL, error)) {
3665 E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_DBUS_EXCEPTION, error);
3671 status = E_CALENDAR_STATUS_OK;
3673 GSList *susers = NULL, *iter;
3674 gchar *object = NULL;
3676 e_return_error_if_fail (e_gdbus_cal_decode_send_objects ((const gchar * const *) out_array, &object, &susers), E_CALENDAR_STATUS_OTHER_ERROR);
3678 *modified_icalcomp = icalparser_parse_string (object);
3679 if (!(*modified_icalcomp))
3680 status = E_CALENDAR_STATUS_INVALID_OBJECT;
3683 for (iter = susers; iter; iter = iter->next) {
3684 *users = g_list_append (*users, iter->data);
3686 /* do not call g_free() on item's data of susers, it's moved to *users */
3687 g_slist_free (susers);
3688 g_strfreev (out_array);
3691 E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_OTHER_ERROR, error);
3693 E_CALENDAR_CHECK_STATUS (status, error);
3697 * e_cal_get_timezone:
3698 * @ecal: A calendar client.
3699 * @tzid: ID of the timezone to retrieve.
3700 * @zone: Return value for the timezone.
3701 * @error: Placeholder for error information.
3703 * Retrieves a timezone object from the calendar backend.
3705 * Returns: TRUE if the operation was successful, FALSE otherwise.
3707 * Deprecated: 3.2: Use e_cal_client_get_timezone_sync() instead.
3710 e_cal_get_timezone (ECal *ecal,
3712 icaltimezone **zone,
3716 ECalendarStatus status = E_CALENDAR_STATUS_OK;
3717 icalcomponent *icalcomp = NULL;
3718 gchar *object = NULL, *gdbus_tzid = NULL;
3719 const gchar *systzid = NULL;
3721 e_return_error_if_fail (zone, E_CALENDAR_STATUS_INVALID_ARG);
3722 e_return_error_if_fail (E_IS_CAL (ecal), E_CALENDAR_STATUS_INVALID_ARG);
3724 e_return_error_if_fail (priv->gdbus_cal, E_CALENDAR_STATUS_REPOSITORY_OFFLINE);
3727 if (priv->load_state != E_CAL_LOAD_LOADED) {
3728 E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error);
3731 /* Check for well known zones and in the cache */
3732 /* If tzid is NULL or "" we return NULL, since it is a 'local time'. */
3733 if (!tzid || !tzid[0]) {
3734 E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_OK, error);
3738 /* If it is UTC, we return the special UTC timezone. */
3739 if (!strcmp (tzid, "UTC")) {
3740 *zone = icaltimezone_get_utc_timezone ();
3742 /* See if we already have it in the cache. */
3743 *zone = g_hash_table_lookup (priv->timezones, tzid);
3748 E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_OK, error);
3752 * Try to replace the original time zone with a more complete
3753 * and/or potentially updated system time zone. Note that this
3754 * also applies to TZIDs which match system time zones exactly:
3755 * they are extracted via icaltimezone_get_builtin_timezone_from_tzid()
3756 * below without a roundtrip to the backend.
3758 systzid = e_cal_match_tzid (tzid);
3760 /* call the backend */
3761 if (!e_gdbus_cal_call_get_timezone_sync (priv->gdbus_cal, e_util_ensure_gdbus_string (tzid, &gdbus_tzid), &object, NULL, error)) {
3762 g_free (gdbus_tzid);
3765 E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_DBUS_EXCEPTION, error);
3768 g_free (gdbus_tzid);
3770 icalcomp = icalparser_parse_string (object);
3772 status = E_CALENDAR_STATUS_INVALID_OBJECT;
3776 * Use built-in time zone *and* rename it:
3777 * if the caller is asking for a TZID=FOO,
3778 * then likely because it has an event with
3779 * such a TZID. Returning a different TZID
3780 * would lead to broken VCALENDARs in the
3783 icaltimezone *syszone = icaltimezone_get_builtin_timezone_from_tzid (systzid);
3785 gboolean found = FALSE;
3788 icalcomp = icalcomponent_new_clone (icaltimezone_get_component (syszone));
3789 prop = icalcomponent_get_first_property (icalcomp,
3791 while (!found && prop) {
3792 if (icalproperty_isa (prop) == ICAL_TZID_PROPERTY) {
3793 icalproperty_set_value_from_string(prop, tzid, "NO");
3796 prop = icalcomponent_get_next_property (icalcomp,
3800 status = E_CALENDAR_STATUS_INVALID_OBJECT;
3806 E_CALENDAR_CHECK_STATUS (status, error);
3809 *zone = icaltimezone_new ();
3810 if (!icaltimezone_set_component (*zone, icalcomp)) {
3811 icaltimezone_free (*zone, 1);
3813 E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_OBJECT_NOT_FOUND, error);
3816 /* Now add it to the cache, to avoid the server call in future. */
3817 g_hash_table_insert (priv->timezones, (gpointer) icaltimezone_get_tzid (*zone), *zone);
3824 * e_cal_add_timezone
3825 * @ecal: A calendar client.
3826 * @izone: The timezone to add.
3827 * @error: Placeholder for error information.
3829 * Add a VTIMEZONE object to the given calendar.
3831 * Returns: TRUE if successful, FALSE otherwise.
3833 * Deprecated: 3.2: Use e_cal_client_add_timezone_sync() instead.
3836 e_cal_add_timezone (ECal *ecal,
3837 icaltimezone *izone,
3841 gchar *tzobj, *gdbus_tzobj = NULL;
3842 icalcomponent *icalcomp;
3844 e_return_error_if_fail (E_IS_CAL (ecal), E_CALENDAR_STATUS_INVALID_ARG);
3845 e_return_error_if_fail (izone, E_CALENDAR_STATUS_INVALID_ARG);
3847 e_return_error_if_fail (priv->gdbus_cal, E_CALENDAR_STATUS_REPOSITORY_OFFLINE);
3849 if (priv->load_state != E_CAL_LOAD_LOADED) {
3850 E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error);
3853 /* Make sure we have a valid component - UTC doesn't, nor do
3854 * we really have to add it */
3855 if (izone == icaltimezone_get_utc_timezone ()) {
3856 E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_OK, error);
3859 icalcomp = icaltimezone_get_component (izone);
3861 E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_INVALID_ARG, error);
3864 /* convert icaltimezone into a string */
3865 tzobj = icalcomponent_as_ical_string_r (icalcomp);
3867 /* call the backend */
3868 if (!e_gdbus_cal_call_add_timezone_sync (priv->gdbus_cal, e_util_ensure_gdbus_string (tzobj, &gdbus_tzobj), NULL, error)) {
3870 g_free (gdbus_tzobj);
3872 E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_DBUS_EXCEPTION, error);
3876 g_free (gdbus_tzobj);
3878 E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_OK, error);
3883 * @ecal: A calendar client.
3884 * @sexp: S-expression representing the query.
3885 * @query: (out): Return value for the new query.
3886 * @error: Placeholder for error information.
3888 * Creates a live query object from a loaded calendar.
3890 * Returns: A query object that will emit notification signals as calendar
3891 * components are added and removed from the query in the server.
3893 * Deprecated: 3.2: Use e_cal_client_get_view_sync() instead.
3896 e_cal_get_query (ECal *ecal,
3902 ECalendarStatus status;
3903 gchar *query_path = NULL, *gdbus_sexp = NULL;
3904 EGdbusCalView *gdbus_calview;
3906 e_return_error_if_fail (sexp, E_CALENDAR_STATUS_INVALID_ARG);
3907 e_return_error_if_fail (query, E_CALENDAR_STATUS_INVALID_ARG);
3908 e_return_error_if_fail (E_IS_CAL (ecal), E_CALENDAR_STATUS_INVALID_ARG);
3910 e_return_error_if_fail (priv->gdbus_cal, E_CALENDAR_STATUS_REPOSITORY_OFFLINE);
3913 if (priv->load_state != E_CAL_LOAD_LOADED) {
3914 E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error);
3917 if (!e_gdbus_cal_call_get_view_sync (priv->gdbus_cal, e_util_ensure_gdbus_string (sexp, &gdbus_sexp), &query_path, NULL, error)) {
3918 g_free (gdbus_sexp);
3920 E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_DBUS_EXCEPTION, error);
3923 g_free (gdbus_sexp);
3925 status = E_CALENDAR_STATUS_OK;
3927 gdbus_calview = e_gdbus_cal_view_proxy_new_sync (g_dbus_proxy_get_connection (G_DBUS_PROXY (cal_factory_proxy)),
3928 G_DBUS_PROXY_FLAGS_NONE,
3929 CALENDAR_DBUS_SERVICE_NAME,
3934 g_free (query_path);
3936 if (!gdbus_calview) {
3938 status = E_CALENDAR_STATUS_OTHER_ERROR;
3940 *query = _e_cal_view_new (ecal, gdbus_calview);
3941 g_object_unref (gdbus_calview);
3944 E_CALENDAR_CHECK_STATUS (status, error);
3948 * e_cal_set_default_timezone:
3949 * @ecal: A calendar client.
3950 * @zone: A timezone object.
3951 * @error: Placeholder for error information.
3953 * Sets the default timezone on the calendar. This should be called before opening
3956 * Returns: TRUE if the operation was successful, FALSE otherwise.
3958 * Deprecated: 3.2: Use e_cal_client_set_default_timezone() instead.
3961 e_cal_set_default_timezone (ECal *ecal,
3967 e_return_error_if_fail (E_IS_CAL (ecal), E_CALENDAR_STATUS_INVALID_ARG);
3968 e_return_error_if_fail (zone, E_CALENDAR_STATUS_INVALID_ARG);
3970 e_return_error_if_fail (priv->gdbus_cal, E_CALENDAR_STATUS_REPOSITORY_OFFLINE);
3972 /* If the same timezone is already set, we don't have to do anything. */
3973 if (priv->default_zone == zone)
3976 /* FIXME Adding it to the server to change the tzid */
3977 if (!icaltimezone_get_component (zone)) {
3978 E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_INVALID_ARG, error);
3981 priv->default_zone = zone;
3983 E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_OK, error);
3987 * e_cal_get_error_message
3988 * @status: A status code.
3990 * Gets an error message for the given status code.
3992 * Returns: the error message.
3994 * Deprecated: 3.2: Use e_cal_client_error_to_string() instead.
3997 e_cal_get_error_message (ECalendarStatus status)
4000 case E_CALENDAR_STATUS_INVALID_ARG :
4001 return _("Invalid argument");
4002 case E_CALENDAR_STATUS_BUSY :
4003 return _("Backend is busy");
4004 case E_CALENDAR_STATUS_REPOSITORY_OFFLINE :
4005 return _("Repository is offline");
4006 case E_CALENDAR_STATUS_NO_SUCH_CALENDAR :
4007 return _("No such calendar");
4008 case E_CALENDAR_STATUS_OBJECT_NOT_FOUND :
4009 return _("Object not found");
4010 case E_CALENDAR_STATUS_INVALID_OBJECT :
4011 return _("Invalid object");
4012 case E_CALENDAR_STATUS_URI_NOT_LOADED :
4013 return _("URI not loaded");
4014 case E_CALENDAR_STATUS_URI_ALREADY_LOADED :
4015 return _("URI already loaded");
4016 case E_CALENDAR_STATUS_PERMISSION_DENIED :
4017 return _("Permission denied");
4018 case E_CALENDAR_STATUS_UNKNOWN_USER :
4019 return _("Unknown User");
4020 case E_CALENDAR_STATUS_OBJECT_ID_ALREADY_EXISTS :
4021 return _("Object ID already exists");
4022 case E_CALENDAR_STATUS_PROTOCOL_NOT_SUPPORTED :
4023 return _("Protocol not supported");
4024 case E_CALENDAR_STATUS_CANCELLED :
4025 return _("Operation has been canceled");
4026 case E_CALENDAR_STATUS_COULD_NOT_CANCEL :
4027 return _("Could not cancel operation");
4028 case E_CALENDAR_STATUS_AUTHENTICATION_FAILED :
4029 return _("Authentication failed");
4030 case E_CALENDAR_STATUS_AUTHENTICATION_REQUIRED :
4031 return _("Authentication required");
4032 case E_CALENDAR_STATUS_DBUS_EXCEPTION :
4033 return _("A D-Bus exception has occurred");
4034 case E_CALENDAR_STATUS_OTHER_ERROR :
4035 return _("Unknown error");
4036 case E_CALENDAR_STATUS_OK :
4037 return _("No error");
4038 case E_CALENDAR_STATUS_NOT_SUPPORTED :
4039 /* Translators: The string for NOT_SUPPORTED error */
4040 return _("Not supported");
4042 /* ignore everything else */