diff options
author | Ettore Perazzoli <ettore@src.gnome.org> | 2003-10-22 02:49:34 +0800 |
---|---|---|
committer | Ettore Perazzoli <ettore@src.gnome.org> | 2003-10-22 02:49:34 +0800 |
commit | 653cfffc0e00dfb59b36813c1b45c53d3f773c65 (patch) | |
tree | 9b486d5e383ec1391d60973d9cc548be0ef6d9d5 /calendar/cal-client/cal-client.c | |
parent | 0fb08f3ff81575a4749d851404233f34252dd2f2 (diff) | |
download | gsoc2013-evolution-653cfffc0e00dfb59b36813c1b45c53d3f773c65.tar.gz gsoc2013-evolution-653cfffc0e00dfb59b36813c1b45c53d3f773c65.tar.zst gsoc2013-evolution-653cfffc0e00dfb59b36813c1b45c53d3f773c65.zip |
Merge new-ui-branch to the trunk.
svn path=/trunk/; revision=22965
Diffstat (limited to 'calendar/cal-client/cal-client.c')
-rw-r--r-- | calendar/cal-client/cal-client.c | 3710 |
1 files changed, 2247 insertions, 1463 deletions
diff --git a/calendar/cal-client/cal-client.c b/calendar/cal-client/cal-client.c index e40d405120..95efdd6d5d 100644 --- a/calendar/cal-client/cal-client.c +++ b/calendar/cal-client/cal-client.c @@ -22,20 +22,39 @@ #include <config.h> #endif +#include <pthread.h> #include <string.h> #include <bonobo-activation/bonobo-activation.h> #include <bonobo/bonobo-exception.h> +#include <bonobo/bonobo-i18n.h> #include <libgnome/gnome-util.h> #include "e-util/e-component-listener.h" #include "e-util/e-config-listener.h" +#include "e-util/e-url.h" +#include "e-util/e-msgport.h" #include "cal-util/cal-util-marshal.h" -#include "cal-client-types.h" +#include "cal-util/timeutil.h" #include "cal-client.h" #include "cal-listener.h" +#include "query-listener.h" +typedef struct { + EMutex *mutex; + pthread_cond_t cond; + ECalendarStatus status; + + char *uid; + GList *list; + gboolean bool; + char *string; + + CalQuery *query; + QueryListener *listener; +} ECalendarOp; + /* Private part of the CalClient structure */ struct _CalClientPrivate { /* Load state to avoid multiple loads */ @@ -45,7 +64,12 @@ struct _CalClientPrivate { * NULL if we are not loaded. */ char *uri; + CalObjType type; + + ECalendarOp *current_op; + EMutex *mutex; + /* Email address associated with this calendar, or NULL */ char *cal_address; char *alarm_email_address; @@ -85,8 +109,6 @@ struct _CalClientPrivate { enum { CAL_OPENED, CAL_SET_MODE, - OBJ_UPDATED, - OBJ_REMOVED, BACKEND_ERROR, CATEGORIES_CHANGED, FORGET_PASSWORD, @@ -94,10 +116,6 @@ enum { LAST_SIGNAL }; -static void cal_client_class_init (CalClientClass *klass); -static void cal_client_init (CalClient *client, CalClientClass *klass); -static void cal_client_finalize (GObject *object); - static void cal_client_get_object_timezones_cb (icalparameter *param, void *data); @@ -105,36 +123,28 @@ static guint cal_client_signals[LAST_SIGNAL]; static GObjectClass *parent_class; +#define E_CALENDAR_CHECK_STATUS(status,error) G_STMT_START{ \ + if ((status) == E_CALENDAR_STATUS_OK) { \ + return TRUE; \ + } \ + else { \ + const char *msg; \ + msg = cal_client_get_error_message ((status)); \ + g_set_error ((error), E_CALENDAR_ERROR, (status), msg, (status)); \ + return FALSE; \ + } }G_STMT_END + -/** - * cal_client_get_type: - * - * Registers the #CalClient class if necessary, and returns the type ID assigned - * to it. - * - * Return value: The type ID of the #CalClient class. - **/ -GType -cal_client_get_type (void) +/* Error quark */ +GQuark +e_calendar_error_quark (void) { - static GType cal_client_type = 0; - - if (!cal_client_type) { - static GTypeInfo info = { - sizeof (CalClientClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) cal_client_class_init, - NULL, NULL, - sizeof (CalClient), - 0, - (GInstanceInitFunc) cal_client_init - }; - cal_client_type = g_type_register_static (G_TYPE_OBJECT, "CalClient", &info, 0); - } + static GQuark q = 0; + if (q == 0) + q = g_quark_from_static_string ("e-calendar-error-quark"); - return cal_client_type; + return q; } GType @@ -198,118 +208,48 @@ cal_mode_enum_get_type (void) return cal_mode_enum_type; } -/* Class initialization function for the calendar client */ -static void -cal_client_class_init (CalClientClass *klass) +/* EBookOp calls */ + +static ECalendarOp* +e_calendar_new_op (CalClient *client) { - GObjectClass *object_class; + ECalendarOp *op = g_new0 (ECalendarOp, 1); - object_class = (GObjectClass *) klass; + op->mutex = e_mutex_new (E_MUTEX_SIMPLE); + pthread_cond_init (&op->cond, 0); - parent_class = g_type_class_peek_parent (klass); - - cal_client_signals[CAL_OPENED] = - g_signal_new ("cal_opened", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (CalClientClass, cal_opened), - NULL, NULL, - g_cclosure_marshal_VOID__ENUM, - G_TYPE_NONE, 1, - CAL_CLIENT_OPEN_STATUS_ENUM_TYPE); - cal_client_signals[CAL_SET_MODE] = - g_signal_new ("cal_set_mode", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (CalClientClass, cal_set_mode), - NULL, NULL, - cal_util_marshal_VOID__ENUM_ENUM, - G_TYPE_NONE, 2, - CAL_CLIENT_SET_MODE_STATUS_ENUM_TYPE, - CAL_MODE_ENUM_TYPE); - cal_client_signals[OBJ_UPDATED] = - g_signal_new ("obj_updated", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (CalClientClass, obj_updated), - NULL, NULL, - g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, 1, - G_TYPE_STRING); - cal_client_signals[OBJ_REMOVED] = - g_signal_new ("obj_removed", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (CalClientClass, obj_removed), - NULL, NULL, - g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, 1, - G_TYPE_STRING); - cal_client_signals[BACKEND_ERROR] = - g_signal_new ("backend_error", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (CalClientClass, backend_error), - NULL, NULL, - g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, 1, - G_TYPE_STRING); - cal_client_signals[CATEGORIES_CHANGED] = - g_signal_new ("categories_changed", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (CalClientClass, categories_changed), - NULL, NULL, - g_cclosure_marshal_VOID__POINTER, - G_TYPE_NONE, 1, - G_TYPE_POINTER); - cal_client_signals[FORGET_PASSWORD] = - g_signal_new ("forget_password", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (CalClientClass, forget_password), - NULL, NULL, - g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, 1, - G_TYPE_STRING); - cal_client_signals[BACKEND_DIED] = - g_signal_new ("backend_died", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (CalClientClass, backend_died), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); + client->priv->current_op = op; - klass->cal_opened = NULL; - klass->obj_updated = NULL; - klass->obj_removed = NULL; - klass->categories_changed = NULL; - klass->forget_password = NULL; - klass->backend_died = NULL; + return op; +} - object_class->finalize = cal_client_finalize; +static ECalendarOp* +e_calendar_get_op (CalClient *client) +{ + if (!client->priv->current_op) { + g_warning (G_STRLOC ": Unexpected response"); + return NULL; + } + + return client->priv->current_op; } -/* Object initialization function for the calendar client */ static void -cal_client_init (CalClient *client, CalClientClass *klass) +e_calendar_free_op (ECalendarOp *op) { - CalClientPrivate *priv; + /* XXX more stuff here */ + pthread_cond_destroy (&op->cond); + e_mutex_destroy (op->mutex); + g_free (op); +} - priv = g_new0 (CalClientPrivate, 1); - client->priv = priv; +static void +e_calendar_remove_op (CalClient *client, ECalendarOp *op) +{ + if (client->priv->current_op != op) + g_warning (G_STRLOC ": Cannot remove op, it's not current"); - priv->load_state = CAL_CLIENT_LOAD_NOT_LOADED; - priv->uri = NULL; - priv->cal_address = NULL; - priv->alarm_email_address = NULL; - priv->ldap_attribute = NULL; - priv->capabilities = FALSE; - priv->factories = NULL; - priv->timezones = g_hash_table_new (g_str_hash, g_str_equal); - priv->default_zone = icaltimezone_get_utc_timezone (); - priv->comp_listener = NULL; + client->priv->current_op = NULL; } /* Gets rid of the factories that a client knows about */ @@ -364,7 +304,7 @@ destroy_cal (CalClient *client) CORBA_exception_init (&ev); result = CORBA_Object_is_nil (priv->cal, &ev); if (BONOBO_EX (&ev)) { - g_message ("destroy_cal(): could not see if the " + g_message (G_STRLOC ": could not see if the " "calendar client interface object was nil"); priv->cal = CORBA_OBJECT_NIL; CORBA_exception_free (&ev); @@ -375,19 +315,7 @@ destroy_cal (CalClient *client) if (result) return; - CORBA_exception_init (&ev); - GNOME_Evolution_Calendar_Cal_unref (priv->cal, &ev); - if (BONOBO_EX (&ev)) - g_message ("destroy_cal(): could not unref the calendar client interface object"); - - CORBA_exception_free (&ev); - - CORBA_exception_init (&ev); - CORBA_Object_release (priv->cal, &ev); - if (BONOBO_EX (&ev)) - g_message ("destroy_cal(): could not release the calendar client interface object"); - - CORBA_exception_free (&ev); + bonobo_object_release_unref (priv->cal, NULL); priv->cal = CORBA_OBJECT_NIL; } @@ -400,184 +328,541 @@ free_timezone (gpointer key, gpointer value, gpointer data) icaltimezone_free (value, TRUE); } -/* Finalize handler for the calendar client */ + + static void -cal_client_finalize (GObject *object) +backend_died_cb (EComponentListener *cl, gpointer user_data) { - CalClient *client; CalClientPrivate *priv; + CalClient *client = (CalClient *) user_data; - g_return_if_fail (object != NULL); - g_return_if_fail (IS_CAL_CLIENT (object)); + g_return_if_fail (IS_CAL_CLIENT (client)); - client = CAL_CLIENT (object); priv = client->priv; + priv->load_state = CAL_CLIENT_LOAD_NOT_LOADED; + g_signal_emit (G_OBJECT (client), cal_client_signals[BACKEND_DIED], 0); +} - if (priv->listener) { - cal_listener_stop_notification (priv->listener); - bonobo_object_unref (priv->listener); - priv->listener = NULL; +/* Signal handlers for the listener's signals */ +/* Handle the cal_opened notification from the listener */ + +static void +cal_read_only_cb (CalListener *listener, ECalendarStatus status, gboolean read_only, gpointer data) +{ + CalClient *client = data; + ECalendarOp *op; + + op = e_calendar_get_op (client); + + if (op == NULL) { + g_warning (G_STRLOC ": Cannot find operation "); + return; } - if (priv->comp_listener) { - g_signal_handlers_disconnect_matched (G_OBJECT (priv->comp_listener), - G_SIGNAL_MATCH_DATA, - 0, 0, NULL, NULL, - client); - g_object_unref (G_OBJECT (priv->comp_listener)); - priv->comp_listener = NULL; + e_mutex_lock (op->mutex); + + op->status = status; + op->bool = read_only; + + pthread_cond_signal (&op->cond); + + e_mutex_unlock (op->mutex); +} + +static void +cal_cal_address_cb (CalListener *listener, ECalendarStatus status, const char *address, gpointer data) +{ + CalClient *client = data; + ECalendarOp *op; + + op = e_calendar_get_op (client); + + if (op == NULL) { + g_warning (G_STRLOC ": Cannot find operation "); + return; } - destroy_factories (client); - destroy_cal (client); + e_mutex_lock (op->mutex); - priv->load_state = CAL_CLIENT_LOAD_NOT_LOADED; + op->status = status; + op->string = g_strdup (address); - if (priv->uri) { - g_free (priv->uri); - priv->uri = NULL; + pthread_cond_signal (&op->cond); + + e_mutex_unlock (op->mutex); +} + +static void +cal_alarm_address_cb (CalListener *listener, ECalendarStatus status, const char *address, gpointer data) +{ + CalClient *client = data; + ECalendarOp *op; + + op = e_calendar_get_op (client); + + if (op == NULL) { + g_warning (G_STRLOC ": Cannot find operation "); + return; } - if (priv->cal_address) { - g_free (priv->cal_address); - priv->cal_address = NULL; + e_mutex_lock (op->mutex); + + op->status = status; + op->string = g_strdup (address); + + pthread_cond_signal (&op->cond); + + e_mutex_unlock (op->mutex); +} + +static void +cal_ldap_attribute_cb (CalListener *listener, ECalendarStatus status, const char *attribute, gpointer data) +{ + CalClient *client = data; + ECalendarOp *op; + + op = e_calendar_get_op (client); + + if (op == NULL) { + g_warning (G_STRLOC ": Cannot find operation "); + return; } - if (priv->alarm_email_address) { - g_free (priv->alarm_email_address); - priv->alarm_email_address = NULL; + + e_mutex_lock (op->mutex); + + op->status = status; + op->string = g_strdup (attribute); + + pthread_cond_signal (&op->cond); + + e_mutex_unlock (op->mutex); +} + +static void +cal_static_capabilities_cb (CalListener *listener, ECalendarStatus status, const char *capabilities, gpointer data) +{ + CalClient *client = data; + ECalendarOp *op; + + op = e_calendar_get_op (client); + + if (op == NULL) { + g_warning (G_STRLOC ": Cannot find operation "); + return; } - if (priv->ldap_attribute) { - g_free (priv->ldap_attribute); - priv->ldap_attribute = NULL; + + e_mutex_lock (op->mutex); + + op->status = status; + op->string = g_strdup (capabilities); + + pthread_cond_signal (&op->cond); + + e_mutex_unlock (op->mutex); +} + +static void +cal_opened_cb (CalListener *listener, ECalendarStatus status, gpointer data) +{ + CalClient *client = data; + ECalendarOp *op; + + op = e_calendar_get_op (client); + + if (op == NULL) { + g_warning (G_STRLOC ": Cannot find operation "); + return; } - if (priv->capabilities) { - g_free (priv->capabilities); - priv->capabilities = NULL; + + e_mutex_lock (op->mutex); + + op->status = status; + + pthread_cond_signal (&op->cond); + + e_mutex_unlock (op->mutex); +} + +static void +cal_removed_cb (CalListener *listener, ECalendarStatus status, gpointer data) +{ + CalClient *client = data; + ECalendarOp *op; + + op = e_calendar_get_op (client); + + if (op == NULL) { + g_warning (G_STRLOC ": Cannot find operation "); + return; } - g_hash_table_foreach (priv->timezones, free_timezone, NULL); - g_hash_table_destroy (priv->timezones); - priv->timezones = NULL; + e_mutex_lock (op->mutex); - g_free (priv); - client->priv = NULL; + op->status = status; - if (G_OBJECT_CLASS (parent_class)->finalize) - (* G_OBJECT_CLASS (parent_class)->finalize) (object); + pthread_cond_signal (&op->cond); + + e_mutex_unlock (op->mutex); } - +static void +cal_object_created_cb (CalListener *listener, ECalendarStatus status, const char *uid, gpointer data) +{ + CalClient *client = data; + ECalendarOp *op; + + op = e_calendar_get_op (client); + + if (op == NULL) { + g_warning (G_STRLOC ": Cannot find operation "); + return; + } + + e_mutex_lock (op->mutex); + + op->status = status; + op->uid = g_strdup (uid); + + pthread_cond_signal (&op->cond); + + e_mutex_unlock (op->mutex); +} static void -backend_died_cb (EComponentListener *cl, gpointer user_data) +cal_object_modified_cb (CalListener *listener, ECalendarStatus status, gpointer data) { - CalClientPrivate *priv; - CalClient *client = (CalClient *) user_data; + CalClient *client = data; + ECalendarOp *op; - g_return_if_fail (IS_CAL_CLIENT (client)); + op = e_calendar_get_op (client); - priv = client->priv; - priv->load_state = CAL_CLIENT_LOAD_NOT_LOADED; - g_signal_emit (G_OBJECT (client), cal_client_signals[BACKEND_DIED], 0); + if (op == NULL) { + g_warning (G_STRLOC ": Cannot find operation "); + return; + } + + e_mutex_lock (op->mutex); + + op->status = status; + + pthread_cond_signal (&op->cond); + + e_mutex_unlock (op->mutex); } -/* Signal handlers for the listener's signals */ -/* Handle the cal_opened notification from the listener */ static void -cal_opened_cb (CalListener *listener, - GNOME_Evolution_Calendar_Listener_OpenStatus status, - GNOME_Evolution_Calendar_Cal cal, - gpointer data) +cal_object_removed_cb (CalListener *listener, ECalendarStatus status, gpointer data) { - CalClient *client; - CalClientPrivate *priv; - CORBA_Environment ev; - GNOME_Evolution_Calendar_Cal cal_copy; - CalClientOpenStatus client_status; + CalClient *client = data; + ECalendarOp *op; - client = CAL_CLIENT (data); - priv = client->priv; + op = e_calendar_get_op (client); - g_assert (priv->load_state == CAL_CLIENT_LOAD_LOADING); - g_assert (priv->uri != NULL); + if (op == NULL) { + g_warning (G_STRLOC ": Cannot find operation "); + return; + } - client_status = CAL_CLIENT_OPEN_ERROR; + e_mutex_lock (op->mutex); - switch (status) { - case GNOME_Evolution_Calendar_Listener_SUCCESS: - CORBA_exception_init (&ev); - cal_copy = CORBA_Object_duplicate (cal, &ev); - if (BONOBO_EX (&ev)) { - g_message ("cal_opened_cb(): could not duplicate the " - "calendar client interface"); - CORBA_exception_free (&ev); - goto error; - } - CORBA_exception_free (&ev); + op->status = status; - priv->cal = cal_copy; - priv->load_state = CAL_CLIENT_LOAD_LOADED; + pthread_cond_signal (&op->cond); + + e_mutex_unlock (op->mutex); +} - client_status = CAL_CLIENT_OPEN_SUCCESS; +static void +cal_alarm_discarded_cb (CalListener *listener, ECalendarStatus status, gpointer data) +{ + CalClient *client = data; + ECalendarOp *op; - /* setup component listener */ - priv->comp_listener = e_component_listener_new (priv->cal); - g_signal_connect (G_OBJECT (priv->comp_listener), "component_died", - G_CALLBACK (backend_died_cb), client); - goto out; + op = e_calendar_get_op (client); - case GNOME_Evolution_Calendar_Listener_ERROR: - client_status = CAL_CLIENT_OPEN_ERROR; - goto error; + if (op == NULL) { + g_warning (G_STRLOC ": Cannot find operation "); + return; + } - case GNOME_Evolution_Calendar_Listener_NOT_FOUND: - client_status = CAL_CLIENT_OPEN_NOT_FOUND; - goto error; + e_mutex_lock (op->mutex); - case GNOME_Evolution_Calendar_Listener_METHOD_NOT_SUPPORTED: - client_status = CAL_CLIENT_OPEN_METHOD_NOT_SUPPORTED; - goto error; + op->status = status; - case GNOME_Evolution_Calendar_Listener_PERMISSION_DENIED : - client_status = CAL_CLIENT_OPEN_PERMISSION_DENIED; - goto error; + pthread_cond_signal (&op->cond); - default: - g_assert_not_reached (); + e_mutex_unlock (op->mutex); +} + +static void +cal_objects_received_cb (CalListener *listener, ECalendarStatus status, gpointer data) +{ + CalClient *client = data; + ECalendarOp *op; + + op = e_calendar_get_op (client); + + if (op == NULL) { + g_warning (G_STRLOC ": Cannot find operation "); + return; } - error: + e_mutex_lock (op->mutex); - bonobo_object_unref (BONOBO_OBJECT (priv->listener)); - priv->listener = NULL; + op->status = status; - /* We free the priv->uri and set the priv->load_state until after the - * "cal_opened" signal has been emitted so that handlers will be able to - * access this information. - */ + pthread_cond_signal (&op->cond); - out: + e_mutex_unlock (op->mutex); +} - /* We are *not* inside a signal handler (this is just a simple callback - * called from the listener), so there is not a temporary reference to - * the client object. We ref() so that we can safely emit our own - * signal and clean up. - */ +static void +cal_objects_sent_cb (CalListener *listener, ECalendarStatus status, gpointer data) +{ + CalClient *client = data; + ECalendarOp *op; - g_object_ref (G_OBJECT (client)); + op = e_calendar_get_op (client); - g_signal_emit (G_OBJECT (client), cal_client_signals[CAL_OPENED], - 0, client_status); + if (op == NULL) { + g_warning (G_STRLOC ": Cannot find operation "); + return; + } - if (client_status != CAL_CLIENT_OPEN_SUCCESS) { - priv->load_state = CAL_CLIENT_LOAD_NOT_LOADED; - g_free (priv->uri); - priv->uri = NULL; + e_mutex_lock (op->mutex); + + op->status = status; + + pthread_cond_signal (&op->cond); + + e_mutex_unlock (op->mutex); +} + +static void +cal_default_object_requested_cb (CalListener *listener, ECalendarStatus status, const char *object, gpointer data) +{ + CalClient *client = data; + ECalendarOp *op; + + op = e_calendar_get_op (client); + + if (op == NULL) { + g_warning (G_STRLOC ": Cannot find operation "); + return; } - g_assert (priv->load_state != CAL_CLIENT_LOAD_LOADING); + e_mutex_lock (op->mutex); - g_object_unref (G_OBJECT (client)); + op->status = status; + op->string = g_strdup (object); + + pthread_cond_signal (&op->cond); + + e_mutex_unlock (op->mutex); +} + +static void +cal_object_requested_cb (CalListener *listener, ECalendarStatus status, const char *object, gpointer data) +{ + CalClient *client = data; + ECalendarOp *op; + + op = e_calendar_get_op (client); + + if (op == NULL) { + g_warning (G_STRLOC ": Cannot find operation "); + return; + } + + e_mutex_lock (op->mutex); + + op->status = status; + op->string = g_strdup (object); + + pthread_cond_signal (&op->cond); + + e_mutex_unlock (op->mutex); +} + +static void +cal_object_list_cb (CalListener *listener, ECalendarStatus status, GList *objects, gpointer data) +{ + CalClient *client = data; + ECalendarOp *op; + GList *l; + + op = e_calendar_get_op (client); + + if (op == NULL) { + g_warning (G_STRLOC ": Cannot find operation "); + return; + } + + e_mutex_lock (op->mutex); + + op->status = status; + op->list = g_list_copy (objects); + + for (l = op->list; l; l = l->next) + l->data = icalcomponent_new_clone (l->data); + + pthread_cond_signal (&op->cond); + + e_mutex_unlock (op->mutex); +} + +static void +cal_get_timezone_cb (CalListener *listener, ECalendarStatus status, const char *object, gpointer data) +{ + CalClient *client = data; + ECalendarOp *op; + + op = e_calendar_get_op (client); + + if (op == NULL) { + g_warning (G_STRLOC ": Cannot find operation "); + return; + } + + e_mutex_lock (op->mutex); + + op->status = status; + op->string = g_strdup (object); + + pthread_cond_signal (&op->cond); + + e_mutex_unlock (op->mutex); + +} + +static void +cal_add_timezone_cb (CalListener *listener, ECalendarStatus status, const char *tzid, gpointer data) +{ + CalClient *client = data; + ECalendarOp *op; + + op = e_calendar_get_op (client); + + if (op == NULL) { + g_warning (G_STRLOC ": Cannot find operation "); + return; + } + + e_mutex_lock (op->mutex); + + op->status = status; + op->uid = g_strdup (tzid); + + pthread_cond_signal (&op->cond); + + e_mutex_unlock (op->mutex); + +} + +static void +cal_set_default_timezone_cb (CalListener *listener, ECalendarStatus status, gpointer data) +{ + CalClient *client = data; + ECalendarOp *op; + + op = e_calendar_get_op (client); + + if (op == NULL) { + g_warning (G_STRLOC ": Cannot find operation "); + return; + } + + e_mutex_lock (op->mutex); + + op->status = status; + + pthread_cond_signal (&op->cond); + + e_mutex_unlock (op->mutex); +} + +static void +cal_get_changes_cb (CalListener *listener, ECalendarStatus status, GList *changes, gpointer data) +{ + CalClient *client = data; + ECalendarOp *op; + GList *l; + + op = e_calendar_get_op (client); + + if (op == NULL) { + g_warning (G_STRLOC ": Cannot find operation "); + return; + } + + e_mutex_lock (op->mutex); + + op->status = status; + op->list = g_list_copy (changes); + + for (l = op->list; l; l = l->next) { + CalClientChange *ccc = l->data, *new_ccc; + + new_ccc = g_new (CalClientChange, 1); + new_ccc->comp = cal_component_clone (ccc->comp); + new_ccc->type = ccc->type; + + l->data = new_ccc; + } + + pthread_cond_signal (&op->cond); + + e_mutex_unlock (op->mutex); +} + +static void +cal_get_free_busy_cb (CalListener *listener, ECalendarStatus status, GList *freebusy, gpointer data) +{ + CalClient *client = data; + ECalendarOp *op; + GList *l; + + op = e_calendar_get_op (client); + + if (op == NULL) { + g_warning (G_STRLOC ": Cannot find operation "); + return; + } + + e_mutex_lock (op->mutex); + + op->status = status; + op->list = g_list_copy (freebusy); + + for (l = op->list; l; l = l->next) + l->data = cal_component_clone (l->data); + + pthread_cond_signal (&op->cond); + + e_mutex_unlock (op->mutex); +} + +static void +cal_query_cb (CalListener *listener, ECalendarStatus status, GNOME_Evolution_Calendar_Query query, gpointer data) +{ + CalClient *client = data; + ECalendarOp *op; + + op = e_calendar_get_op (client); + + if (op == NULL) { + g_warning (G_STRLOC ": Cannot find operation "); + return; + } + + e_mutex_lock (op->mutex); + + op->status = status; + op->query = cal_query_new (query, op->listener, client); + + pthread_cond_signal (&op->cond); + + e_mutex_unlock (op->mutex); } /* Handle the cal_set_mode notification from the listener */ @@ -624,26 +909,6 @@ cal_set_mode_cb (CalListener *listener, g_object_unref (G_OBJECT (client)); } -/* Handle the obj_updated signal from the listener */ -static void -obj_updated_cb (CalListener *listener, const CORBA_char *uid, gpointer data) -{ - CalClient *client; - - client = CAL_CLIENT (data); - g_signal_emit (G_OBJECT (client), cal_client_signals[OBJ_UPDATED], 0, uid); -} - -/* Handle the obj_removed signal from the listener */ -static void -obj_removed_cb (CalListener *listener, const CORBA_char *uid, gpointer data) -{ - CalClient *client; - - client = CAL_CLIENT (data); - g_signal_emit (G_OBJECT (client), cal_client_signals[OBJ_REMOVED], 0, uid); -} - /* Handle the error_occurred signal from the listener */ static void backend_error_cb (CalListener *listener, const char *message, gpointer data) @@ -678,97 +943,343 @@ categories_changed_cb (CalListener *listener, const GNOME_Evolution_Calendar_Str -static GList * -get_factories (void) +static gboolean +get_factories (const char *str_uri, GList **factories) { - GList *factories = NULL; GNOME_Evolution_Calendar_CalFactory factory; Bonobo_ServerInfoList *servers; - CORBA_Environment ev; + EUri *uri; + char *query; int i; - CORBA_exception_init (&ev); - servers = bonobo_activation_query ("repo_ids.has ('IDL:GNOME/Evolution/Calendar/CalFactory:1.0')", NULL, &ev); - if (ev._major != CORBA_NO_EXCEPTION) { - g_message ("Cannot perform OAF query for Calendar servers."); - CORBA_exception_free (&ev); - return NULL; + /* Determine the protocol and query for factory supporting that */ + uri = e_uri_new (str_uri); + if (!uri) { + g_warning (G_STRLOC ": Invalid uri string"); + + return FALSE; } - if (servers->_length == 0) - g_warning ("No Calendar servers installed."); + query = g_strdup_printf ("repo_ids.has ('IDL:GNOME/Evolution/Calendar/CalFactory:1.0')" + " AND calendar:supported_protocols.has ('%s')", uri->protocol); + + + servers = bonobo_activation_query (query, NULL, NULL); + + g_free (query); + e_uri_free (uri); + if (!servers) { + g_warning (G_STRLOC ": Unable to query for calendar factories"); + + return FALSE; + } + + /* Try to activate the servers for the protocol */ for (i = 0; i < servers->_length; i++) { const Bonobo_ServerInfo *info; info = servers->_buffer + i; - factory = (GNOME_Evolution_Calendar_CalFactory) - bonobo_activation_activate_from_id (info->iid, 0, NULL, &ev); - if (BONOBO_EX (&ev)) { -#if 0 - g_warning ("cal_client_construct: Could not activate calendar server %s", info->iid); - CORBA_free (servers); - CORBA_exception_free (&ev); - return NULL; -#endif - } + g_message (G_STRLOC ": Activating calendar factory (%s)", info->iid); + factory = bonobo_activation_activate_from_id (info->iid, 0, NULL, NULL); + + if (factory == CORBA_OBJECT_NIL) + g_warning (G_STRLOC ": Could not activate calendar factory (%s)", info->iid); else - factories = g_list_prepend (factories, factory); + *factories = g_list_append (*factories, factory); } CORBA_free (servers); - CORBA_exception_free (&ev); - return factories; + + return TRUE; +} + +/* Object initialization function for the calendar client */ +static void +cal_client_init (CalClient *client, CalClientClass *klass) +{ + CalClientPrivate *priv; + + priv = g_new0 (CalClientPrivate, 1); + client->priv = priv; + + priv->load_state = CAL_CLIENT_LOAD_NOT_LOADED; + priv->uri = NULL; + priv->mutex = e_mutex_new (E_MUTEX_REC); + priv->listener = cal_listener_new (cal_set_mode_cb, + backend_error_cb, + categories_changed_cb, + client); + + priv->cal_address = NULL; + priv->alarm_email_address = NULL; + priv->ldap_attribute = NULL; + priv->capabilities = FALSE; + priv->factories = NULL; + priv->timezones = g_hash_table_new (g_str_hash, g_str_equal); + priv->default_zone = icaltimezone_get_utc_timezone (); + priv->comp_listener = NULL; + + g_signal_connect (G_OBJECT (priv->listener), "read_only", G_CALLBACK (cal_read_only_cb), client); + g_signal_connect (G_OBJECT (priv->listener), "cal_address", G_CALLBACK (cal_cal_address_cb), client); + g_signal_connect (G_OBJECT (priv->listener), "alarm_address", G_CALLBACK (cal_alarm_address_cb), client); + g_signal_connect (G_OBJECT (priv->listener), "ldap_attribute", G_CALLBACK (cal_ldap_attribute_cb), client); + g_signal_connect (G_OBJECT (priv->listener), "static_capabilities", G_CALLBACK (cal_static_capabilities_cb), client); + g_signal_connect (G_OBJECT (priv->listener), "open", G_CALLBACK (cal_opened_cb), client); + g_signal_connect (G_OBJECT (priv->listener), "remove", G_CALLBACK (cal_removed_cb), client); + g_signal_connect (G_OBJECT (priv->listener), "create_object", G_CALLBACK (cal_object_created_cb), client); + g_signal_connect (G_OBJECT (priv->listener), "modify_object", G_CALLBACK (cal_object_modified_cb), client); + g_signal_connect (G_OBJECT (priv->listener), "remove_object", G_CALLBACK (cal_object_removed_cb), client); + g_signal_connect (G_OBJECT (priv->listener), "discard_alarm", G_CALLBACK (cal_alarm_discarded_cb), client); + g_signal_connect (G_OBJECT (priv->listener), "receive_objects", G_CALLBACK (cal_objects_received_cb), client); + g_signal_connect (G_OBJECT (priv->listener), "send_objects", G_CALLBACK (cal_objects_sent_cb), client); + g_signal_connect (G_OBJECT (priv->listener), "default_object", G_CALLBACK (cal_default_object_requested_cb), client); + g_signal_connect (G_OBJECT (priv->listener), "object", G_CALLBACK (cal_object_requested_cb), client); + g_signal_connect (G_OBJECT (priv->listener), "object_list", G_CALLBACK (cal_object_list_cb), client); + g_signal_connect (G_OBJECT (priv->listener), "get_timezone", G_CALLBACK (cal_get_timezone_cb), client); + g_signal_connect (G_OBJECT (priv->listener), "add_timezone", G_CALLBACK (cal_add_timezone_cb), client); + g_signal_connect (G_OBJECT (priv->listener), "set_default_timezone", G_CALLBACK (cal_set_default_timezone_cb), client); + g_signal_connect (G_OBJECT (priv->listener), "get_changes", G_CALLBACK (cal_get_changes_cb), client); + g_signal_connect (G_OBJECT (priv->listener), "get_free_busy", G_CALLBACK (cal_get_free_busy_cb), client); + g_signal_connect (G_OBJECT (priv->listener), "query", G_CALLBACK (cal_query_cb), client); +} + +/* Finalize handler for the calendar client */ +static void +cal_client_finalize (GObject *object) +{ + CalClient *client; + CalClientPrivate *priv; + + g_return_if_fail (object != NULL); + g_return_if_fail (IS_CAL_CLIENT (object)); + + client = CAL_CLIENT (object); + priv = client->priv; + + if (priv->listener) { + cal_listener_stop_notification (priv->listener); + bonobo_object_unref (priv->listener); + priv->listener = NULL; + } + + if (priv->comp_listener) { + g_signal_handlers_disconnect_matched (G_OBJECT (priv->comp_listener), + G_SIGNAL_MATCH_DATA, + 0, 0, NULL, NULL, + client); + g_object_unref (G_OBJECT (priv->comp_listener)); + priv->comp_listener = NULL; + } + + destroy_factories (client); + destroy_cal (client); + + priv->load_state = CAL_CLIENT_LOAD_NOT_LOADED; + + if (priv->uri) { + g_free (priv->uri); + priv->uri = NULL; + } + + if (priv->mutex) { + e_mutex_destroy (priv->mutex); + priv->mutex = NULL; + } + + if (priv->cal_address) { + g_free (priv->cal_address); + priv->cal_address = NULL; + } + if (priv->alarm_email_address) { + g_free (priv->alarm_email_address); + priv->alarm_email_address = NULL; + } + if (priv->ldap_attribute) { + g_free (priv->ldap_attribute); + priv->ldap_attribute = NULL; + } + if (priv->capabilities) { + g_free (priv->capabilities); + priv->capabilities = NULL; + } + + g_hash_table_foreach (priv->timezones, free_timezone, NULL); + g_hash_table_destroy (priv->timezones); + priv->timezones = NULL; + + g_free (priv); + client->priv = NULL; + + if (G_OBJECT_CLASS (parent_class)->finalize) + (* G_OBJECT_CLASS (parent_class)->finalize) (object); +} + +/* Class initialization function for the calendar client */ +static void +cal_client_class_init (CalClientClass *klass) +{ + GObjectClass *object_class; + + object_class = (GObjectClass *) klass; + + parent_class = g_type_class_peek_parent (klass); + + cal_client_signals[CAL_OPENED] = + g_signal_new ("cal_opened", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (CalClientClass, cal_opened), + NULL, NULL, + g_cclosure_marshal_VOID__ENUM, + G_TYPE_NONE, 1, + CAL_CLIENT_OPEN_STATUS_ENUM_TYPE); + cal_client_signals[CAL_SET_MODE] = + g_signal_new ("cal_set_mode", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (CalClientClass, cal_set_mode), + NULL, NULL, + cal_util_marshal_VOID__ENUM_ENUM, + G_TYPE_NONE, 2, + CAL_CLIENT_SET_MODE_STATUS_ENUM_TYPE, + CAL_MODE_ENUM_TYPE); + cal_client_signals[BACKEND_ERROR] = + g_signal_new ("backend_error", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (CalClientClass, backend_error), + NULL, NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, 1, + G_TYPE_STRING); + cal_client_signals[CATEGORIES_CHANGED] = + g_signal_new ("categories_changed", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (CalClientClass, categories_changed), + NULL, NULL, + g_cclosure_marshal_VOID__POINTER, + G_TYPE_NONE, 1, + G_TYPE_POINTER); + cal_client_signals[FORGET_PASSWORD] = + g_signal_new ("forget_password", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (CalClientClass, forget_password), + NULL, NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, 1, + G_TYPE_STRING); + cal_client_signals[BACKEND_DIED] = + g_signal_new ("backend_died", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (CalClientClass, backend_died), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + klass->cal_opened = NULL; + klass->categories_changed = NULL; + klass->forget_password = NULL; + klass->backend_died = NULL; + + object_class->finalize = cal_client_finalize; } /** - * cal_client_construct: - * @client: A calendar client. + * cal_client_get_type: * - * Constructs a calendar client object by contacting all available - * calendar factories. + * Registers the #CalClient class if necessary, and returns the type ID assigned + * to it. * - * Return value: The same object as the @client argument, or NULL if the - * calendar factory could not be contacted. + * Return value: The type ID of the #CalClient class. **/ -CalClient * -cal_client_construct (CalClient *client) +GType +cal_client_get_type (void) { - CalClientPrivate *priv; + static GType cal_client_type = 0; - g_return_val_if_fail (client != NULL, NULL); - g_return_val_if_fail (IS_CAL_CLIENT (client), NULL); + if (!cal_client_type) { + static GTypeInfo info = { + sizeof (CalClientClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) cal_client_class_init, + NULL, NULL, + sizeof (CalClient), + 0, + (GInstanceInitFunc) cal_client_init + }; + cal_client_type = g_type_register_static (G_TYPE_OBJECT, "CalClient", &info, 0); + } + return cal_client_type; +} + + +static gboolean +fetch_corba_cal (CalClient *client, const char *str_uri, CalObjType type) +{ + CalClientPrivate *priv; + GList *f; + CORBA_Environment ev; + priv = client->priv; - priv->factories = get_factories (); + g_return_val_if_fail (priv->load_state == CAL_CLIENT_LOAD_NOT_LOADED, FALSE); + g_assert (priv->uri == NULL); - return client; + g_return_val_if_fail (str_uri != NULL, FALSE); + + if (!get_factories (str_uri, &priv->factories)) + return FALSE; + + priv->uri = g_strdup (str_uri); + priv->type = type; + + for (f = priv->factories; f; f = f->next) { + GNOME_Evolution_Calendar_Cal cal; + + CORBA_exception_init (&ev); + + cal = GNOME_Evolution_Calendar_CalFactory_getCal (f->data, priv->uri, priv->type, + BONOBO_OBJREF (priv->listener), &ev); + if (BONOBO_EX (&ev)) + continue; + + priv->cal = cal; + + return TRUE; + } + + return FALSE; } /** * cal_client_new: * * Creates a new calendar client. It should be initialized by calling - * cal_client_open_calendar(). + * cal_client_open(). * * Return value: A newly-created calendar client, or NULL if the client could * not be constructed because it could not contact the calendar server. **/ CalClient * -cal_client_new (void) +cal_client_new (const char *uri, CalObjType type) { CalClient *client; client = g_object_new (CAL_CLIENT_TYPE, NULL); - if (!cal_client_construct (client)) { - g_message ("cal_client_new(): could not construct the calendar client"); - g_object_unref (G_OBJECT (client)); + if (!fetch_corba_cal (client, uri, type)) { + g_object_unref (client); + return NULL; } - + return client; } @@ -800,74 +1311,8 @@ cal_client_set_auth_func (CalClient *client, CalClientAuthFunc func, gpointer da client->priv->auth_user_data = data; } -static gboolean -real_open_calendar (CalClient *client, const char *str_uri, gboolean only_if_exists, gboolean *supported) -{ - CalClientPrivate *priv; - GNOME_Evolution_Calendar_Listener corba_listener; - int unsupported; - GList *f; - CORBA_Environment ev; - - priv = client->priv; - g_return_val_if_fail (priv->load_state == CAL_CLIENT_LOAD_NOT_LOADED, FALSE); - g_assert (priv->uri == NULL); - - g_return_val_if_fail (str_uri != NULL, FALSE); - - priv->listener = cal_listener_new (cal_opened_cb, - cal_set_mode_cb, - obj_updated_cb, - obj_removed_cb, - backend_error_cb, - categories_changed_cb, - client); - if (!priv->listener) { - g_message ("cal_client_open_calendar(): could not create the listener"); - return FALSE; - } - - corba_listener = (GNOME_Evolution_Calendar_Listener) (BONOBO_OBJREF (priv->listener)); - - priv->load_state = CAL_CLIENT_LOAD_LOADING; - priv->uri = g_strdup (str_uri); - - unsupported = 0; - for (f = priv->factories; f; f = f->next) { - CORBA_exception_init (&ev); - - GNOME_Evolution_Calendar_CalFactory_open (f->data, str_uri, - only_if_exists, - corba_listener, &ev); - if (!BONOBO_EX (&ev)) { - if (supported != NULL) - *supported = TRUE; - return TRUE; - } - - if (BONOBO_USER_EX (&ev, ex_GNOME_Evolution_Calendar_CalFactory_UnsupportedMethod)) - unsupported++; - CORBA_exception_free (&ev); - } - - if (supported != NULL) { - if (unsupported == g_list_length (priv->factories)) - *supported = FALSE; - else - *supported = TRUE; - } - - bonobo_object_unref (BONOBO_OBJECT (priv->listener)); - priv->listener = NULL; - priv->load_state = CAL_CLIENT_LOAD_NOT_LOADED; - g_free (priv->uri); - priv->uri = NULL; - - return FALSE; -} - /** - * cal_client_open_calendar: + * cal_client_open * @client: A calendar client. * @str_uri: URI of calendar to open. * @only_if_exists: FALSE if the calendar should be opened even if there @@ -882,93 +1327,167 @@ real_open_calendar (CalClient *client, const char *str_uri, gboolean only_if_exi * Return value: TRUE on success, FALSE on failure to issue the open request. **/ gboolean -cal_client_open_calendar (CalClient *client, const char *str_uri, gboolean only_if_exists) +cal_client_open (CalClient *client, gboolean only_if_exists, GError **error) { + CalClientPrivate *priv; + CORBA_Environment ev; + ECalendarStatus status; + ECalendarOp *our_op; + g_return_val_if_fail (client != NULL, FALSE); g_return_val_if_fail (IS_CAL_CLIENT (client), FALSE); - return real_open_calendar (client, str_uri, only_if_exists, NULL); -} + priv = client->priv; + + e_mutex_lock (client->priv->mutex); -static char * -get_fall_back_uri (gboolean tasks) -{ - if (tasks) - return g_concat_dir_and_file (g_get_home_dir (), - "evolution/local/" - "Tasks/tasks.ics"); - else - return g_concat_dir_and_file (g_get_home_dir (), - "evolution/local/" - "Calendar/calendar.ics"); -} + if (client->priv->current_op != NULL) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error); + } -static char * -get_default_uri (gboolean tasks) -{ - EConfigListener *db; - char *uri; + our_op = e_calendar_new_op (client); + + e_mutex_lock (our_op->mutex); + + e_mutex_unlock (client->priv->mutex); + + CORBA_exception_init (&ev); + + priv->load_state = CAL_CLIENT_LOAD_LOADING; + + GNOME_Evolution_Calendar_Cal_open (priv->cal, only_if_exists, &ev); + if (BONOBO_EX (&ev)) { + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + CORBA_exception_free (&ev); + + g_warning (G_STRLOC ": Unable to contact backend"); + + g_signal_emit (G_OBJECT (client), cal_client_signals[CAL_OPENED], 0, + E_CALENDAR_STATUS_CORBA_EXCEPTION); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error); + } + + CORBA_exception_free (&ev); + + /* wait for something to happen (both cancellation and a + successful response will notity us via our cv */ + e_mutex_cond_wait (&our_op->cond, our_op->mutex); - db = e_config_listener_new (); + status = our_op->status; - if (tasks) - uri = e_config_listener_get_string (db, "/apps/evolution/shell/default_folders/tasks_uri"); - else - uri = e_config_listener_get_string (db, "/apps/evolution/shell/default_folders/calendar_uri"); - g_object_unref (G_OBJECT (db)); + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); - if (!uri || *uri == '\0') - uri = get_fall_back_uri (tasks); + if (status == E_CALENDAR_STATUS_OK) + priv->load_state = CAL_CLIENT_LOAD_LOADED; else - uri = cal_util_expand_uri (uri, tasks); - - return uri; + priv->load_state = CAL_CLIENT_LOAD_NOT_LOADED; + + g_signal_emit (G_OBJECT (client), cal_client_signals[CAL_OPENED], 0, status); + E_CALENDAR_CHECK_STATUS (status, error); } -gboolean -cal_client_open_default_calendar (CalClient *client, gboolean only_if_exists) +typedef struct { + CalClient *client; + + gboolean exists; +} CalClientAsyncData; + +static gboolean +open_async (gpointer data) { - char *default_uri, *fall_back; - gboolean result, supported; + CalClientAsyncData *ccad = data; + GError *error = NULL; - g_return_val_if_fail (client != NULL, FALSE); - g_return_val_if_fail (IS_CAL_CLIENT (client), FALSE); + cal_client_open (ccad->client, ccad->exists, &error); - default_uri = get_default_uri (FALSE); - fall_back = get_fall_back_uri (FALSE); - - result = real_open_calendar (client, default_uri, only_if_exists, &supported); - if (!supported && strcmp (fall_back, default_uri)) - result = real_open_calendar (client, fall_back, only_if_exists, NULL); + g_clear_error (&error); - g_free (default_uri); - g_free (fall_back); + g_object_unref (ccad); + g_free (ccad); - return result; + return FALSE; } -gboolean -cal_client_open_default_tasks (CalClient *client, gboolean only_if_exists) +void +cal_client_open_async (CalClient *client, gboolean only_if_exists) { - char *default_uri, *fall_back; - gboolean result, supported; + CalClientAsyncData *ccad; + + g_return_if_fail (client != NULL); + g_return_if_fail (IS_CAL_CLIENT (client)); + + ccad = g_new0 (CalClientAsyncData, 1); + ccad->client = g_object_ref (client); + ccad->exists = only_if_exists; + /* FIXME This should really spawn a new thread */ + g_idle_add (open_async, ccad); +} + +gboolean +cal_client_remove_calendar (CalClient *client, GError **error) +{ + CalClientPrivate *priv; + CORBA_Environment ev; + ECalendarStatus status; + ECalendarOp *our_op; + g_return_val_if_fail (client != NULL, FALSE); g_return_val_if_fail (IS_CAL_CLIENT (client), FALSE); - default_uri = get_default_uri (TRUE); - fall_back = get_fall_back_uri (TRUE); + priv = client->priv; + + e_mutex_lock (client->priv->mutex); + + if (client->priv->current_op != NULL) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error); + } + + our_op = e_calendar_new_op (client); - result = real_open_calendar (client, default_uri, only_if_exists, &supported); - if (!supported && strcmp (fall_back, default_uri)) - result = real_open_calendar (client, fall_back, only_if_exists, NULL); + e_mutex_lock (our_op->mutex); - g_free (default_uri); - g_free (fall_back); + e_mutex_unlock (client->priv->mutex); + + + CORBA_exception_init (&ev); - return result; + GNOME_Evolution_Calendar_Cal_remove (priv->cal, &ev); + if (BONOBO_EX (&ev)) { + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + CORBA_exception_free (&ev); + + g_warning (G_STRLOC ": Unable to contact backend"); + + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error); + } + + CORBA_exception_free (&ev); + + /* wait for something to happen (both cancellation and a + successful response will notity us via our cv */ + e_mutex_cond_wait (&our_op->cond, our_op->mutex); + + status = our_op->status; + + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + E_CALENDAR_CHECK_STATUS (status, error); } +#if 0 /* Builds an URI list out of a CORBA string sequence */ static GList * build_uri_list (GNOME_Evolution_Calendar_StringSeq *seq) @@ -981,6 +1500,7 @@ build_uri_list (GNOME_Evolution_Calendar_StringSeq *seq) return uris; } +#endif /** * cal_client_uri_list: @@ -993,6 +1513,7 @@ build_uri_list (GNOME_Evolution_Calendar_StringSeq *seq) GList * cal_client_uri_list (CalClient *client, CalMode mode) { +#if 0 CalClientPrivate *priv; GNOME_Evolution_Calendar_StringSeq *uri_seq; GList *uris = NULL; @@ -1026,8 +1547,12 @@ cal_client_uri_list (CalClient *client, CalMode mode) } return uris; +#endif + + return NULL; } + /** * cal_client_get_load_state: * @client: A calendar client. @@ -1076,33 +1601,72 @@ cal_client_get_uri (CalClient *client) * @client: A calendar client. * * Queries whether the calendar client can perform modifications - * on the calendar or not. + * on the calendar or not. Whether the backend is read only or not + * is specified, on exit, in the @read_only argument. * - * Return value: TRUE if the calendar is read-only, FALSE otherwise. + * Return value: TRUE if the call was successful, FALSE if there was an error. */ gboolean -cal_client_is_read_only (CalClient *client) +cal_client_is_read_only (CalClient *client, gboolean *read_only, GError **error) { CalClientPrivate *priv; CORBA_Environment ev; - CORBA_boolean read_only; - + ECalendarStatus status; + ECalendarOp *our_op; + g_return_val_if_fail (client != NULL, FALSE); g_return_val_if_fail (IS_CAL_CLIENT (client), FALSE); priv = client->priv; + + e_mutex_lock (client->priv->mutex); + + if (client->priv->load_state != CAL_CLIENT_LOAD_LOADED) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error); + } + + if (client->priv->current_op != NULL) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error); + } + + our_op = e_calendar_new_op (client); + + e_mutex_lock (our_op->mutex); + + e_mutex_unlock (client->priv->mutex); - if (priv->load_state != CAL_CLIENT_LOAD_LOADED) - return FALSE; CORBA_exception_init (&ev); - read_only = GNOME_Evolution_Calendar_Cal_isReadOnly (priv->cal, &ev); + + GNOME_Evolution_Calendar_Cal_isReadOnly (priv->cal, &ev); if (BONOBO_EX (&ev)) { - g_message ("cal_client_is_read_only: could not call isReadOnly method"); + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + CORBA_exception_free (&ev); + + g_warning (G_STRLOC ": Unable to contact backend"); + + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error); } + CORBA_exception_free (&ev); - return read_only; + /* wait for something to happen (both cancellation and a + successful response will notity us via our cv */ + e_mutex_cond_wait (&our_op->cond, our_op->mutex); + + status = our_op->status; + *read_only = our_op->bool; + + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + return status; } /** @@ -1115,119 +1679,269 @@ cal_client_is_read_only (CalClient *client) * is loaded or being loaded, or %NULL if the client has not started a * load request yet or the calendar has no associated email address. **/ -const char * -cal_client_get_cal_address (CalClient *client) +gboolean +cal_client_get_cal_address (CalClient *client, char **cal_address, GError **error) { CalClientPrivate *priv; - - g_return_val_if_fail (client != NULL, NULL); - g_return_val_if_fail (IS_CAL_CLIENT (client), NULL); + CORBA_Environment ev; + ECalendarStatus status; + ECalendarOp *our_op; + + g_return_val_if_fail (client != NULL, FALSE); + g_return_val_if_fail (IS_CAL_CLIENT (client), FALSE); priv = client->priv; - g_return_val_if_fail (priv->load_state == CAL_CLIENT_LOAD_LOADED, NULL); + + e_mutex_lock (client->priv->mutex); - if (priv->cal_address == NULL) { - CORBA_Environment ev; - CORBA_char *cal_address; + if (client->priv->load_state != CAL_CLIENT_LOAD_LOADED) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error); + } + + if (client->priv->current_op != NULL) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error); + } + + our_op = e_calendar_new_op (client); + + e_mutex_lock (our_op->mutex); + + e_mutex_unlock (client->priv->mutex); + + + CORBA_exception_init (&ev); + + GNOME_Evolution_Calendar_Cal_getCalAddress (priv->cal, &ev); + if (BONOBO_EX (&ev)) { + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); - CORBA_exception_init (&ev); - cal_address = GNOME_Evolution_Calendar_Cal_getCalAddress (priv->cal, &ev); - if (!BONOBO_EX (&ev)) { - priv->cal_address = g_strdup (cal_address); - CORBA_free (cal_address); - } CORBA_exception_free (&ev); + + g_warning (G_STRLOC ": Unable to contact backend"); + + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error); } - return priv->cal_address; + CORBA_exception_free (&ev); + + /* wait for something to happen (both cancellation and a + successful response will notity us via our cv */ + e_mutex_cond_wait (&our_op->cond, our_op->mutex); + + status = our_op->status; + *cal_address = our_op->string; + + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + E_CALENDAR_CHECK_STATUS (status, error); } -const char * -cal_client_get_alarm_email_address (CalClient *client) +gboolean +cal_client_get_alarm_email_address (CalClient *client, char **alarm_address, GError **error) { CalClientPrivate *priv; + CORBA_Environment ev; + ECalendarStatus status; + ECalendarOp *our_op; - g_return_val_if_fail (client != NULL, NULL); - g_return_val_if_fail (IS_CAL_CLIENT (client), NULL); + g_return_val_if_fail (client != NULL, FALSE); + g_return_val_if_fail (IS_CAL_CLIENT (client), FALSE); priv = client->priv; - g_return_val_if_fail (priv->load_state == CAL_CLIENT_LOAD_LOADED, NULL); - if (priv->alarm_email_address == NULL) { - CORBA_Environment ev; - CORBA_char *email_address; + e_mutex_lock (client->priv->mutex); + + if (client->priv->load_state != CAL_CLIENT_LOAD_LOADED) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error); + } + + if (client->priv->current_op != NULL) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error); + } + + our_op = e_calendar_new_op (client); + + e_mutex_lock (our_op->mutex); + + e_mutex_unlock (client->priv->mutex); + + + CORBA_exception_init (&ev); + + GNOME_Evolution_Calendar_Cal_getAlarmEmailAddress (priv->cal, &ev); + if (BONOBO_EX (&ev)) { + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); - CORBA_exception_init (&ev); - email_address = GNOME_Evolution_Calendar_Cal_getAlarmEmailAddress (priv->cal, &ev); - if (!BONOBO_EX (&ev)) { - priv->alarm_email_address = g_strdup (email_address); - CORBA_free (email_address); - } CORBA_exception_free (&ev); + + g_warning (G_STRLOC ": Unable to contact backend"); + + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error); } - return priv->alarm_email_address; + CORBA_exception_free (&ev); + + /* wait for something to happen (both cancellation and a + successful response will notity us via our cv */ + e_mutex_cond_wait (&our_op->cond, our_op->mutex); + + status = our_op->status; + *alarm_address = our_op->string; + + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + E_CALENDAR_CHECK_STATUS (status, error); } -const char * -cal_client_get_ldap_attribute (CalClient *client) +gboolean +cal_client_get_ldap_attribute (CalClient *client, char **ldap_attribute, GError **error) { CalClientPrivate *priv; + CORBA_Environment ev; + ECalendarStatus status; + ECalendarOp *our_op; - g_return_val_if_fail (client != NULL, NULL); - g_return_val_if_fail (IS_CAL_CLIENT (client), NULL); + g_return_val_if_fail (client != NULL, FALSE); + g_return_val_if_fail (IS_CAL_CLIENT (client), FALSE); priv = client->priv; - g_return_val_if_fail (priv->load_state == CAL_CLIENT_LOAD_LOADED, NULL); - if (priv->ldap_attribute == NULL) { - CORBA_Environment ev; - CORBA_char *ldap_attribute; + e_mutex_lock (client->priv->mutex); + + if (client->priv->load_state != CAL_CLIENT_LOAD_LOADED) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error); + } + + if (client->priv->current_op != NULL) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error); + } + + our_op = e_calendar_new_op (client); + + e_mutex_lock (our_op->mutex); + + e_mutex_unlock (client->priv->mutex); + + + CORBA_exception_init (&ev); + + GNOME_Evolution_Calendar_Cal_getLdapAttribute (priv->cal, &ev); + if (BONOBO_EX (&ev)) { + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); - CORBA_exception_init (&ev); - ldap_attribute = GNOME_Evolution_Calendar_Cal_getLdapAttribute (priv->cal, &ev); - if (!BONOBO_EX (&ev)) { - priv->ldap_attribute = g_strdup (ldap_attribute); - CORBA_free (ldap_attribute); - } CORBA_exception_free (&ev); + + g_warning (G_STRLOC ": Unable to contact backend"); + + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error); } - return priv->ldap_attribute; + CORBA_exception_free (&ev); + + /* wait for something to happen (both cancellation and a + successful response will notity us via our cv */ + e_mutex_cond_wait (&our_op->cond, our_op->mutex); + + status = our_op->status; + *ldap_attribute = our_op->string; + + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + E_CALENDAR_CHECK_STATUS (status, error); } -static void -load_static_capabilities (CalClient *client) +static gboolean +load_static_capabilities (CalClient *client, GError **error) { CalClientPrivate *priv; CORBA_Environment ev; + ECalendarStatus status; + ECalendarOp *our_op; char *cap; priv = client->priv; if (priv->capabilities) - return; - + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_OK, error); + + e_mutex_lock (client->priv->mutex); + + if (client->priv->load_state != CAL_CLIENT_LOAD_LOADED) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error); + } + + if (client->priv->current_op != NULL) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error); + } + + our_op = e_calendar_new_op (client); + + e_mutex_lock (our_op->mutex); + + e_mutex_unlock (client->priv->mutex); + + CORBA_exception_init (&ev); - cap = GNOME_Evolution_Calendar_Cal_getStaticCapabilities (priv->cal, &ev); - if (!BONOBO_EX (&ev)) - priv->capabilities = g_strdup (cap); - else - priv->capabilities = g_strdup (""); - CORBA_free (cap); + GNOME_Evolution_Calendar_Cal_getStaticCapabilities (priv->cal, &ev); + if (BONOBO_EX (&ev)) { + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + CORBA_exception_free (&ev); + + g_warning (G_STRLOC ": Unable to contact backend"); + + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error); + } + CORBA_exception_free (&ev); + + /* wait for something to happen (both cancellation and a + successful response will notity us via our cv */ + e_mutex_cond_wait (&our_op->cond, our_op->mutex); + + status = our_op->status; + cap = our_op->string; + + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + E_CALENDAR_CHECK_STATUS (status, error); } static gboolean check_capability (CalClient *client, const char *cap) { CalClientPrivate *priv; - + priv = client->priv; - load_static_capabilities (client); - if (strstr (priv->capabilities, cap)) + /* FIXME Check result */ + load_static_capabilities (client, NULL); + if (priv->capabilities && strstr (priv->capabilities, cap)) return TRUE; return FALSE; @@ -1269,15 +1983,6 @@ cal_client_get_save_schedules (CalClient *client) return check_capability (client, CAL_STATIC_CAPABILITY_SAVE_SCHEDULES); } -/* Converts our representation of a calendar component type into its CORBA representation */ -static GNOME_Evolution_Calendar_CalObjType -corba_obj_type (CalObjType type) -{ - return (((type & CALOBJ_TYPE_EVENT) ? GNOME_Evolution_Calendar_TYPE_EVENT : 0) - | ((type & CALOBJ_TYPE_TODO) ? GNOME_Evolution_Calendar_TYPE_TODO : 0) - | ((type & CALOBJ_TYPE_JOURNAL) ? GNOME_Evolution_Calendar_TYPE_JOURNAL : 0)); -} - gboolean cal_client_set_mode (CalClient *client, CalMode mode) { @@ -1302,45 +2007,6 @@ cal_client_set_mode (CalClient *client, CalMode mode) return retval; } -/** - * cal_client_get_n_objects: - * @client: A calendar client. - * @type: Type of objects that will be counted. - * - * Counts the number of calendar components of the specified @type. This can be - * used to count how many events, to-dos, or journals there are, for example. - * - * Return value: Number of components. - **/ -int -cal_client_get_n_objects (CalClient *client, CalObjType type) -{ - CalClientPrivate *priv; - CORBA_Environment ev; - int n; - int t; - - g_return_val_if_fail (client != NULL, -1); - g_return_val_if_fail (IS_CAL_CLIENT (client), -1); - - priv = client->priv; - g_return_val_if_fail (priv->load_state == CAL_CLIENT_LOAD_LOADED, -1); - - t = corba_obj_type (type); - - CORBA_exception_init (&ev); - n = GNOME_Evolution_Calendar_Cal_countObjects (priv->cal, t, &ev); - - if (BONOBO_EX (&ev)) { - g_message ("cal_client_get_n_objects(): could not get the number of objects"); - CORBA_exception_free (&ev); - return -1; - } - - CORBA_exception_free (&ev); - return n; -} - /* This is used in the callback which fetches all the timezones needed for an object. */ @@ -1348,68 +2014,93 @@ typedef struct _CalClientGetTimezonesData CalClientGetTimezonesData; struct _CalClientGetTimezonesData { CalClient *client; - /* This starts out at CAL_CLIENT_GET_SUCCESS. If an error occurs this + /* This starts out at E_CALENDAR_STATUS_OK. If an error occurs this contains the last error. */ - CalClientGetStatus status; + ECalendarStatus status; }; -CalClientGetStatus -cal_client_get_default_object (CalClient *client, CalObjType type, icalcomponent **icalcomp) +gboolean +cal_client_get_default_object (CalClient *client, icalcomponent **icalcomp, GError **error) { CalClientPrivate *priv; CORBA_Environment ev; - GNOME_Evolution_Calendar_CalObj comp_str; - CalClientGetStatus retval; - CalClientGetTimezonesData cb_data; + ECalendarStatus status; + ECalendarOp *our_op; - g_return_val_if_fail (client != NULL, CAL_CLIENT_GET_NOT_FOUND); - g_return_val_if_fail (IS_CAL_CLIENT (client), CAL_CLIENT_GET_NOT_FOUND); + g_return_val_if_fail (client != NULL, FALSE); + g_return_val_if_fail (IS_CAL_CLIENT (client), FALSE); priv = client->priv; - g_return_val_if_fail (priv->load_state == CAL_CLIENT_LOAD_LOADED, CAL_CLIENT_GET_NOT_FOUND); - g_return_val_if_fail (icalcomp != NULL, CAL_CLIENT_GET_NOT_FOUND); + e_mutex_lock (client->priv->mutex); - retval = CAL_CLIENT_GET_NOT_FOUND; - *icalcomp = NULL; + if (client->priv->load_state != CAL_CLIENT_LOAD_LOADED) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error); + } + + if (client->priv->current_op != NULL) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error); + } + + our_op = e_calendar_new_op (client); + + e_mutex_lock (our_op->mutex); + + e_mutex_unlock (client->priv->mutex); CORBA_exception_init (&ev); - comp_str = GNOME_Evolution_Calendar_Cal_getDefaultObject (priv->cal, type, &ev); - if (BONOBO_USER_EX (&ev, ex_GNOME_Evolution_Calendar_Cal_NotFound)) - goto out; - else if (BONOBO_EX (&ev)) { - g_message ("cal_client_get_default_object(): could not get the object"); - goto out; - } + GNOME_Evolution_Calendar_Cal_getDefaultObject (priv->cal, &ev); + if (BONOBO_EX (&ev)) { + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); - *icalcomp = icalparser_parse_string (comp_str); - CORBA_free (comp_str); + CORBA_exception_free (&ev); - if (!*icalcomp) { - retval = CAL_CLIENT_GET_SYNTAX_ERROR; - goto out; + g_warning (G_STRLOC ": Unable to contact backend"); + + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error); } - /* Now make sure we have all timezones needed for this object. - We do this to try to avoid any problems caused by getting a timezone - in the middle of other code. Any calls to ORBit result in a - recursive call of the GTK+ main loop, which can cause problems for - code that doesn't expect it. Currently GnomeCanvas has problems if - we try to get a timezone in the middle of a redraw, and there is a - resize pending, which leads to an assert failure and an abort. */ - cb_data.client = client; - cb_data.status = CAL_CLIENT_GET_SUCCESS; - icalcomponent_foreach_tzid (*icalcomp, - cal_client_get_object_timezones_cb, - &cb_data); + CORBA_exception_free (&ev); - retval = cb_data.status; + /* wait for something to happen (both cancellation and a + successful response will notity us via our cv */ + e_mutex_cond_wait (&our_op->cond, our_op->mutex); - out: + status = our_op->status; + *icalcomp = icalparser_parse_string (our_op->string); + g_free (our_op->string); - CORBA_exception_free (&ev); - return retval; + if (!*icalcomp) { + status = E_CALENDAR_STATUS_INVALID_OBJECT; + } else { + CalClientGetTimezonesData cb_data; + + /* Now make sure we have all timezones needed for this object. + We do this to try to avoid any problems caused by getting a timezone + in the middle of other code. Any calls to ORBit result in a + recursive call of the GTK+ main loop, which can cause problems for + code that doesn't expect it. Currently GnomeCanvas has problems if + we try to get a timezone in the middle of a redraw, and there is a + resize pending, which leads to an assert failure and an abort. */ + cb_data.client = client; + cb_data.status = E_CALENDAR_STATUS_OK; + icalcomponent_foreach_tzid (*icalcomp, + cal_client_get_object_timezones_cb, + &cb_data); + + status = cb_data.status; + } + + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + E_CALENDAR_CHECK_STATUS (status, error); } /** @@ -1423,64 +2114,89 @@ cal_client_get_default_object (CalClient *client, CalObjType type, icalcomponent * * Return value: Result code based on the status of the operation. **/ -CalClientGetStatus -cal_client_get_object (CalClient *client, const char *uid, icalcomponent **icalcomp) +gboolean +cal_client_get_object (CalClient *client, const char *uid, const char *rid, icalcomponent **icalcomp, GError **error) { + CalClientPrivate *priv; CORBA_Environment ev; - GNOME_Evolution_Calendar_CalObj comp_str; - CalClientGetStatus retval; - CalClientGetTimezonesData cb_data; + ECalendarStatus status; + ECalendarOp *our_op; - g_return_val_if_fail (client != NULL, CAL_CLIENT_GET_NOT_FOUND); - g_return_val_if_fail (IS_CAL_CLIENT (client), CAL_CLIENT_GET_NOT_FOUND); + g_return_val_if_fail (client != NULL, FALSE); + g_return_val_if_fail (IS_CAL_CLIENT (client), FALSE); priv = client->priv; - g_return_val_if_fail (priv->load_state == CAL_CLIENT_LOAD_LOADED, CAL_CLIENT_GET_NOT_FOUND); - g_return_val_if_fail (uid != NULL, CAL_CLIENT_GET_NOT_FOUND); - g_return_val_if_fail (icalcomp != NULL, CAL_CLIENT_GET_NOT_FOUND); + e_mutex_lock (client->priv->mutex); + + if (client->priv->load_state != CAL_CLIENT_LOAD_LOADED) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error); + } + + if (client->priv->current_op != NULL) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error); + } - retval = CAL_CLIENT_GET_NOT_FOUND; - *icalcomp = NULL; + our_op = e_calendar_new_op (client); + + e_mutex_lock (our_op->mutex); + + e_mutex_unlock (client->priv->mutex); CORBA_exception_init (&ev); - comp_str = GNOME_Evolution_Calendar_Cal_getObject (priv->cal, (char *) uid, &ev); - if (BONOBO_USER_EX (&ev, ex_GNOME_Evolution_Calendar_Cal_NotFound)) - goto out; - else if (BONOBO_EX (&ev)) { - g_message ("cal_client_get_object(): could not get the object"); - goto out; - } + GNOME_Evolution_Calendar_Cal_getObject (priv->cal, uid, rid ? rid : "", &ev); + if (BONOBO_EX (&ev)) { + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); - *icalcomp = icalparser_parse_string (comp_str); - CORBA_free (comp_str); + CORBA_exception_free (&ev); - if (!*icalcomp) { - retval = CAL_CLIENT_GET_SYNTAX_ERROR; - goto out; + g_warning (G_STRLOC ": Unable to contact backend"); + + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error); } - /* Now make sure we have all timezones needed for this object. - We do this to try to avoid any problems caused by getting a timezone - in the middle of other code. Any calls to ORBit result in a - recursive call of the GLib main loop, which can cause problems for - code that doesn't expect it. Currently GnomeCanvas has problems if - we try to get a timezone in the middle of a redraw, and there is a - resize pending, which leads to an assert failure and an abort. */ - cb_data.client = client; - cb_data.status = CAL_CLIENT_GET_SUCCESS; - icalcomponent_foreach_tzid (*icalcomp, - cal_client_get_object_timezones_cb, - &cb_data); + CORBA_exception_free (&ev); - retval = cb_data.status; + /* wait for something to happen (both cancellation and a + successful response will notity us via our cv */ + e_mutex_cond_wait (&our_op->cond, our_op->mutex); - out: + status = our_op->status; + *icalcomp = icalparser_parse_string (our_op->string); + g_free (our_op->string); - CORBA_exception_free (&ev); - return retval; + if (!*icalcomp) { + status = E_CALENDAR_STATUS_INVALID_OBJECT; + } else { + CalClientGetTimezonesData cb_data; + + /* Now make sure we have all timezones needed for this object. + We do this to try to avoid any problems caused by getting a timezone + in the middle of other code. Any calls to ORBit result in a + recursive call of the GTK+ main loop, which can cause problems for + code that doesn't expect it. Currently GnomeCanvas has problems if + we try to get a timezone in the middle of a redraw, and there is a + resize pending, which leads to an assert failure and an abort. */ + cb_data.client = client; + cb_data.status = E_CALENDAR_STATUS_OK; + icalcomponent_foreach_tzid (*icalcomp, + cal_client_get_object_timezones_cb, + &cb_data); + + status = cb_data.status; + } + + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + E_CALENDAR_CHECK_STATUS (status, error); } @@ -1491,106 +2207,18 @@ cal_client_get_object_timezones_cb (icalparameter *param, CalClientGetTimezonesData *cb_data = data; const char *tzid; icaltimezone *zone; - CalClientGetStatus status; + GError *error = NULL; tzid = icalparameter_get_tzid (param); if (!tzid) { - cb_data->status = CAL_CLIENT_GET_SYNTAX_ERROR; + cb_data->status = E_CALENDAR_STATUS_INVALID_OBJECT; return; } - status = cal_client_get_timezone (cb_data->client, tzid, &zone); - if (status != CAL_CLIENT_GET_SUCCESS) - cb_data->status = status; -} - - -CalClientGetStatus -cal_client_get_timezone (CalClient *client, - const char *tzid, - icaltimezone **zone) -{ - CalClientPrivate *priv; - CORBA_Environment ev; - GNOME_Evolution_Calendar_CalObj comp_str; - CalClientGetStatus retval; - icalcomponent *icalcomp; - icaltimezone *tmp_zone; - - g_return_val_if_fail (client != NULL, CAL_CLIENT_GET_NOT_FOUND); - g_return_val_if_fail (IS_CAL_CLIENT (client), CAL_CLIENT_GET_NOT_FOUND); - - priv = client->priv; - g_return_val_if_fail (priv->load_state == CAL_CLIENT_LOAD_LOADED, - CAL_CLIENT_GET_NOT_FOUND); - - g_return_val_if_fail (zone != NULL, CAL_CLIENT_GET_NOT_FOUND); - - /* If tzid is NULL or "" we return NULL, since it is a 'local time'. */ - if (!tzid || !tzid[0]) { - *zone = NULL; - return CAL_CLIENT_GET_SUCCESS; - } - - /* If it is UTC, we return the special UTC timezone. */ - if (!strcmp (tzid, "UTC")) { - *zone = icaltimezone_get_utc_timezone (); - return CAL_CLIENT_GET_SUCCESS; - } - - /* See if we already have it in the cache. */ - tmp_zone = g_hash_table_lookup (priv->timezones, tzid); - if (tmp_zone) { - *zone = tmp_zone; - return CAL_CLIENT_GET_SUCCESS; - } - - retval = CAL_CLIENT_GET_NOT_FOUND; - *zone = NULL; - - /* We don't already have it, so we try to get it from the server. */ - CORBA_exception_init (&ev); - comp_str = GNOME_Evolution_Calendar_Cal_getTimezoneObject (priv->cal, (char *) tzid, &ev); - - if (BONOBO_USER_EX (&ev, ex_GNOME_Evolution_Calendar_Cal_NotFound)) - goto out; - else if (BONOBO_EX (&ev)) { - g_message ("cal_client_get_timezone(): could not get the object"); - goto out; - } - - icalcomp = icalparser_parse_string (comp_str); - CORBA_free (comp_str); - - if (!icalcomp) { - retval = CAL_CLIENT_GET_SYNTAX_ERROR; - goto out; - } - - tmp_zone = icaltimezone_new (); - if (!tmp_zone) { - /* FIXME: Needs better error code - out of memory. Or just - abort like GLib does? */ - retval = CAL_CLIENT_GET_NOT_FOUND; - goto out; - } - - if (!icaltimezone_set_component (tmp_zone, icalcomp)) { - retval = CAL_CLIENT_GET_SYNTAX_ERROR; - goto out; - } - - /* Now add it to the cache, to avoid the server call in future. */ - g_hash_table_insert (priv->timezones, icaltimezone_get_tzid (tmp_zone), - tmp_zone); - - *zone = tmp_zone; - retval = CAL_CLIENT_GET_SUCCESS; - - out: - - CORBA_exception_free (&ev); - return retval; + if (!cal_client_get_timezone (cb_data->client, tzid, &zone, &error)) + cb_data->status = error->code; + + g_clear_error (&error); } /* Resolves TZIDs for the recurrence generator. */ @@ -1599,7 +2227,6 @@ cal_client_resolve_tzid_cb (const char *tzid, gpointer data) { CalClient *client; icaltimezone *zone = NULL; - CalClientGetStatus status; g_return_val_if_fail (data != NULL, NULL); g_return_val_if_fail (IS_CAL_CLIENT (data), NULL); @@ -1607,219 +2234,180 @@ cal_client_resolve_tzid_cb (const char *tzid, gpointer data) client = CAL_CLIENT (data); /* FIXME: Handle errors. */ - status = cal_client_get_timezone (client, tzid, &zone); + cal_client_get_timezone (client, tzid, &zone, NULL); return zone; } - -/* Builds an UID list out of a CORBA UID sequence */ -static GList * -build_uid_list (GNOME_Evolution_Calendar_CalObjUIDSeq *seq) -{ - GList *uids; - int i; - - uids = NULL; - - for (i = 0; i < seq->_length; i++) - uids = g_list_prepend (uids, g_strdup (seq->_buffer[i])); - - return uids; -} - -/** - * cal_client_get_uids: - * @client: A calendar client. - * @type: Bitmask with types of objects to return. - * - * Queries a calendar for a list of unique identifiers corresponding to calendar - * objects whose type matches one of the types specified in the @type flags. - * - * Return value: A list of strings that are the sought UIDs. This should be - * freed using the cal_obj_uid_list_free() function. - **/ -GList * -cal_client_get_uids (CalClient *client, CalObjType type) +gboolean +cal_client_get_changes (CalClient *client, CalObjType type, const char *change_id, GList **changes, GError **error) { - CalClientPrivate *priv; CORBA_Environment ev; - GNOME_Evolution_Calendar_CalObjUIDSeq *seq; - int t; - GList *uids; + ECalendarOp *our_op; + ECalendarStatus status; - g_return_val_if_fail (client != NULL, NULL); - g_return_val_if_fail (IS_CAL_CLIENT (client), NULL); + g_return_val_if_fail (client != NULL, E_CALENDAR_STATUS_INVALID_ARG); + g_return_val_if_fail (IS_CAL_CLIENT (client), E_CALENDAR_STATUS_INVALID_ARG); + g_return_val_if_fail (change_id != NULL, E_CALENDAR_STATUS_INVALID_ARG); - priv = client->priv; - g_return_val_if_fail (priv->load_state == CAL_CLIENT_LOAD_LOADED, NULL); + e_mutex_lock (client->priv->mutex); - t = corba_obj_type (type); - - CORBA_exception_init (&ev); + if (client->priv->load_state != CAL_CLIENT_LOAD_LOADED) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error); + } - seq = GNOME_Evolution_Calendar_Cal_getUIDs (priv->cal, t, &ev); - if (BONOBO_EX (&ev)) { - g_message ("cal_client_get_uids(): could not get the list of UIDs"); - CORBA_exception_free (&ev); - return NULL; + if (client->priv->current_op != NULL) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error); } - CORBA_exception_free (&ev); + our_op = e_calendar_new_op (client); - uids = build_uid_list (seq); - CORBA_free (seq); + e_mutex_lock (our_op->mutex); - return uids; -} + e_mutex_unlock (client->priv->mutex); -/* Builds a GList of CalClientChange structures from the CORBA sequence */ -static GList * -build_change_list (GNOME_Evolution_Calendar_CalObjChangeSeq *seq) -{ - GList *list = NULL; - icalcomponent *icalcomp; - int i; + CORBA_exception_init (&ev); - /* Create the list in reverse order */ - for (i = 0; i < seq->_length; i++) { - GNOME_Evolution_Calendar_CalObjChange *corba_coc; - CalClientChange *ccc; + GNOME_Evolution_Calendar_Cal_getChanges (client->priv->cal, type, change_id, &ev); - corba_coc = &seq->_buffer[i]; - ccc = g_new (CalClientChange, 1); + if (BONOBO_EX (&ev)) { + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); - icalcomp = icalparser_parse_string (corba_coc->calobj); - if (!icalcomp) - continue; + CORBA_exception_free (&ev); - ccc->comp = cal_component_new (); - if (!cal_component_set_icalcomponent (ccc->comp, icalcomp)) { - icalcomponent_free (icalcomp); - g_object_unref (G_OBJECT (ccc->comp)); - continue; - } - ccc->type = corba_coc->type; + g_warning (G_STRLOC ": Unable to contact backend"); - list = g_list_prepend (list, ccc); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error); } + + CORBA_exception_free (&ev); + + /* wait for something to happen (both cancellation and a + successful response will notity us via our cv */ + e_mutex_cond_wait (&our_op->cond, our_op->mutex); - list = g_list_reverse (list); + status = our_op->status; + *changes = our_op->list; - return list; + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + E_CALENDAR_CHECK_STATUS (status, error); } -GList * -cal_client_get_changes (CalClient *client, CalObjType type, const char *change_id) + +/** + * cal_client_get_object_list: + * @client: + * @query: + * + * + * + * Return value: + **/ +gboolean +cal_client_get_object_list (CalClient *client, const char *query, GList **objects, GError **error) { - CalClientPrivate *priv; CORBA_Environment ev; - GNOME_Evolution_Calendar_CalObjChangeSeq *seq; - int t; - GList *changes; + ECalendarOp *our_op; + ECalendarStatus status; - g_return_val_if_fail (client != NULL, NULL); - g_return_val_if_fail (IS_CAL_CLIENT (client), NULL); + g_return_val_if_fail (client != NULL, E_CALENDAR_STATUS_INVALID_ARG); + g_return_val_if_fail (IS_CAL_CLIENT (client), E_CALENDAR_STATUS_INVALID_ARG); + g_return_val_if_fail (query != NULL, E_CALENDAR_STATUS_INVALID_ARG); - priv = client->priv; - g_return_val_if_fail (priv->load_state == CAL_CLIENT_LOAD_LOADED, NULL); + e_mutex_lock (client->priv->mutex); - t = corba_obj_type (type); - CORBA_exception_init (&ev); + if (client->priv->load_state != CAL_CLIENT_LOAD_LOADED) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error); + } - seq = GNOME_Evolution_Calendar_Cal_getChanges (priv->cal, t, change_id, &ev); - if (BONOBO_EX (&ev)) { - g_message ("cal_client_get_changes(): could not get the list of changes"); - CORBA_exception_free (&ev); - return NULL; + if (client->priv->current_op != NULL) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error); } - CORBA_exception_free (&ev); + our_op = e_calendar_new_op (client); - changes = build_change_list (seq); - CORBA_free (seq); + e_mutex_lock (our_op->mutex); - return changes; -} + e_mutex_unlock (client->priv->mutex); -/* FIXME: Not used? */ -#if 0 -/* Builds a GList of CalObjInstance structures from the CORBA sequence */ -static GList * -build_object_instance_list (GNOME_Evolution_Calendar_CalObjInstanceSeq *seq) -{ - GList *list; - int i; + CORBA_exception_init (&ev); - /* Create the list in reverse order */ + GNOME_Evolution_Calendar_Cal_getObjectList (client->priv->cal, query, &ev); - list = NULL; - for (i = 0; i < seq->_length; i++) { - GNOME_Evolution_Calendar_CalObjInstance *corba_icoi; - CalObjInstance *icoi; + if (BONOBO_EX (&ev)) { + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); - corba_icoi = &seq->_buffer[i]; - icoi = g_new (CalObjInstance, 1); + CORBA_exception_free (&ev); - icoi->uid = g_strdup (corba_icoi->uid); - icoi->start = corba_icoi->start; - icoi->end = corba_icoi->end; + g_warning (G_STRLOC ": Unable to contact backend"); - list = g_list_prepend (list, icoi); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error); } + + CORBA_exception_free (&ev); - list = g_list_reverse (list); - return list; -} -#endif - -/** - * cal_client_get_objects_in_range: - * @client: A calendar client. - * @type: Bitmask with types of objects to return. - * @start: Start time for query. - * @end: End time for query. - * - * Queries a calendar for the objects that occur or recur in the specified range - * of time. - * - * Return value: A list of UID strings. This should be freed using the - * cal_obj_uid_list_free() function. - **/ -GList * -cal_client_get_objects_in_range (CalClient *client, CalObjType type, time_t start, time_t end) -{ - CalClientPrivate *priv; - CORBA_Environment ev; - GNOME_Evolution_Calendar_CalObjUIDSeq *seq; - GList *uids; - int t; - - g_return_val_if_fail (client != NULL, NULL); - g_return_val_if_fail (IS_CAL_CLIENT (client), NULL); + /* wait for something to happen (both cancellation and a + successful response will notity us via our cv */ + e_mutex_cond_wait (&our_op->cond, our_op->mutex); - priv = client->priv; - g_return_val_if_fail (priv->load_state == CAL_CLIENT_LOAD_LOADED, NULL); + status = our_op->status; + *objects = our_op->list; - g_return_val_if_fail (start != -1 && end != -1, NULL); - g_return_val_if_fail (start <= end, NULL); + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); - CORBA_exception_init (&ev); - - t = corba_obj_type (type); + E_CALENDAR_CHECK_STATUS (status, error); +} - seq = GNOME_Evolution_Calendar_Cal_getObjectsInRange (priv->cal, t, start, end, &ev); - if (BONOBO_EX (&ev)) { - g_message ("cal_client_get_objects_in_range(): could not get the objects"); - CORBA_exception_free (&ev); - return NULL; +gboolean +cal_client_get_object_list_as_comp (CalClient *client, const char *query, GList **objects, GError **error) +{ + GList *ical_objects = NULL; + GList *l; + + g_return_val_if_fail (client != NULL, E_CALENDAR_STATUS_INVALID_ARG); + g_return_val_if_fail (IS_CAL_CLIENT (client), E_CALENDAR_STATUS_INVALID_ARG); + g_return_val_if_fail (query != NULL, E_CALENDAR_STATUS_INVALID_ARG); + g_return_val_if_fail (objects != NULL, E_CALENDAR_STATUS_INVALID_ARG); + + if (!cal_client_get_object_list (client, query, &ical_objects, error)) + return FALSE; + + *objects = NULL; + for (l = ical_objects; l; l = l->next) { + CalComponent *comp; + + comp = cal_component_new (); + cal_component_set_icalcomponent (comp, l->data); + *objects = g_list_prepend (*objects, comp); } - CORBA_exception_free (&ev); + + g_list_free (ical_objects); - uids = build_uid_list (seq); - CORBA_free (seq); + return TRUE; +} + +void +cal_client_free_object_list (GList *objects) +{ + GList *l; + + for (l = objects; l; l = l->next) + icalcomponent_free (l->data); - return uids; + g_list_free (objects); } /** @@ -1833,57 +2421,81 @@ cal_client_get_objects_in_range (CalClient *client, CalObjType type, time_t star * * Returns: a GList of VFREEBUSY CalComponents */ -GList * -cal_client_get_free_busy (CalClient *client, GList *users, - time_t start, time_t end) +gboolean +cal_client_get_free_busy (CalClient *client, GList *users, time_t start, time_t end, + GList **freebusy, GError **error) { - CalClientPrivate *priv; CORBA_Environment ev; - GNOME_Evolution_Calendar_UserList *corba_list; - GNOME_Evolution_Calendar_CalObjSeq *calobj_list; + ECalendarOp *our_op; + ECalendarStatus status; + GNOME_Evolution_Calendar_UserList corba_users; GList *l; - GList *comp_list = NULL; - int len, i; + int i, len; + + g_return_val_if_fail (client != NULL, E_CALENDAR_STATUS_INVALID_ARG); + g_return_val_if_fail (IS_CAL_CLIENT (client), E_CALENDAR_STATUS_INVALID_ARG); - g_return_val_if_fail (client != NULL, NULL); - g_return_val_if_fail (IS_CAL_CLIENT (client), NULL); + e_mutex_lock (client->priv->mutex); - priv = client->priv; - g_return_val_if_fail (priv->load_state == CAL_CLIENT_LOAD_LOADED, NULL); + if (client->priv->load_state != CAL_CLIENT_LOAD_LOADED) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error); + } - g_return_val_if_fail (start != -1 && end != -1, NULL); - g_return_val_if_fail (start <= end, NULL); + if (client->priv->current_op != NULL) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error); + } + + our_op = e_calendar_new_op (client); + + e_mutex_lock (our_op->mutex); + + e_mutex_unlock (client->priv->mutex); /* create the CORBA user list to be passed to the backend */ len = g_list_length (users); - corba_list = GNOME_Evolution_Calendar_UserList__alloc (); - CORBA_sequence_set_release (corba_list, TRUE); - corba_list->_length = len; - corba_list->_buffer = CORBA_sequence_GNOME_Evolution_Calendar_User_allocbuf (len); + corba_users._length = len; + corba_users._buffer = CORBA_sequence_GNOME_Evolution_Calendar_User_allocbuf (len); - for (l = g_list_first (users), i = 0; l; l = l->next, i++) - corba_list->_buffer[i] = CORBA_string_dup ((CORBA_char *) l->data); + for (l = users, i = 0; l; l = l->next, i++) + corba_users._buffer[i] = CORBA_string_dup (l->data); - /* call the method on the backend */ CORBA_exception_init (&ev); - calobj_list = GNOME_Evolution_Calendar_Cal_getFreeBusy (priv->cal, corba_list, - start, end, &ev); - CORBA_free (corba_list); - if (BONOBO_EX (&ev) || !calobj_list) { - if (!BONOBO_USER_EX (&ev, ex_GNOME_Evolution_Calendar_Cal_NotFound)) - g_message ("cal_client_get_free_busy(): could not get the objects"); + GNOME_Evolution_Calendar_Cal_getFreeBusy (client->priv->cal, &corba_users, start, end, &ev); + + CORBA_free (corba_users._buffer); + + if (BONOBO_EX (&ev)) { + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + CORBA_exception_free (&ev); - return NULL; + + g_warning (G_STRLOC ": Unable to contact backend"); + + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error); } + + CORBA_exception_free (&ev); - for (i = 0; i < calobj_list->_length; i++) { + /* wait for something to happen (both cancellation and a + successful response will notity us via our cv */ + e_mutex_cond_wait (&our_op->cond, our_op->mutex); + + status = our_op->status; + + *freebusy = NULL; + for (l = our_op->list; l; l = l->next) { CalComponent *comp; + icalcomponent *icalcomp; icalcomponent_kind kind; - icalcomp = icalparser_parse_string (calobj_list->_buffer[i]); + icalcomp = icalparser_parse_string (l->data); if (!icalcomp) continue; @@ -1896,184 +2508,17 @@ cal_client_get_free_busy (CalClient *client, GList *users, continue; } - comp_list = g_list_append (comp_list, comp); + *freebusy = g_list_append (*freebusy, comp); } else icalcomponent_free (icalcomp); } - CORBA_exception_free (&ev); - CORBA_free (calobj_list); - - return comp_list; -} - -/* Callback used when an object is updated and we must update the copy we have */ -static void -generate_instances_obj_updated_cb (CalClient *client, const char *uid, gpointer data) -{ - GHashTable *uid_comp_hash; - CalComponent *comp; - icalcomponent *icalcomp; - CalClientGetStatus status; - const char *comp_uid; - - uid_comp_hash = data; - - comp = g_hash_table_lookup (uid_comp_hash, uid); - if (!comp) - /* OK, so we don't care about new objects that may indeed be in - * the requested time range. We only care about the ones that - * were returned by the first query to - * cal_client_get_objects_in_range(). - */ - return; - - g_hash_table_remove (uid_comp_hash, uid); - g_object_unref (G_OBJECT (comp)); - - status = cal_client_get_object (client, uid, &icalcomp); - - switch (status) { - case CAL_CLIENT_GET_SUCCESS: - comp = cal_component_new (); - if (cal_component_set_icalcomponent (comp, icalcomp)) { - /* The hash key comes from the component's internal data */ - cal_component_get_uid (comp, &comp_uid); - g_hash_table_insert (uid_comp_hash, (char *) comp_uid, comp); - } else { - g_object_unref (comp); - icalcomponent_free (icalcomp); - } - break; - - case CAL_CLIENT_GET_NOT_FOUND: - /* No longer in the server, too bad */ - break; - - case CAL_CLIENT_GET_SYNTAX_ERROR: - g_message ("obj_updated_cb(): Syntax error when getting " - "object `%s'; ignoring...", uid); - break; - - } -} - -/* Callback used when an object is removed and we must delete the copy we have */ -static void -generate_instances_obj_removed_cb (CalClient *client, const char *uid, gpointer data) -{ - GHashTable *uid_comp_hash; - CalComponent *comp; - - uid_comp_hash = data; - - comp = g_hash_table_lookup (uid_comp_hash, uid); - if (!comp) - return; - - g_hash_table_remove (uid_comp_hash, uid); - g_object_unref (G_OBJECT (comp)); -} - -/* Adds a component to the list; called from g_hash_table_foreach() */ -static void -add_component (gpointer key, gpointer value, gpointer data) -{ - CalComponent *comp; - GList **list; - - comp = CAL_COMPONENT (value); - list = data; - - *list = g_list_prepend (*list, comp); -} - -/* Gets a list of components that recur within the specified range of time. It - * ensures that the resulting list of CalComponent objects contains only objects - * that are actually in the server at the time the initial - * cal_client_get_objects_in_range() query ends. - */ -static GList * -get_objects_atomically (CalClient *client, CalObjType type, time_t start, time_t end) -{ - GList *uids; - GHashTable *uid_comp_hash; - GList *objects; - guint obj_updated_id; - guint obj_removed_id; - GList *l; - - uids = cal_client_get_objects_in_range (client, type, start, end); - - uid_comp_hash = g_hash_table_new (g_str_hash, g_str_equal); - - /* While we are getting the actual object data, keep track of changes */ - - obj_updated_id = g_signal_connect (G_OBJECT (client), "obj_updated", - G_CALLBACK (generate_instances_obj_updated_cb), - uid_comp_hash); - - obj_removed_id = g_signal_connect (G_OBJECT (client), "obj_removed", - G_CALLBACK (generate_instances_obj_removed_cb), - uid_comp_hash); - - /* Get the objects */ - - for (l = uids; l; l = l->next) { - CalComponent *comp; - icalcomponent *icalcomp; - CalClientGetStatus status; - char *uid; - const char *comp_uid; - - uid = l->data; - - status = cal_client_get_object (client, uid, &icalcomp); - - switch (status) { - case CAL_CLIENT_GET_SUCCESS: - comp = cal_component_new (); - if (cal_component_set_icalcomponent (comp, icalcomp)) { - /* The hash key comes from the component's internal data - * instead of the duped UID from the list of UIDS. - */ - cal_component_get_uid (comp, &comp_uid); - g_hash_table_insert (uid_comp_hash, (char *) comp_uid, comp); - } else { - g_object_unref (comp); - icalcomponent_free (icalcomp); - } - break; - - case CAL_CLIENT_GET_NOT_FOUND: - /* Object disappeared from the server, so don't log it */ - break; - - case CAL_CLIENT_GET_SYNTAX_ERROR: - g_message ("get_objects_atomically(): Syntax error when getting " - "object `%s'; ignoring...", uid); - break; - - default: - g_assert_not_reached (); - } - } - - cal_obj_uid_list_free (uids); - - /* Now our state is consistent with the server, so disconnect from the - * notification signals and generate the final list of components. - */ + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); - g_signal_handler_disconnect (client, obj_updated_id); - g_signal_handler_disconnect (client, obj_removed_id); - - objects = NULL; - g_hash_table_foreach (uid_comp_hash, add_component, &objects); - g_hash_table_destroy (uid_comp_hash); - - return objects; + E_CALENDAR_CHECK_STATUS (status, error); } struct comp_instance { @@ -2127,10 +2572,8 @@ compare_comp_instance (gconstpointer a, gconstpointer b) * @cb: Callback for each generated instance. * @cb_data: Closure data for the callback. * - * Does a combination of cal_client_get_objects_in_range() and - * cal_recur_generate_instances(). It fetches the list of objects in an atomic - * way so that the generated instances are actually in the server at the time - * the initial cal_client_get_objects_in_range() query ends. + * Does a combination of cal_client_get_object_list () and + * cal_recur_generate_instances(). * * The callback function should do a g_object_ref() of the calendar component * it gets passed if it intends to keep it around. @@ -2144,7 +2587,8 @@ cal_client_generate_instances (CalClient *client, CalObjType type, GList *objects; GList *instances; GList *l; - + char *query; + g_return_if_fail (client != NULL); g_return_if_fail (IS_CAL_CLIENT (client)); @@ -2156,8 +2600,13 @@ cal_client_generate_instances (CalClient *client, CalObjType type, g_return_if_fail (cb != NULL); /* Generate objects */ + query = g_strdup_printf ("(occur-in-time-range? (%lu) (%lu))", start, end); + if (!cal_client_get_object_list (client, query, &objects, NULL)) { + g_free (query); + return; + } + g_free (query); - objects = get_objects_atomically (client, type, start, end); instances = NULL; for (l = objects; l; l = l->next) { @@ -2201,64 +2650,22 @@ cal_client_generate_instances (CalClient *client, CalObjType type, g_list_free (instances); } -/* Builds a list of CalAlarmInstance structures */ -static GSList * -build_alarm_instance_list (CalComponent *comp, GNOME_Evolution_Calendar_CalAlarmInstanceSeq *seq) -{ - GSList *alarms; - int i; - - alarms = NULL; - - for (i = 0; i < seq->_length; i++) { - GNOME_Evolution_Calendar_CalAlarmInstance *corba_instance; - CalComponentAlarm *alarm; - const char *auid; - CalAlarmInstance *instance; - - corba_instance = seq->_buffer + i; - - /* Since we want the in-commponent auid, we look for the alarm - * in the component and fetch its "real" auid. - */ - - alarm = cal_component_get_alarm (comp, corba_instance->auid); - if (!alarm) - continue; - - auid = cal_component_alarm_get_uid (alarm); - cal_component_alarm_free (alarm); - - instance = g_new (CalAlarmInstance, 1); - instance->auid = auid; - instance->trigger = corba_instance->trigger; - instance->occur_start = corba_instance->occur_start; - instance->occur_end = corba_instance->occur_end; - - alarms = g_slist_prepend (alarms, instance); - } - - return g_slist_reverse (alarms); -} - /* Builds a list of CalComponentAlarms structures */ static GSList * -build_component_alarms_list (GNOME_Evolution_Calendar_CalComponentAlarmsSeq *seq) +build_component_alarms_list (CalClient *client, GList *object_list, time_t start, time_t end) { GSList *comp_alarms; - int i; + GList *l; comp_alarms = NULL; - for (i = 0; i < seq->_length; i++) { - GNOME_Evolution_Calendar_CalComponentAlarms *corba_alarms; + for (l = object_list; l != NULL; l = l->next) { CalComponent *comp; CalComponentAlarms *alarms; icalcomponent *icalcomp; + CalAlarmAction omit[] = {-1}; - corba_alarms = seq->_buffer + i; - - icalcomp = icalparser_parse_string (corba_alarms->calobj); + icalcomp = icalparser_parse_string (l->data); if (!icalcomp) continue; @@ -2269,11 +2676,10 @@ build_component_alarms_list (GNOME_Evolution_Calendar_CalComponentAlarmsSeq *seq continue; } - alarms = g_new (CalComponentAlarms, 1); - alarms->comp = comp; - alarms->alarms = build_alarm_instance_list (comp, &corba_alarms->alarms); - - comp_alarms = g_slist_prepend (comp_alarms, alarms); + alarms = cal_util_generate_alarms_for_comp (comp, start, end, omit, cal_client_resolve_tzid_cb, + icalcomp, client->priv->default_zone); + if (alarms) + comp_alarms = g_slist_prepend (comp_alarms, alarms); } return comp_alarms; @@ -2297,9 +2703,9 @@ GSList * cal_client_get_alarms_in_range (CalClient *client, time_t start, time_t end) { CalClientPrivate *priv; - CORBA_Environment ev; - GNOME_Evolution_Calendar_CalComponentAlarmsSeq *seq; GSList *alarms; + char *sexp; + GList *object_list = NULL; g_return_val_if_fail (client != NULL, NULL); g_return_val_if_fail (IS_CAL_CLIENT (client), NULL); @@ -2310,18 +2716,20 @@ cal_client_get_alarms_in_range (CalClient *client, time_t start, time_t end) g_return_val_if_fail (start != -1 && end != -1, NULL); g_return_val_if_fail (start <= end, NULL); - CORBA_exception_init (&ev); + /* build the query string */ + sexp = g_strdup ("(and (has-alarms? #t))"); - seq = GNOME_Evolution_Calendar_Cal_getAlarmsInRange (priv->cal, start, end, &ev); - if (BONOBO_EX (&ev)) { - g_message ("cal_client_get_alarms_in_range(): could not get the alarm range"); - CORBA_exception_free (&ev); + /* execute the query on the server */ + if (!cal_client_get_object_list (client, sexp, &object_list, NULL)) { + g_free (sexp); return NULL; } - CORBA_exception_free (&ev); - alarms = build_component_alarms_list (seq); - CORBA_free (seq); + alarms = build_component_alarms_list (client, object_list, start, end); + + g_list_foreach (object_list, (GFunc) g_free, NULL); + g_list_free (object_list); + g_free (sexp); return alarms; } @@ -2371,11 +2779,9 @@ cal_client_get_alarms_for_object (CalClient *client, const char *uid, CalComponentAlarms **alarms) { CalClientPrivate *priv; - CORBA_Environment ev; - GNOME_Evolution_Calendar_CalComponentAlarms *corba_alarms; - gboolean retval; icalcomponent *icalcomp; CalComponent *comp; + CalAlarmAction omit[] = {-1}; g_return_val_if_fail (client != NULL, FALSE); g_return_val_if_fail (IS_CAL_CLIENT (client), FALSE); @@ -2389,40 +2795,23 @@ cal_client_get_alarms_for_object (CalClient *client, const char *uid, g_return_val_if_fail (alarms != NULL, FALSE); *alarms = NULL; - retval = FALSE; - - CORBA_exception_init (&ev); - - corba_alarms = GNOME_Evolution_Calendar_Cal_getAlarmsForObject (priv->cal, (char *) uid, - start, end, &ev); - if (BONOBO_USER_EX (&ev, ex_GNOME_Evolution_Calendar_Cal_NotFound)) - goto out; - else if (BONOBO_EX (&ev)) { - g_message ("cal_client_get_alarms_for_object(): could not get the alarm range"); - goto out; - } - icalcomp = icalparser_parse_string (corba_alarms->calobj); + if (!cal_client_get_object (client, uid, NULL, &icalcomp, NULL)) + return FALSE; if (!icalcomp) - goto out; + return FALSE; comp = cal_component_new (); if (!cal_component_set_icalcomponent (comp, icalcomp)) { icalcomponent_free (icalcomp); g_object_unref (G_OBJECT (comp)); - goto out; + return FALSE; } - retval = TRUE; - - *alarms = g_new (CalComponentAlarms, 1); - (*alarms)->comp = comp; - (*alarms)->alarms = build_alarm_instance_list (comp, &corba_alarms->alarms); - CORBA_free (corba_alarms); + *alarms = cal_util_generate_alarms_for_comp (comp, start, end, omit, cal_client_resolve_tzid_cb, + icalcomp, priv->default_zone); - out: - CORBA_exception_free (&ev); - return retval; + return TRUE; } /** @@ -2439,33 +2828,68 @@ cal_client_get_alarms_for_object (CalClient *client, const char *uid, * Return value: a #CalClientResult value indicating the result of the * operation. */ -CalClientResult -cal_client_discard_alarm (CalClient *client, CalComponent *comp, const char *auid) +gboolean +cal_client_discard_alarm (CalClient *client, CalComponent *comp, const char *auid, GError **error) { CalClientPrivate *priv; - CalClientResult retval; CORBA_Environment ev; + ECalendarStatus status; + ECalendarOp *our_op; const char *uid; - - g_return_val_if_fail (IS_CAL_CLIENT (client), CAL_CLIENT_RESULT_NOT_FOUND); - g_return_val_if_fail (IS_CAL_COMPONENT (comp), CAL_CLIENT_RESULT_NOT_FOUND); - g_return_val_if_fail (auid != NULL, CAL_CLIENT_RESULT_NOT_FOUND); + + g_return_val_if_fail (client != NULL, FALSE); + g_return_val_if_fail (IS_CAL_CLIENT (client), FALSE); priv = client->priv; + e_mutex_lock (client->priv->mutex); + + if (client->priv->load_state != CAL_CLIENT_LOAD_LOADED) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error); + } + + if (client->priv->current_op != NULL) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error); + } + + our_op = e_calendar_new_op (client); + + e_mutex_lock (our_op->mutex); + + e_mutex_unlock (client->priv->mutex); + cal_component_get_uid (comp, &uid); CORBA_exception_init (&ev); + GNOME_Evolution_Calendar_Cal_discardAlarm (priv->cal, uid, auid, &ev); - if (BONOBO_USER_EX (&ev, ex_GNOME_Evolution_Calendar_Cal_NotFound)) - retval = CAL_CLIENT_RESULT_NOT_FOUND; - else if (BONOBO_EX (&ev)) - retval = CAL_CLIENT_RESULT_CORBA_ERROR; - else - retval = CAL_CLIENT_RESULT_SUCCESS; + if (BONOBO_EX (&ev)) { + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + CORBA_exception_free (&ev); + + g_warning (G_STRLOC ": Unable to contact backend"); + + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error); + } CORBA_exception_free (&ev); - return retval; + + /* wait for something to happen (both cancellation and a + successful response will notity us via our cv */ + e_mutex_cond_wait (&our_op->cond, our_op->mutex); + + status = our_op->status; + + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + E_CALENDAR_CHECK_STATUS (status, error); } typedef struct _ForeachTZIDCallbackData ForeachTZIDCallbackData; @@ -2500,10 +2924,7 @@ foreach_tzid_callback (icalparameter *param, void *cbdata) return; if (data->include_all_timezones) { - CalClientGetStatus status; - - status = cal_client_get_timezone (data->client, tzid, &zone); - if (status != CAL_CLIENT_GET_SUCCESS) { + if (!cal_client_get_timezone (data->client, tzid, &zone, NULL)) { data->success = FALSE; return; } @@ -2642,163 +3063,192 @@ cal_client_get_component_as_string (CalClient *client, icalcomponent *icalcomp) return cal_client_get_component_as_string_internal (client, icalcomp, TRUE); } -CalClientResult -cal_client_update_object_with_mod (CalClient *client, CalComponent *comp, CalObjModType mod) +gboolean +cal_client_create_object (CalClient *client, icalcomponent *icalcomp, char **uid, GError **error) { CalClientPrivate *priv; CORBA_Environment ev; - CalClientResult retval; - char *obj_string; + ECalendarStatus status; + ECalendarOp *our_op; - g_return_val_if_fail (client != NULL, CAL_CLIENT_RESULT_INVALID_OBJECT); - g_return_val_if_fail (IS_CAL_CLIENT (client), CAL_CLIENT_RESULT_INVALID_OBJECT); + g_return_val_if_fail (client != NULL, FALSE); + g_return_val_if_fail (IS_CAL_CLIENT (client), FALSE); priv = client->priv; - g_return_val_if_fail (priv->load_state == CAL_CLIENT_LOAD_LOADED, CAL_CLIENT_RESULT_INVALID_OBJECT); - g_return_val_if_fail (comp != NULL, CAL_CLIENT_RESULT_INVALID_OBJECT); + e_mutex_lock (client->priv->mutex); - cal_component_commit_sequence (comp); + if (client->priv->load_state != CAL_CLIENT_LOAD_LOADED) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error); + } - obj_string = cal_client_get_component_as_string_internal (client, - cal_component_get_icalcomponent (comp), - FALSE); - if (obj_string == NULL) - return CAL_CLIENT_RESULT_INVALID_OBJECT; + if (client->priv->current_op != NULL) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error); + } + + our_op = e_calendar_new_op (client); + + e_mutex_lock (our_op->mutex); + + e_mutex_unlock (client->priv->mutex); CORBA_exception_init (&ev); - GNOME_Evolution_Calendar_Cal_updateObjects (priv->cal, obj_string, mod, &ev); - g_free (obj_string); - - if (BONOBO_USER_EX (&ev, ex_GNOME_Evolution_Calendar_Cal_InvalidObject)) - retval = CAL_CLIENT_RESULT_INVALID_OBJECT; - else if (BONOBO_USER_EX (&ev, ex_GNOME_Evolution_Calendar_Cal_NotFound)) - retval = CAL_CLIENT_RESULT_NOT_FOUND; - else if (BONOBO_USER_EX (&ev, ex_GNOME_Evolution_Calendar_Cal_PermissionDenied)) - retval = CAL_CLIENT_RESULT_PERMISSION_DENIED; - else if (BONOBO_EX (&ev)) { - g_message ("cal_client_update_object(): could not update the object"); - retval = CAL_CLIENT_RESULT_CORBA_ERROR; + + GNOME_Evolution_Calendar_Cal_createObject (priv->cal, icalcomponent_as_ical_string (icalcomp), &ev); + if (BONOBO_EX (&ev)) { + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + CORBA_exception_free (&ev); + + g_warning (G_STRLOC ": Unable to contact backend"); + + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error); } - else - retval = CAL_CLIENT_RESULT_SUCCESS; CORBA_exception_free (&ev); - return retval; -} + /* wait for something to happen (both cancellation and a + successful response will notity us via our cv */ + e_mutex_cond_wait (&our_op->cond, our_op->mutex); -/** - * cal_client_update_object: - * @client: A calendar client. - * @comp: A calendar component object. - * - * Asks a calendar to update a component. Any existing component with the - * specified component's UID will be replaced. The client program should not - * assume that the object is actually in the server's storage until it has - * received the "obj_updated" notification signal. - * - * Return value: a #CalClientResult value indicating the result of the - * operation. - **/ -CalClientResult -cal_client_update_object (CalClient *client, CalComponent *comp) -{ + status = our_op->status; + if (uid) + *uid = our_op->uid; + + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); - return cal_client_update_object_with_mod (client, comp, CALOBJ_MOD_ALL); + E_CALENDAR_CHECK_STATUS (status, error); } -/** - * cal_client_update_objects: - * @client: A calendar client. - * @icalcomp: A toplevel VCALENDAR libical component. - * - * Asks a calendar to add or update one or more components, possibly including - * VTIMEZONE data. Any existing components with the same UIDs will be - * replaced. The VTIMEZONE data will be compared to existing VTIMEZONEs in - * the calendar, and the VTIMEZONEs may possibly be renamed, as well as all - * references to them throughout the VCALENDAR. - * - * The client program should not assume that the objects are actually in the - * server's storage until it has received the "obj_updated" notification - * signal. - * - * Return value: a #CalClientResult value indicating the result of the - * operation. - **/ -CalClientResult -cal_client_update_objects (CalClient *client, icalcomponent *icalcomp) +gboolean +cal_client_modify_object (CalClient *client, icalcomponent *icalcomp, CalObjModType mod, GError **error) { CalClientPrivate *priv; CORBA_Environment ev; - CalClientResult retval; - char *obj_string; + ECalendarStatus status; + ECalendarOp *our_op; - g_return_val_if_fail (client != NULL, CAL_CLIENT_RESULT_INVALID_OBJECT); - g_return_val_if_fail (IS_CAL_CLIENT (client), CAL_CLIENT_RESULT_INVALID_OBJECT); + g_return_val_if_fail (client != NULL, FALSE); + g_return_val_if_fail (IS_CAL_CLIENT (client), FALSE); + g_return_val_if_fail (icalcomp != NULL, FALSE); priv = client->priv; - g_return_val_if_fail (priv->load_state == CAL_CLIENT_LOAD_LOADED, - CAL_CLIENT_RESULT_INVALID_OBJECT); - g_return_val_if_fail (icalcomp != NULL, CAL_CLIENT_RESULT_INVALID_OBJECT); + e_mutex_lock (client->priv->mutex); - /* Libical owns this memory, using one of its temporary buffers. */ - obj_string = icalcomponent_as_ical_string (icalcomp); + if (client->priv->load_state != CAL_CLIENT_LOAD_LOADED) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error); + } + + if (client->priv->current_op != NULL) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error); + } + + our_op = e_calendar_new_op (client); + + e_mutex_lock (our_op->mutex); + + e_mutex_unlock (client->priv->mutex); CORBA_exception_init (&ev); - GNOME_Evolution_Calendar_Cal_updateObjects (priv->cal, obj_string, GNOME_Evolution_Calendar_MOD_ALL, &ev); - - if (BONOBO_USER_EX (&ev, ex_GNOME_Evolution_Calendar_Cal_InvalidObject)) - retval = CAL_CLIENT_RESULT_INVALID_OBJECT; - else if (BONOBO_USER_EX (&ev, ex_GNOME_Evolution_Calendar_Cal_NotFound)) - retval = CAL_CLIENT_RESULT_NOT_FOUND; - else if (BONOBO_USER_EX (&ev, ex_GNOME_Evolution_Calendar_Cal_PermissionDenied)) - retval = CAL_CLIENT_RESULT_PERMISSION_DENIED; - else if (BONOBO_EX (&ev)) { - g_message ("cal_client_update_objects(): could not update the objects"); - retval = CAL_CLIENT_RESULT_CORBA_ERROR; + + GNOME_Evolution_Calendar_Cal_modifyObject (priv->cal, icalcomponent_as_ical_string (icalcomp), mod, &ev); + if (BONOBO_EX (&ev)) { + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + CORBA_exception_free (&ev); + + g_warning (G_STRLOC ": Unable to contact backend"); + + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error); } - else - retval = CAL_CLIENT_RESULT_SUCCESS; CORBA_exception_free (&ev); - return retval; + + /* wait for something to happen (both cancellation and a + successful response will notity us via our cv */ + e_mutex_cond_wait (&our_op->cond, our_op->mutex); + + status = our_op->status; + + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + E_CALENDAR_CHECK_STATUS (status, error); } -CalClientResult -cal_client_remove_object_with_mod (CalClient *client, const char *uid, CalObjModType mod) +gboolean +cal_client_remove_object_with_mod (CalClient *client, const char *uid, + const char *rid, CalObjModType mod, GError **error) { CalClientPrivate *priv; CORBA_Environment ev; - CalClientResult retval; + ECalendarStatus status; + ECalendarOp *our_op; - g_return_val_if_fail (client != NULL, CAL_CLIENT_RESULT_INVALID_OBJECT); - g_return_val_if_fail (IS_CAL_CLIENT (client), CAL_CLIENT_RESULT_INVALID_OBJECT); + g_return_val_if_fail (client != NULL, FALSE); + g_return_val_if_fail (IS_CAL_CLIENT (client), FALSE); priv = client->priv; - g_return_val_if_fail (priv->load_state == CAL_CLIENT_LOAD_LOADED, CAL_CLIENT_RESULT_INVALID_OBJECT); - g_return_val_if_fail (uid != NULL, CAL_CLIENT_RESULT_NOT_FOUND); + e_mutex_lock (client->priv->mutex); + + if (client->priv->load_state != CAL_CLIENT_LOAD_LOADED) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error); + } + + if (client->priv->current_op != NULL) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error); + } + + our_op = e_calendar_new_op (client); + + e_mutex_lock (our_op->mutex); + + e_mutex_unlock (client->priv->mutex); + CORBA_exception_init (&ev); - GNOME_Evolution_Calendar_Cal_removeObject (priv->cal, (char *) uid, mod, &ev); - - if (BONOBO_USER_EX (&ev, ex_GNOME_Evolution_Calendar_Cal_InvalidObject)) - retval = CAL_CLIENT_RESULT_INVALID_OBJECT; - else if (BONOBO_USER_EX (&ev, ex_GNOME_Evolution_Calendar_Cal_NotFound)) - retval = CAL_CLIENT_RESULT_NOT_FOUND; - else if (BONOBO_USER_EX (&ev, ex_GNOME_Evolution_Calendar_Cal_PermissionDenied)) - retval = CAL_CLIENT_RESULT_PERMISSION_DENIED; - else if (BONOBO_EX (&ev)) { - g_message ("cal_client_remove_object(): could not remove the object"); - retval = CAL_CLIENT_RESULT_CORBA_ERROR; + + GNOME_Evolution_Calendar_Cal_removeObject (priv->cal, uid, rid ? rid : "", mod, &ev); + if (BONOBO_EX (&ev)) { + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + CORBA_exception_free (&ev); + + g_warning (G_STRLOC ": Unable to contact backend"); + + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error); } - else - retval = CAL_CLIENT_RESULT_SUCCESS; CORBA_exception_free (&ev); - return retval; + + /* wait for something to happen (both cancellation and a + successful response will notity us via our cv */ + e_mutex_cond_wait (&our_op->cond, our_op->mutex); + + status = our_op->status; + + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + E_CALENDAR_CHECK_STATUS (status, error); } /** @@ -2813,69 +3263,319 @@ cal_client_remove_object_with_mod (CalClient *client, const char *uid, CalObjMod * Return value: a #CalClientResult value indicating the result of the * operation. **/ -CalClientResult -cal_client_remove_object (CalClient *client, const char *uid) +gboolean +cal_client_remove_object (CalClient *client, const char *uid, GError **error) { - return cal_client_remove_object_with_mod (client, uid, CALOBJ_MOD_ALL); + g_return_val_if_fail (client != NULL, FALSE); + g_return_val_if_fail (IS_CAL_CLIENT (client), FALSE); + + return cal_client_remove_object_with_mod (client, uid, NULL, CALOBJ_MOD_ALL, error); } -CalClientResult -cal_client_send_object (CalClient *client, icalcomponent *icalcomp, - icalcomponent **new_icalcomp, GList **users, - char **error_msg) +gboolean +cal_client_receive_objects (CalClient *client, icalcomponent *icalcomp, GError **error) { CalClientPrivate *priv; CORBA_Environment ev; - CalClientResult retval; - GNOME_Evolution_Calendar_UserList *user_list; - char *obj_string; - int i; + ECalendarStatus status; + ECalendarOp *our_op; + + g_return_val_if_fail (client != NULL, FALSE); + g_return_val_if_fail (IS_CAL_CLIENT (client), FALSE); + + priv = client->priv; + + e_mutex_lock (client->priv->mutex); + + if (client->priv->load_state != CAL_CLIENT_LOAD_LOADED) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error); + } + + if (client->priv->current_op != NULL) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error); + } + + our_op = e_calendar_new_op (client); + + e_mutex_lock (our_op->mutex); + + e_mutex_unlock (client->priv->mutex); + + CORBA_exception_init (&ev); + + GNOME_Evolution_Calendar_Cal_receiveObjects (priv->cal, icalcomponent_as_ical_string (icalcomp), &ev); + if (BONOBO_EX (&ev)) { + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + CORBA_exception_free (&ev); + + g_warning (G_STRLOC ": Unable to contact backend"); + + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error); + } + + CORBA_exception_free (&ev); + + /* wait for something to happen (both cancellation and a + successful response will notity us via our cv */ + e_mutex_cond_wait (&our_op->cond, our_op->mutex); + + status = our_op->status; - g_return_val_if_fail (client != NULL, CAL_CLIENT_RESULT_INVALID_OBJECT); - g_return_val_if_fail (IS_CAL_CLIENT (client), CAL_CLIENT_RESULT_INVALID_OBJECT); + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + E_CALENDAR_CHECK_STATUS (status, error); +} + +gboolean +cal_client_send_objects (CalClient *client, icalcomponent *icalcomp, GError **error) +{ + CalClientPrivate *priv; + CORBA_Environment ev; + ECalendarStatus status; + ECalendarOp *our_op; + + g_return_val_if_fail (client != NULL, FALSE); + g_return_val_if_fail (IS_CAL_CLIENT (client), FALSE); priv = client->priv; - g_return_val_if_fail (priv->load_state == CAL_CLIENT_LOAD_LOADED, - CAL_CLIENT_RESULT_INVALID_OBJECT); - g_return_val_if_fail (icalcomp != NULL, CAL_CLIENT_RESULT_INVALID_OBJECT); + e_mutex_lock (client->priv->mutex); - /* Libical owns this memory, using one of its temporary buffers. */ - obj_string = icalcomponent_as_ical_string (icalcomp); + if (client->priv->load_state != CAL_CLIENT_LOAD_LOADED) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error); + } + + if (client->priv->current_op != NULL) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error); + } + + our_op = e_calendar_new_op (client); + + e_mutex_lock (our_op->mutex); + + e_mutex_unlock (client->priv->mutex); CORBA_exception_init (&ev); - obj_string = GNOME_Evolution_Calendar_Cal_sendObject (priv->cal, obj_string, &user_list, &ev); - - if (BONOBO_USER_EX (&ev, ex_GNOME_Evolution_Calendar_Cal_InvalidObject)) { - retval = CAL_CLIENT_SEND_INVALID_OBJECT; - } else if (BONOBO_USER_EX (&ev, ex_GNOME_Evolution_Calendar_Cal_Busy)) { - retval = CAL_CLIENT_SEND_BUSY; - if (error_msg) - *error_msg = g_strdup (((GNOME_Evolution_Calendar_Cal_Busy *)(CORBA_exception_value (&ev)))->errorMsg); - } else if (BONOBO_USER_EX (&ev, ex_GNOME_Evolution_Calendar_Cal_PermissionDenied)) { - retval = CAL_CLIENT_SEND_PERMISSION_DENIED; - } else if (BONOBO_EX (&ev)) { - g_message ("cal_client_update_objects(): could not send the objects"); - retval = CAL_CLIENT_SEND_CORBA_ERROR; + + GNOME_Evolution_Calendar_Cal_sendObjects (priv->cal, icalcomponent_as_ical_string (icalcomp), &ev); + if (BONOBO_EX (&ev)) { + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + CORBA_exception_free (&ev); + + g_warning (G_STRLOC ": Unable to contact backend"); + + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error); + } + + CORBA_exception_free (&ev); + + /* wait for something to happen (both cancellation and a + successful response will notity us via our cv */ + e_mutex_cond_wait (&our_op->cond, our_op->mutex); + + status = our_op->status; + + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + E_CALENDAR_CHECK_STATUS (status, error); +} + +gboolean +cal_client_get_timezone (CalClient *client, const char *tzid, icaltimezone **zone, GError **error) +{ + CalClientPrivate *priv; + CORBA_Environment ev; + ECalendarStatus status; + ECalendarOp *our_op; + icalcomponent *icalcomp; + + g_return_val_if_fail (IS_CAL_CLIENT (client), FALSE); + g_return_val_if_fail (tzid != NULL, FALSE); + + priv = client->priv; + + e_mutex_lock (priv->mutex); + + if (client->priv->load_state != CAL_CLIENT_LOAD_LOADED) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error); + } + + if (client->priv->current_op != NULL) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error); + } + + our_op = e_calendar_new_op (client); + + e_mutex_lock (our_op->mutex); + + e_mutex_unlock (priv->mutex); + + /* Check for well known zones and in the cache */ + *zone = NULL; + + /* If tzid is NULL or "" we return NULL, since it is a 'local time'. */ + if (!tzid || !tzid[0]) { + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_OK, error); + } + + /* If it is UTC, we return the special UTC timezone. */ + if (!strcmp (tzid, "UTC")) { + *zone = icaltimezone_get_utc_timezone (); } else { - retval = CAL_CLIENT_RESULT_SUCCESS; - - *new_icalcomp = icalparser_parse_string (obj_string); - CORBA_free (obj_string); - - if (*new_icalcomp == NULL) { - retval = CAL_CLIENT_RESULT_INVALID_OBJECT; - } else { - *users = NULL; - for (i = 0; i < user_list->_length; i++) - *users = g_list_append (*users, g_strdup (user_list->_buffer[i])); - CORBA_free (user_list); - } + /* See if we already have it in the cache. */ + *zone = g_hash_table_lookup (priv->timezones, tzid); + } + + if (*zone) { + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_OK, error); } + /* call the backend */ + CORBA_exception_init (&ev); + + GNOME_Evolution_Calendar_Cal_getTimezone (priv->cal, tzid, &ev); + if (BONOBO_EX (&ev)) { + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + CORBA_exception_free (&ev); + + g_warning (G_STRLOC ": Unable to contact backend"); + + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error); + } + CORBA_exception_free (&ev); - return retval; + /* wait for something to happen (both cancellation and a + successful response will notity us via our cv */ + e_mutex_cond_wait (&our_op->cond, our_op->mutex); + + status = our_op->status; + + icalcomp = icalparser_parse_string (our_op->string); + g_free (our_op->string); + + /* FIXME Invalid object status? */ + if (!icalcomp) + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_OBJECT_NOT_FOUND, error); + + *zone = icaltimezone_new (); + if (!icaltimezone_set_component (*zone, icalcomp)) { + icaltimezone_free (*zone, 1); + + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_OBJECT_NOT_FOUND, error); + } + + /* Now add it to the cache, to avoid the server call in future. */ + g_hash_table_insert (priv->timezones, icaltimezone_get_tzid (*zone), *zone); + + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + E_CALENDAR_CHECK_STATUS (status, error); +} + +/** + * cal_client_add_timezone + * @client: A calendar client. + * @izone: The timezone to add. + * @error: Placeholder for error information. + * + * Add a VTIMEZONE object to the given calendar. + * + * Returns: TRUE if successful, FALSE otherwise. + */ +gboolean +cal_client_add_timezone (CalClient *client, icaltimezone *izone, GError **error) +{ + CalClientPrivate *priv; + CORBA_Environment ev; + ECalendarStatus status; + ECalendarOp *our_op; + const char *tzobj; + + g_return_val_if_fail (IS_CAL_CLIENT (client), FALSE); + g_return_val_if_fail (izone != NULL, FALSE); + + priv = client->priv; + + e_mutex_lock (priv->mutex); + + if (client->priv->load_state != CAL_CLIENT_LOAD_LOADED) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error); + } + + if (client->priv->current_op != NULL) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error); + } + + our_op = e_calendar_new_op (client); + + e_mutex_lock (our_op->mutex); + + e_mutex_unlock (priv->mutex); + + /* convert icaltimezone into a string */ + tzobj = icalcomponent_as_ical_string (icaltimezone_get_component (izone)); + + /* call the backend */ + CORBA_exception_init (&ev); + + GNOME_Evolution_Calendar_Cal_addTimezone (priv->cal, tzobj, &ev); + if (BONOBO_EX (&ev)) { + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + CORBA_exception_free (&ev); + + g_warning (G_STRLOC ": Unable to contact backend"); + + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error); + } + + CORBA_exception_free (&ev); + + /* wait for something to happen (both cancellation and a + successful response will notity us via our cv */ + e_mutex_cond_wait (&our_op->cond, our_op->mutex); + + status = our_op->status; + + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + E_CALENDAR_CHECK_STATUS (status, error); } /** @@ -2888,20 +3588,68 @@ cal_client_send_object (CalClient *client, icalcomponent *icalcomp, * Return value: A query object that will emit notification signals as calendar * components are added and removed from the query in the server. **/ -CalQuery * -cal_client_get_query (CalClient *client, const char *sexp) +gboolean +cal_client_get_query (CalClient *client, const char *sexp, CalQuery **query, GError **error) { - CalClientPrivate *priv; + CORBA_Environment ev; + ECalendarOp *our_op; + ECalendarStatus status; - g_return_val_if_fail (client != NULL, NULL); - g_return_val_if_fail (IS_CAL_CLIENT (client), NULL); + g_return_val_if_fail (client != NULL, E_CALENDAR_STATUS_INVALID_ARG); + g_return_val_if_fail (IS_CAL_CLIENT (client), E_CALENDAR_STATUS_INVALID_ARG); + g_return_val_if_fail (query != NULL, E_CALENDAR_STATUS_INVALID_ARG); - priv = client->priv; - g_return_val_if_fail (priv->load_state == CAL_CLIENT_LOAD_LOADED, FALSE); + e_mutex_lock (client->priv->mutex); + + if (client->priv->load_state != CAL_CLIENT_LOAD_LOADED) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error); + } - g_return_val_if_fail (sexp != NULL, NULL); + if (client->priv->current_op != NULL) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error); + } + + our_op = e_calendar_new_op (client); + + e_mutex_lock (our_op->mutex); + + e_mutex_unlock (client->priv->mutex); + + CORBA_exception_init (&ev); + + our_op->listener = query_listener_new (); + GNOME_Evolution_Calendar_Cal_getQuery (client->priv->cal, sexp, BONOBO_OBJREF (our_op->listener), &ev); - return cal_query_new (client, priv->cal, sexp); + if (BONOBO_EX (&ev)) { + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + CORBA_exception_free (&ev); + + g_warning (G_STRLOC ": Unable to contact backend"); + + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error); + } + + CORBA_exception_free (&ev); + + /* wait for something to happen (both cancellation and a + successful response will notity us via our cv */ + e_mutex_cond_wait (&our_op->cond, our_op->mutex); + + status = our_op->status; + *query = our_op->query; + + bonobo_object_unref (BONOBO_OBJECT (our_op->listener)); + + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + E_CALENDAR_CHECK_STATUS (status, error); } @@ -2910,19 +3658,16 @@ cal_client_get_query (CalClient *client, const char *sexp) DATE-TIME values into specific times. (Most of our IDL interface uses time_t values to pass specific times from the server to the client.) */ static gboolean -cal_client_ensure_timezone_on_server (CalClient *client, icaltimezone *zone) +cal_client_ensure_timezone_on_server (CalClient *client, icaltimezone *zone, GError **error) { CalClientPrivate *priv; - char *tzid, *obj_string; + char *tzid; icaltimezone *tmp_zone; - GString *vcal_string; - gboolean retval = FALSE; - icalcomponent *vtimezone_comp; - char *vtimezone_as_string; - CORBA_Environment ev; priv = client->priv; + /* FIXME This is highly broken since there is no locking */ + /* If the zone is NULL or UTC we don't need to do anything. */ if (!zone) return TRUE; @@ -2940,89 +3685,128 @@ cal_client_ensure_timezone_on_server (CalClient *client, icaltimezone *zone) /* Now we have to send it to the server, in case it doesn't already have it. */ - - vcal_string = g_string_new (NULL); - g_string_append (vcal_string, - "BEGIN:VCALENDAR\n" - "PRODID:-//Ximian//NONSGML Evolution Calendar//EN\n" - "VERSION:2.0\n"); - - /* Convert the timezone to a string and add it. */ - vtimezone_comp = icaltimezone_get_component (zone); - if (!vtimezone_comp) { - g_string_free (vcal_string, TRUE); - return FALSE; - } - - /* We don't need to free this string as libical owns it. */ - vtimezone_as_string = icalcomponent_as_ical_string (vtimezone_comp); - g_string_append (vcal_string, vtimezone_as_string); - - g_string_append (vcal_string, "END:VCALENDAR\n"); - - obj_string = vcal_string->str; - g_string_free (vcal_string, FALSE); - - CORBA_exception_init (&ev); - GNOME_Evolution_Calendar_Cal_updateObjects (priv->cal, obj_string, GNOME_Evolution_Calendar_MOD_ALL, &ev); - g_free (obj_string); - - if (BONOBO_USER_EX (&ev, ex_GNOME_Evolution_Calendar_Cal_InvalidObject)) - goto out; - else if (BONOBO_EX (&ev)) { - g_message ("cal_client_ensure_timezone_on_server(): could not add the timezone to the server"); - goto out; - } - - retval = TRUE; - - out: - CORBA_exception_free (&ev); - return retval; + return cal_client_add_timezone (client, zone, error); } - gboolean -cal_client_set_default_timezone (CalClient *client, icaltimezone *zone) +cal_client_set_default_timezone (CalClient *client, icaltimezone *zone, GError **error) { CalClientPrivate *priv; - gboolean retval = FALSE; CORBA_Environment ev; + ECalendarStatus status; + ECalendarOp *our_op; const char *tzid; - - g_return_val_if_fail (client != NULL, FALSE); + g_return_val_if_fail (IS_CAL_CLIENT (client), FALSE); g_return_val_if_fail (zone != NULL, FALSE); priv = client->priv; - g_return_val_if_fail (priv->load_state == CAL_CLIENT_LOAD_LOADED, - FALSE); - /* Make sure the server has the VTIMEZONE data. */ - if (!cal_client_ensure_timezone_on_server (client, zone)) + if (!cal_client_ensure_timezone_on_server (client, zone, error)) return FALSE; - /* Now set the default timezone on the server. */ - CORBA_exception_init (&ev); - tzid = icaltimezone_get_tzid (zone); - GNOME_Evolution_Calendar_Cal_setDefaultTimezone (priv->cal, - (char *) tzid, &ev); + e_mutex_lock (priv->mutex); - if (BONOBO_USER_EX (&ev, ex_GNOME_Evolution_Calendar_Cal_NotFound)) - goto out; - else if (BONOBO_EX (&ev)) { - g_message ("cal_client_set_default_timezone(): could not set the default timezone"); - goto out; + if (client->priv->load_state != CAL_CLIENT_LOAD_LOADED) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error); } - retval = TRUE; + if (client->priv->current_op != NULL) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error); + } + + our_op = e_calendar_new_op (client); + + e_mutex_lock (our_op->mutex); + + e_mutex_unlock (priv->mutex); - priv->default_zone = zone; + /* FIXME Adding it to the server to change the tzid */ + tzid = icaltimezone_get_tzid (zone); + + /* call the backend */ + CORBA_exception_init (&ev); - out: + GNOME_Evolution_Calendar_Cal_setDefaultTimezone (priv->cal, tzid, &ev); + if (BONOBO_EX (&ev)) { + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + CORBA_exception_free (&ev); + + g_warning (G_STRLOC ": Unable to contact backend"); + + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error); + } CORBA_exception_free (&ev); - return retval; + + /* wait for something to happen (both cancellation and a + successful response will notity us via our cv */ + e_mutex_cond_wait (&our_op->cond, our_op->mutex); + + status = our_op->status; + + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + E_CALENDAR_CHECK_STATUS (status, error); } +/** + * cal_client_get_error_message + * @status: A status code. + * + * Get an error message for the given status code. + * + * Returns: the error message. + */ +const char * +cal_client_get_error_message (ECalendarStatus status) +{ + switch (status) { + case E_CALENDAR_STATUS_INVALID_ARG : + return _("Invalid argument"); + case E_CALENDAR_STATUS_BUSY : + return _("Backend is busy"); + case E_CALENDAR_STATUS_REPOSITORY_OFFLINE : + return _("Repository is offline"); + case E_CALENDAR_STATUS_NO_SUCH_CALENDAR : + return _("No such calendar"); + case E_CALENDAR_STATUS_OBJECT_NOT_FOUND : + return _("Object not found"); + case E_CALENDAR_STATUS_INVALID_OBJECT : + return _("Invalid object"); + case E_CALENDAR_STATUS_URI_NOT_LOADED : + return _("URI not loaded"); + case E_CALENDAR_STATUS_URI_ALREADY_LOADED : + return _("URI already loaded"); + case E_CALENDAR_STATUS_PERMISSION_DENIED : + return _("Permission denied"); + case E_CALENDAR_STATUS_CARD_NOT_FOUND : + return _("Object not found"); + case E_CALENDAR_STATUS_CARD_ID_ALREADY_EXISTS : + return _("Object ID already exists"); + case E_CALENDAR_STATUS_PROTOCOL_NOT_SUPPORTED : + return _("Protocol not supported"); + case E_CALENDAR_STATUS_CANCELLED : + return _("Operation has been cancelled"); + case E_CALENDAR_STATUS_COULD_NOT_CANCEL : + return _("Could not cancel operation"); + case E_CALENDAR_STATUS_AUTHENTICATION_FAILED : + return _("Authentication failed"); + case E_CALENDAR_STATUS_AUTHENTICATION_REQUIRED : + return _("Authentication required"); + case E_CALENDAR_STATUS_CORBA_EXCEPTION : + return _("A CORBA esception has occurred"); + case E_CALENDAR_STATUS_OTHER_ERROR : + return _("Unknown error"); + } + + return NULL; +} |