diff options
Diffstat (limited to 'calendar/cal-client')
-rw-r--r-- | calendar/cal-client/.cvsignore | 2 | ||||
-rw-r--r-- | calendar/cal-client/Makefile.am | 7 | ||||
-rw-r--r-- | calendar/cal-client/cal-client-types.h | 26 | ||||
-rw-r--r-- | calendar/cal-client/cal-client.c | 3710 | ||||
-rw-r--r-- | calendar/cal-client/cal-client.h | 101 | ||||
-rw-r--r-- | calendar/cal-client/cal-listener.c | 895 | ||||
-rw-r--r-- | calendar/cal-client/cal-listener.h | 53 | ||||
-rw-r--r-- | calendar/cal-client/cal-marshal.list | 6 | ||||
-rw-r--r-- | calendar/cal-client/cal-query.c | 470 | ||||
-rw-r--r-- | calendar/cal-client/cal-query.h | 37 | ||||
-rw-r--r-- | calendar/cal-client/client-test.c | 155 | ||||
-rw-r--r-- | calendar/cal-client/query-listener.c | 393 | ||||
-rw-r--r-- | calendar/cal-client/query-listener.h | 44 |
13 files changed, 3611 insertions, 2288 deletions
diff --git a/calendar/cal-client/.cvsignore b/calendar/cal-client/.cvsignore index 1537e6e01d..f2aa4f92ae 100644 --- a/calendar/cal-client/.cvsignore +++ b/calendar/cal-client/.cvsignore @@ -10,6 +10,8 @@ evolution-calendar.h evolution-calendar-common.lo evolution-calendar-skels.lo evolution-calendar-stubs.lo +cal-marshal.c +cal-marshal.h *.lo *.la client-test diff --git a/calendar/cal-client/Makefile.am b/calendar/cal-client/Makefile.am index 5e48e7db23..5f8b5a3cf1 100644 --- a/calendar/cal-client/Makefile.am +++ b/calendar/cal-client/Makefile.am @@ -38,6 +38,8 @@ libcal_clientincludedir = $(privincludedir)/cal-client libcal_client_la_SOURCES = \ $(CORBA_GENERATED_C) \ cal-client-types.c \ + cal-marshal.c \ + cal--marshal.h \ cal-client.c \ cal-listener.c \ cal-listener.h \ @@ -72,7 +74,10 @@ client_test_LDADD = \ libcal-client.la \ $(EVOLUTION_CALENDAR_LIBS) -BUILT_SOURCES = $(CORBA_GENERATED) +MARSHAL_GENERATED = cal-marshal.c cal-marshal.h +@EVO_MARSHAL_RULE@ + +BUILT_SOURCES = $(CORBA_GENERATED) $(MARSHAL_GENERATED) CLEANFILES = $(BUILT_SOURCES) dist-hook: diff --git a/calendar/cal-client/cal-client-types.h b/calendar/cal-client/cal-client-types.h index c160a1fa94..925628337b 100644 --- a/calendar/cal-client/cal-client-types.h +++ b/calendar/cal-client/cal-client-types.h @@ -29,6 +29,10 @@ G_BEGIN_DECLS +#define E_CALENDAR_ERROR e_calendar_error_quark() + +GQuark e_calendar_error_quark (void) G_GNUC_CONST; + typedef enum { CAL_CLIENT_CHANGE_ADDED = 1 << 0, CAL_CLIENT_CHANGE_MODIFIED = 1 << 1, @@ -41,6 +45,28 @@ typedef struct CalClientChangeType type; } CalClientChange; +typedef enum { + E_CALENDAR_STATUS_OK, + E_CALENDAR_STATUS_INVALID_ARG, + E_CALENDAR_STATUS_BUSY, + E_CALENDAR_STATUS_REPOSITORY_OFFLINE, + E_CALENDAR_STATUS_NO_SUCH_CALENDAR, + E_CALENDAR_STATUS_OBJECT_NOT_FOUND, + E_CALENDAR_STATUS_INVALID_OBJECT, + E_CALENDAR_STATUS_URI_NOT_LOADED, + E_CALENDAR_STATUS_URI_ALREADY_LOADED, + E_CALENDAR_STATUS_PERMISSION_DENIED, + E_CALENDAR_STATUS_CARD_NOT_FOUND, + E_CALENDAR_STATUS_CARD_ID_ALREADY_EXISTS, + E_CALENDAR_STATUS_PROTOCOL_NOT_SUPPORTED, + E_CALENDAR_STATUS_CANCELLED, + E_CALENDAR_STATUS_COULD_NOT_CANCEL, + E_CALENDAR_STATUS_AUTHENTICATION_FAILED, + E_CALENDAR_STATUS_AUTHENTICATION_REQUIRED, + E_CALENDAR_STATUS_CORBA_EXCEPTION, + E_CALENDAR_STATUS_OTHER_ERROR +} ECalendarStatus; + void cal_client_change_list_free (GList *list); G_END_DECLS 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; +} diff --git a/calendar/cal-client/cal-client.h b/calendar/cal-client/cal-client.h index 961ba5d993..277522f097 100644 --- a/calendar/cal-client/cal-client.h +++ b/calendar/cal-client/cal-client.h @@ -25,6 +25,7 @@ #include <cal-util/cal-recur.h> #include <cal-util/cal-util.h> #include <cal-client/cal-query.h> +#include "cal-client-types.h" G_BEGIN_DECLS @@ -37,6 +38,7 @@ G_BEGIN_DECLS #define IS_CAL_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CAL_CLIENT_TYPE)) #define CAL_CLIENT_OPEN_STATUS_ENUM_TYPE (cal_client_open_status_enum_get_type ()) +#define CAL_CLIENT_REMOVE_STATUS_ENUM_TYPE (cal_client_remove_status_enum_get_type ()) #define CAL_CLIENT_SET_MODE_STATUS_ENUM_TYPE (cal_client_set_mode_status_enum_get_type ()) #define CAL_MODE_ENUM_TYPE (cal_mode_enum_get_type ()) @@ -76,14 +78,6 @@ typedef enum { CAL_CLIENT_RESULT_PERMISSION_DENIED } CalClientResult; -typedef enum { - CAL_CLIENT_SEND_SUCCESS, - CAL_CLIENT_SEND_CORBA_ERROR, - CAL_CLIENT_SEND_INVALID_OBJECT, - CAL_CLIENT_SEND_BUSY, - CAL_CLIENT_SEND_PERMISSION_DENIED -} CalClientSendResult; - /* Whether the client is not loaded, is being loaded, or is already loaded */ typedef enum { CAL_CLIENT_LOAD_NOT_LOADED, @@ -104,10 +98,7 @@ struct _CalClientClass { /* Notification signals */ void (* cal_opened) (CalClient *client, CalClientOpenStatus status); - void (* cal_set_mode) (CalClient *client, CalClientSetModeStatus status, CalMode mode); - - void (* obj_updated) (CalClient *client, const char *uid); - void (* obj_removed) (CalClient *client, const char *uid); + void (* cal_set_mode) (CalClient *client, CalClientSetModeStatus status, CalMode mode); void (* backend_error) (CalClient *client, const char *message); @@ -129,21 +120,13 @@ GType cal_client_open_status_enum_get_type (void); GType cal_client_set_mode_status_enum_get_type (void); GType cal_mode_enum_get_type (void); -CalClient *cal_client_construct (CalClient *client); - -CalClient *cal_client_new (void); +CalClient *cal_client_new (const char *uri, CalObjType type); void cal_client_set_auth_func (CalClient *client, CalClientAuthFunc func, gpointer data); -/* Sets the default timezone to use to resolve DATE and floating DATE-TIME - values. This will typically be from the user's timezone setting. Call this - before using any other functions. It will pass the default timezone on to - the server. Returns TRUE on success. */ -gboolean cal_client_set_default_timezone (CalClient *client, icaltimezone *zone); - -gboolean cal_client_open_calendar (CalClient *client, const char *str_uri, gboolean only_if_exists); -gboolean cal_client_open_default_calendar (CalClient *client, gboolean only_if_exists); -gboolean cal_client_open_default_tasks (CalClient *client, gboolean only_if_exists); +gboolean cal_client_open (CalClient *client, gboolean only_if_exists, GError **error); +void cal_client_open_async (CalClient *client, gboolean only_if_exists); +gboolean cal_client_remove_calendar (CalClient *client, GError **error); GList *cal_client_uri_list (CalClient *client, CalMode mode); @@ -151,11 +134,10 @@ CalClientLoadState cal_client_get_load_state (CalClient *client); const char *cal_client_get_uri (CalClient *client); -gboolean cal_client_is_read_only (CalClient *client); - -const char *cal_client_get_cal_address (CalClient *client); -const char *cal_client_get_alarm_email_address (CalClient *client); -const char *cal_client_get_ldap_attribute (CalClient *client); +gboolean cal_client_is_read_only (CalClient *client, gboolean *read_only, GError **error); +gboolean cal_client_get_cal_address (CalClient *client, char **cal_address, GError **error); +gboolean cal_client_get_alarm_email_address (CalClient *client, char **alarm_address, GError **error); +gboolean cal_client_get_ldap_attribute (CalClient *client, char **ldap_attribute, GError **error); gboolean cal_client_get_one_alarm_only (CalClient *client); gboolean cal_client_get_organizer_must_attend (CalClient *client); @@ -164,28 +146,23 @@ gboolean cal_client_get_static_capability (CalClient *client, const char *cap); gboolean cal_client_set_mode (CalClient *client, CalMode mode); -int cal_client_get_n_objects (CalClient *client, CalObjType type); - -CalClientGetStatus cal_client_get_default_object (CalClient *client, - CalObjType type, - icalcomponent **icalcomp); +gboolean cal_client_get_default_object (CalClient *client, + icalcomponent **icalcomp, GError **error); -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); -CalClientGetStatus cal_client_get_timezone (CalClient *client, - const char *tzid, - icaltimezone **zone); +gboolean cal_client_get_changes (CalClient *client, CalObjType type, const char *change_id, GList **changes, GError **error); -GList *cal_client_get_uids (CalClient *client, CalObjType type); -GList *cal_client_get_changes (CalClient *client, CalObjType type, const char *change_id); +gboolean cal_client_get_object_list (CalClient *client, const char *query, GList **objects, GError **error); +gboolean cal_client_get_object_list_as_comp (CalClient *client, const char *query, GList **objects, GError **error); +void cal_client_free_object_list (GList *objects); -GList *cal_client_get_objects_in_range (CalClient *client, CalObjType type, - time_t start, time_t end); - -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); void cal_client_generate_instances (CalClient *client, CalObjType type, time_t start, time_t end, @@ -199,24 +176,25 @@ gboolean cal_client_get_alarms_for_object (CalClient *client, const char *uid, time_t start, time_t end, CalComponentAlarms **alarms); -CalClientResult cal_client_discard_alarm (CalClient *client, CalComponent *comp, const char *auid); - -/* Add or update a single object. When adding an object only builtin timezones - are allowed. To use external VTIMEZONE data call update_objects() instead.*/ -CalClientResult cal_client_update_object (CalClient *client, CalComponent *comp); -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); +gboolean cal_client_modify_object (CalClient *client, icalcomponent *icalcomp, CalObjModType mod, GError **error); +gboolean cal_client_remove_object (CalClient *client, const char *uid, GError **error); +gboolean cal_client_remove_object_with_mod (CalClient *client, const char *uid, const char *rid, CalObjModType mod, GError **error); -/* Add or update multiple objects, possibly including VTIMEZONE data. */ -CalClientResult cal_client_update_objects (CalClient *client, icalcomponent *icalcomp); +gboolean cal_client_discard_alarm (CalClient *client, CalComponent *comp, const char *auid, GError **error); -CalClientResult cal_client_remove_object (CalClient *client, const char *uid); -CalClientResult cal_client_remove_object_with_mod (CalClient *client, const char *uid, CalObjModType mod); +gboolean cal_client_receive_objects (CalClient *client, icalcomponent *icalcomp, GError **error); +gboolean cal_client_send_objects (CalClient *client, icalcomponent *icalcomp, GError **error); -CalClientSendResult cal_client_send_object (CalClient *client, icalcomponent *icalcomp, - icalcomponent **new_icalcomp, GList **users, - char **error_msg); +gboolean cal_client_get_timezone (CalClient *client, const char *tzid, icaltimezone **zone, GError **error); +gboolean cal_client_add_timezone (CalClient *client, icaltimezone *izone, GError **error); +/* Sets the default timezone to use to resolve DATE and floating DATE-TIME + values. This will typically be from the user's timezone setting. Call this + before using any other functions. It will pass the default timezone on to + the server. Returns TRUE on success. */ +gboolean cal_client_set_default_timezone (CalClient *client, icaltimezone *zone, GError **error); -CalQuery *cal_client_get_query (CalClient *client, const char *sexp); +gboolean cal_client_get_query (CalClient *client, const char *sexp, CalQuery **query, GError **error); /* Resolves TZIDs for the recurrence generator. */ icaltimezone *cal_client_resolve_tzid_cb (const char *tzid, gpointer data); @@ -225,6 +203,7 @@ icaltimezone *cal_client_resolve_tzid_cb (const char *tzid, gpointer data); used by the component. It also includes a 'METHOD:PUBLISH' property. */ char* cal_client_get_component_as_string (CalClient *client, icalcomponent *icalcomp); +const char * cal_client_get_error_message (ECalendarStatus status); diff --git a/calendar/cal-client/cal-listener.c b/calendar/cal-client/cal-listener.c index c7beef8c97..ac04be7c07 100644 --- a/calendar/cal-client/cal-listener.c +++ b/calendar/cal-client/cal-listener.c @@ -19,6 +19,9 @@ */ #include <config.h> + +#include <bonobo/bonobo-main.h> +#include "cal-marshal.h" #include "cal-listener.h" @@ -26,10 +29,7 @@ /* Private part of the CalListener structure */ struct CalListenerPrivate { /* Notification functions and their closure data */ - CalListenerCalOpenedFn cal_opened_fn; CalListenerCalSetModeFn cal_set_mode_fn; - CalListenerObjUpdatedFn obj_updated_fn; - CalListenerObjRemovedFn obj_removed_fn; CalListenerErrorOccurredFn error_occurred_fn; CalListenerCategoriesChangedFn categories_changed_fn; gpointer fn_data; @@ -38,124 +38,178 @@ struct CalListenerPrivate { gboolean notify : 1; }; - +/* Signal IDs */ +enum { + READ_ONLY, + CAL_ADDRESS, + ALARM_ADDRESS, + LDAP_ATTRIBUTE, + STATIC_CAPABILITIES, + OPEN, + REMOVE, + CREATE_OBJECT, + MODIFY_OBJECT, + REMOVE_OBJECT, + DISCARD_ALARM, + RECEIVE_OBJECTS, + SEND_OBJECTS, + DEFAULT_OBJECT, + OBJECT, + OBJECT_LIST, + GET_TIMEZONE, + ADD_TIMEZONE, + SET_DEFAULT_TIMEZONE, + GET_CHANGES, + GET_FREE_BUSY, + QUERY, + LAST_SIGNAL +}; -static void cal_listener_class_init (CalListenerClass *klass); -static void cal_listener_init (CalListener *listener, CalListenerClass *klass); -static void cal_listener_finalize (GObject *object); - -static void impl_notifyCalOpened (PortableServer_Servant servant, - GNOME_Evolution_Calendar_Listener_OpenStatus status, - GNOME_Evolution_Calendar_Cal cal, - CORBA_Environment *ev); -static void impl_notifyCalSetMode (PortableServer_Servant servant, - GNOME_Evolution_Calendar_Listener_SetModeStatus status, - GNOME_Evolution_Calendar_CalMode mode, - CORBA_Environment *ev); -static void impl_notifyObjUpdated (PortableServer_Servant servant, - const CORBA_char *uid, - CORBA_Environment *ev); -static void impl_notifyObjRemoved (PortableServer_Servant servant, - const CORBA_char *uid, - CORBA_Environment *ev); -static void impl_notifyErrorOccurred (PortableServer_Servant servant, - const CORBA_char *message, - CORBA_Environment *ev); -static void impl_notifyCategoriesChanged (PortableServer_Servant servant, - const GNOME_Evolution_Calendar_StringSeq *categories, - CORBA_Environment *ev); +static guint signals[LAST_SIGNAL] = { 0 }; static BonoboObjectClass *parent_class; - - -BONOBO_TYPE_FUNC_FULL (CalListener, - GNOME_Evolution_Calendar_Listener, - BONOBO_TYPE_OBJECT, - cal_listener); +static ECalendarStatus +convert_status (const GNOME_Evolution_Calendar_CallStatus status) +{ + switch (status) { + case GNOME_Evolution_Calendar_Success: + return E_CALENDAR_STATUS_OK; + case GNOME_Evolution_Calendar_RepositoryOffline: + return E_CALENDAR_STATUS_REPOSITORY_OFFLINE; + case GNOME_Evolution_Calendar_PermissionDenied: + return E_CALENDAR_STATUS_PERMISSION_DENIED; + case GNOME_Evolution_Calendar_ObjectNotFound: + return E_CALENDAR_STATUS_OBJECT_NOT_FOUND; + case GNOME_Evolution_Calendar_InvalidObject: + return E_CALENDAR_STATUS_INVALID_OBJECT; + case GNOME_Evolution_Calendar_CardIdAlreadyExists: + return E_CALENDAR_STATUS_CARD_ID_ALREADY_EXISTS; + case GNOME_Evolution_Calendar_AuthenticationFailed: + return E_CALENDAR_STATUS_AUTHENTICATION_FAILED; + case GNOME_Evolution_Calendar_AuthenticationRequired: + return E_CALENDAR_STATUS_AUTHENTICATION_REQUIRED; + case GNOME_Evolution_Calendar_OtherError: + default: + return E_CALENDAR_STATUS_OTHER_ERROR; + } +} -/* Class initialization function for the calendar listener */ static void -cal_listener_class_init (CalListenerClass *klass) +impl_notifyReadOnly (PortableServer_Servant servant, + GNOME_Evolution_Calendar_CallStatus status, + const CORBA_boolean read_only, + CORBA_Environment *ev) { - GObjectClass *object_class; - - object_class = (GObjectClass *) klass; + CalListener *listener; + CalListenerPrivate *priv; - parent_class = g_type_class_peek_parent (klass); + listener = CAL_LISTENER (bonobo_object_from_servant (servant)); + priv = listener->priv; - klass->epv.notifyCalOpened = impl_notifyCalOpened; - klass->epv.notifyCalSetMode = impl_notifyCalSetMode; - klass->epv.notifyObjUpdated = impl_notifyObjUpdated; - klass->epv.notifyObjRemoved = impl_notifyObjRemoved; - klass->epv.notifyErrorOccurred = impl_notifyErrorOccurred; - klass->epv.notifyCategoriesChanged = impl_notifyCategoriesChanged; + if (!priv->notify) + return; - object_class->finalize = cal_listener_finalize; + g_signal_emit (G_OBJECT (listener), signals[READ_ONLY], 0, convert_status (status), read_only); } -/* Object initialization function for the calendar listener */ static void -cal_listener_init (CalListener *listener, CalListenerClass *klass) +impl_notifyCalAddress (PortableServer_Servant servant, + GNOME_Evolution_Calendar_CallStatus status, + const CORBA_char *address, + CORBA_Environment *ev) { + CalListener *listener; CalListenerPrivate *priv; - priv = g_new0 (CalListenerPrivate, 1); - listener->priv = priv; + listener = CAL_LISTENER (bonobo_object_from_servant (servant)); + priv = listener->priv; - priv->cal_opened_fn = NULL; - priv->obj_updated_fn = NULL; - priv->obj_removed_fn = NULL; - priv->error_occurred_fn = NULL; - priv->categories_changed_fn = NULL; + if (!priv->notify) + return; - priv->notify = TRUE; + g_signal_emit (G_OBJECT (listener), signals[CAL_ADDRESS], 0, convert_status (status), address); } -/* Finalize handler for the calendar listener */ static void -cal_listener_finalize (GObject *object) +impl_notifyAlarmEmailAddress (PortableServer_Servant servant, + GNOME_Evolution_Calendar_CallStatus status, + const CORBA_char *address, + CORBA_Environment *ev) { CalListener *listener; CalListenerPrivate *priv; - g_return_if_fail (object != NULL); - g_return_if_fail (IS_CAL_LISTENER (object)); - - listener = CAL_LISTENER (object); + listener = CAL_LISTENER (bonobo_object_from_servant (servant)); priv = listener->priv; - priv->cal_opened_fn = NULL; - priv->obj_updated_fn = NULL; - priv->obj_removed_fn = NULL; - priv->error_occurred_fn = NULL; - priv->categories_changed_fn = NULL; - priv->fn_data = NULL; + if (!priv->notify) + return; - priv->notify = FALSE; + g_signal_emit (G_OBJECT (listener), signals[ALARM_ADDRESS], 0, convert_status (status), address); +} - g_free (priv); - listener->priv = NULL; +static void +impl_notifyLDAPAttribute (PortableServer_Servant servant, + GNOME_Evolution_Calendar_CallStatus status, + const CORBA_char *ldap_attribute, + CORBA_Environment *ev) +{ + CalListener *listener; + CalListenerPrivate *priv; - if (G_OBJECT_CLASS (parent_class)->finalize) - (* G_OBJECT_CLASS (parent_class)->finalize) (object); + listener = CAL_LISTENER (bonobo_object_from_servant (servant)); + priv = listener->priv; + + if (!priv->notify) + return; + + g_signal_emit (G_OBJECT (listener), signals[LDAP_ATTRIBUTE], 0, convert_status (status), ldap_attribute); } - +static void +impl_notifyStaticCapabilities (PortableServer_Servant servant, + GNOME_Evolution_Calendar_CallStatus status, + const CORBA_char *capabilities, + CORBA_Environment *ev) +{ + CalListener *listener; + CalListenerPrivate *priv; -/* CORBA servant implementation */ + listener = CAL_LISTENER (bonobo_object_from_servant (servant)); + priv = listener->priv; + + if (!priv->notify) + return; + + g_signal_emit (G_OBJECT (listener), signals[STATIC_CAPABILITIES], 0, convert_status (status)); +} /* ::notifyCalOpened method */ static void impl_notifyCalOpened (PortableServer_Servant servant, - GNOME_Evolution_Calendar_Listener_OpenStatus status, - GNOME_Evolution_Calendar_Cal cal, + GNOME_Evolution_Calendar_CallStatus status, + CORBA_Environment *ev) +{ + CalListener *listener; + CalListenerPrivate *priv; + + listener = CAL_LISTENER (bonobo_object_from_servant (servant)); + priv = listener->priv; + + if (!priv->notify) + return; + + g_signal_emit (G_OBJECT (listener), signals[OPEN], 0, convert_status (status)); +} + +static void +impl_notifyCalRemoved (PortableServer_Servant servant, + GNOME_Evolution_Calendar_CallStatus status, CORBA_Environment *ev) { CalListener *listener; CalListenerPrivate *priv; - CORBA_Environment aev; - GNOME_Evolution_Calendar_Cal cal_copy; listener = CAL_LISTENER (bonobo_object_from_servant (servant)); priv = listener->priv; @@ -163,63 +217,388 @@ impl_notifyCalOpened (PortableServer_Servant servant, if (!priv->notify) return; - CORBA_exception_init (&aev); - cal_copy = CORBA_Object_duplicate (cal, &aev); + g_signal_emit (G_OBJECT (listener), signals[REMOVE], 0, convert_status (status)); +} + +static void +impl_notifyObjectCreated (PortableServer_Servant servant, + GNOME_Evolution_Calendar_CallStatus status, + const CORBA_char *uid, + CORBA_Environment *ev) +{ + CalListener *listener; + CalListenerPrivate *priv; + + listener = CAL_LISTENER (bonobo_object_from_servant (servant)); + priv = listener->priv; + + if (!priv->notify) + return; + + g_signal_emit (G_OBJECT (listener), signals[CREATE_OBJECT], 0, convert_status (status), uid); +} + +static void +impl_notifyObjectModified (PortableServer_Servant servant, + GNOME_Evolution_Calendar_CallStatus status, + CORBA_Environment *ev) +{ + CalListener *listener; + CalListenerPrivate *priv; + + listener = CAL_LISTENER (bonobo_object_from_servant (servant)); + priv = listener->priv; - if (aev._major != CORBA_NO_EXCEPTION) { - g_message ("Listener_notifyCalOpened(): could not duplicate the calendar"); - CORBA_exception_free (&aev); + if (!priv->notify) return; + + g_signal_emit (G_OBJECT (listener), signals[MODIFY_OBJECT], 0, convert_status (status)); +} + +static void +impl_notifyObjectRemoved (PortableServer_Servant servant, + GNOME_Evolution_Calendar_CallStatus status, + CORBA_Environment *ev) +{ + CalListener *listener; + CalListenerPrivate *priv; + + listener = CAL_LISTENER (bonobo_object_from_servant (servant)); + priv = listener->priv; + + if (!priv->notify) + return; + + g_signal_emit (G_OBJECT (listener), signals[REMOVE_OBJECT], 0, convert_status (status)); +} + +static void +impl_notifyAlarmDiscarded (PortableServer_Servant servant, + GNOME_Evolution_Calendar_CallStatus status, + CORBA_Environment *ev) +{ + CalListener *listener; + CalListenerPrivate *priv; + + listener = CAL_LISTENER (bonobo_object_from_servant (servant)); + priv = listener->priv; + + if (!priv->notify) + return; + + g_signal_emit (G_OBJECT (listener), signals[DISCARD_ALARM], 0, convert_status (status)); +} + +static void +impl_notifyObjectsReceived (PortableServer_Servant servant, + GNOME_Evolution_Calendar_CallStatus status, + CORBA_Environment *ev) +{ + CalListener *listener; + CalListenerPrivate *priv; + + listener = CAL_LISTENER (bonobo_object_from_servant (servant)); + priv = listener->priv; + + if (!priv->notify) + return; + + g_signal_emit (G_OBJECT (listener), signals[RECEIVE_OBJECTS], 0, convert_status (status)); +} + +static void +impl_notifyObjectsSent (PortableServer_Servant servant, + GNOME_Evolution_Calendar_CallStatus status, + CORBA_Environment *ev) +{ + CalListener *listener; + CalListenerPrivate *priv; + + listener = CAL_LISTENER (bonobo_object_from_servant (servant)); + priv = listener->priv; + + if (!priv->notify) + return; + + g_signal_emit (G_OBJECT (listener), signals[SEND_OBJECTS], 0, convert_status (status)); +} + +static void +impl_notifyDefaultObjectRequested (PortableServer_Servant servant, + const GNOME_Evolution_Calendar_CallStatus status, + const CORBA_char *object, + CORBA_Environment *ev) +{ + CalListener *listener; + CalListenerPrivate *priv; + + listener = CAL_LISTENER (bonobo_object_from_servant (servant)); + priv = listener->priv; + + if (!priv->notify) + return; + + g_signal_emit (G_OBJECT (listener), signals[DEFAULT_OBJECT], 0, convert_status (status), object); +} + +static void +impl_notifyObjectRequested (PortableServer_Servant servant, + const GNOME_Evolution_Calendar_CallStatus status, + const CORBA_char *object, + CORBA_Environment *ev) +{ + CalListener *listener; + CalListenerPrivate *priv; + + listener = CAL_LISTENER (bonobo_object_from_servant (servant)); + priv = listener->priv; + + if (!priv->notify) + return; + + g_signal_emit (G_OBJECT (listener), signals[OBJECT], 0, convert_status (status), object); +} + +static GList * +build_object_list (const GNOME_Evolution_Calendar_stringlist *seq) +{ + GList *list; + int i; + + list = NULL; + for (i = 0; i < seq->_length; i++) { + icalcomponent *comp; + + comp = icalcomponent_new_from_string (seq->_buffer[i]); + if (!comp) + continue; + + list = g_list_prepend (list, comp); } - CORBA_exception_free (&aev); - g_assert (priv->cal_opened_fn != NULL); - (* priv->cal_opened_fn) (listener, status, cal, priv->fn_data); + return list; +} + +static void +impl_notifyObjectListRequested (PortableServer_Servant servant, + const GNOME_Evolution_Calendar_CallStatus status, + const GNOME_Evolution_Calendar_stringlist *objects, + CORBA_Environment *ev) +{ + CalListener *listener; + CalListenerPrivate *priv; + GList *object_list, *l; + + listener = CAL_LISTENER (bonobo_object_from_servant (servant)); + priv = listener->priv; + + if (!priv->notify) + return; + + object_list = build_object_list (objects); + + g_signal_emit (G_OBJECT (listener), signals[OBJECT_LIST], 0, convert_status (status), object_list); + + for (l = object_list; l; l = l->next) + icalcomponent_free (l->data); + g_list_free (object_list); } -/* ::notifyCalSetMode method */ static void -impl_notifyCalSetMode (PortableServer_Servant servant, - GNOME_Evolution_Calendar_Listener_SetModeStatus status, - GNOME_Evolution_Calendar_CalMode mode, - CORBA_Environment *ev) +impl_notifyTimezoneRequested (PortableServer_Servant servant, + const GNOME_Evolution_Calendar_CallStatus status, + const CORBA_char *object, + CORBA_Environment *ev) { CalListener *listener; CalListenerPrivate *priv; + + listener = CAL_LISTENER (bonobo_object_from_servant (servant)); + priv = listener->priv; + + if (!priv->notify) + return; + + g_signal_emit (G_OBJECT (listener), signals[GET_TIMEZONE], 0, convert_status (status), object); +} +static void +impl_notifyTimezoneAdded (PortableServer_Servant servant, + const GNOME_Evolution_Calendar_CallStatus status, + const CORBA_char *tzid, + CORBA_Environment *ev) +{ + CalListener *listener; + CalListenerPrivate *priv; + listener = CAL_LISTENER (bonobo_object_from_servant (servant)); priv = listener->priv; if (!priv->notify) return; + + g_signal_emit (G_OBJECT (listener), signals[ADD_TIMEZONE], 0, convert_status (status), tzid); +} - g_assert (priv->cal_set_mode_fn != NULL); - (* priv->cal_set_mode_fn) (listener, status, mode, priv->fn_data); +static void +impl_notifyDefaultTimezoneSet (PortableServer_Servant servant, + const GNOME_Evolution_Calendar_CallStatus status, + CORBA_Environment *ev) +{ + CalListener *listener; + CalListenerPrivate *priv; + + listener = CAL_LISTENER (bonobo_object_from_servant (servant)); + priv = listener->priv; + + if (!priv->notify) + return; + + g_signal_emit (G_OBJECT (listener), signals[SET_DEFAULT_TIMEZONE], 0, convert_status (status)); +} + +static GList * +build_change_list (const GNOME_Evolution_Calendar_CalObjChangeSeq *seq) +{ + GList *list = NULL; + icalcomponent *icalcomp; + int i; + + /* Create the list in reverse order */ + for (i = 0; i < seq->_length; i++) { + GNOME_Evolution_Calendar_CalObjChange *corba_coc; + CalClientChange *ccc; + + corba_coc = &seq->_buffer[i]; + ccc = g_new (CalClientChange, 1); + + icalcomp = icalparser_parse_string (corba_coc->calobj); + if (!icalcomp) + continue; + + 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; + + list = g_list_prepend (list, ccc); + } + + list = g_list_reverse (list); + + return list; } -/* ::notifyObjUpdated method */ static void -impl_notifyObjUpdated (PortableServer_Servant servant, - const CORBA_char *uid, - CORBA_Environment *ev) +impl_notifyChanges (PortableServer_Servant servant, + const GNOME_Evolution_Calendar_CallStatus status, + const GNOME_Evolution_Calendar_CalObjChangeSeq *seq, + CORBA_Environment *ev) { CalListener *listener; CalListenerPrivate *priv; + GList *changes, *l; + + listener = CAL_LISTENER (bonobo_object_from_servant (servant)); + priv = listener->priv; + if (!priv->notify) + return; + + changes = build_change_list (seq); + + g_signal_emit (G_OBJECT (listener), signals[GET_CHANGES], 0, convert_status (status), changes); + + for (l = changes; l; l = l->next) + g_free (l->data); + g_list_free (changes); +} + +static GList * +build_free_busy_list (const GNOME_Evolution_Calendar_CalObjSeq *seq) +{ + GList *list = NULL; + int i; + + /* Create the list in reverse order */ + for (i = 0; i < seq->_length; i++) { + CalComponent *comp; + icalcomponent *icalcomp; + icalcomponent_kind kind; + + icalcomp = icalcomponent_new_from_string (seq->_buffer[i]); + if (!icalcomp) + continue; + + kind = icalcomponent_isa (icalcomp); + if (kind == ICAL_VFREEBUSY_COMPONENT) { + comp = cal_component_new (); + if (!cal_component_set_icalcomponent (comp, icalcomp)) { + icalcomponent_free (icalcomp); + g_object_unref (G_OBJECT (comp)); + continue; + } + + list = g_list_append (list, comp); + } else { + icalcomponent_free (icalcomp); + } + } + + return list; +} + +static void +impl_notifyFreeBusy (PortableServer_Servant servant, + const GNOME_Evolution_Calendar_CallStatus status, + const GNOME_Evolution_Calendar_CalObjSeq *seq, + CORBA_Environment *ev) +{ + CalListener *listener; + CalListenerPrivate *priv; + GList *freebusy, *l; + listener = CAL_LISTENER (bonobo_object_from_servant (servant)); priv = listener->priv; if (!priv->notify) return; + + freebusy = build_free_busy_list (seq); + + g_signal_emit (G_OBJECT (listener), signals[GET_FREE_BUSY], 0, convert_status (status), freebusy); + + for (l = freebusy; l; l = l->next) + g_free (l->data); + g_list_free (freebusy); +} - g_assert (priv->obj_updated_fn != NULL); - (* priv->obj_updated_fn) (listener, uid, priv->fn_data); +static void +impl_notifyQuery (PortableServer_Servant servant, + const GNOME_Evolution_Calendar_CallStatus status, + const GNOME_Evolution_Calendar_Query query, + CORBA_Environment *ev) +{ + CalListener *listener; + CalListenerPrivate *priv; + + listener = CAL_LISTENER (bonobo_object_from_servant (servant)); + priv = listener->priv; + + if (!priv->notify) + return; + + g_signal_emit (G_OBJECT (listener), signals[QUERY], 0, convert_status (status), query); } -/* ::notifyObjRemoved method */ +/* ::notifyCalSetMode method */ static void -impl_notifyObjRemoved (PortableServer_Servant servant, - const CORBA_char *uid, +impl_notifyCalSetMode (PortableServer_Servant servant, + GNOME_Evolution_Calendar_Listener_SetModeStatus status, + GNOME_Evolution_Calendar_CalMode mode, CORBA_Environment *ev) { CalListener *listener; @@ -231,10 +610,13 @@ impl_notifyObjRemoved (PortableServer_Servant servant, if (!priv->notify) return; - g_assert (priv->obj_removed_fn != NULL); - (* priv->obj_removed_fn) (listener, uid, priv->fn_data); + g_message ("notify_set_mode"); + + g_assert (priv->cal_set_mode_fn != NULL); + (* priv->cal_set_mode_fn) (listener, status, mode, priv->fn_data); } + /* ::notifyErrorOccurred method */ static void impl_notifyErrorOccurred (PortableServer_Servant servant, @@ -250,6 +632,8 @@ impl_notifyErrorOccurred (PortableServer_Servant servant, if (!priv->notify) return; + g_message ("notify_error"); + g_assert (priv->error_occurred_fn != NULL); (* priv->error_occurred_fn) (listener, message, priv->fn_data); } @@ -269,21 +653,283 @@ impl_notifyCategoriesChanged (PortableServer_Servant servant, if (!priv->notify) return; + g_message ("notify_categories"); + g_assert (priv->categories_changed_fn != NULL); (* priv->categories_changed_fn) (listener, categories, priv->fn_data); } +/* Object initialization function for the calendar listener */ +static void +cal_listener_init (CalListener *listener, CalListenerClass *klass) +{ + CalListenerPrivate *priv; + + priv = g_new0 (CalListenerPrivate, 1); + listener->priv = priv; + + priv->error_occurred_fn = NULL; + priv->categories_changed_fn = NULL; + + priv->notify = TRUE; +} + +/* Finalize handler for the calendar listener */ +static void +cal_listener_finalize (GObject *object) +{ + CalListener *listener; + CalListenerPrivate *priv; + + g_return_if_fail (object != NULL); + g_return_if_fail (IS_CAL_LISTENER (object)); + + listener = CAL_LISTENER (object); + priv = listener->priv; + + priv->error_occurred_fn = NULL; + priv->categories_changed_fn = NULL; + priv->fn_data = NULL; + + priv->notify = FALSE; + + g_free (priv); + listener->priv = NULL; + + if (G_OBJECT_CLASS (parent_class)->finalize) + (* G_OBJECT_CLASS (parent_class)->finalize) (object); +} + +/* Class initialization function for the calendar listener */ +static void +cal_listener_class_init (CalListenerClass *klass) +{ + GObjectClass *object_class; + + object_class = (GObjectClass *) klass; + + parent_class = g_type_class_peek_parent (klass); + + klass->epv.notifyReadOnly = impl_notifyReadOnly; + klass->epv.notifyCalAddress = impl_notifyCalAddress; + klass->epv.notifyAlarmEmailAddress = impl_notifyAlarmEmailAddress; + klass->epv.notifyLDAPAttribute = impl_notifyLDAPAttribute; + klass->epv.notifyStaticCapabilities = impl_notifyStaticCapabilities; + klass->epv.notifyCalOpened = impl_notifyCalOpened; + klass->epv.notifyCalRemoved = impl_notifyCalRemoved; + klass->epv.notifyObjectCreated = impl_notifyObjectCreated; + klass->epv.notifyObjectModified = impl_notifyObjectModified; + klass->epv.notifyObjectRemoved = impl_notifyObjectRemoved; + klass->epv.notifyAlarmDiscarded = impl_notifyAlarmDiscarded; + klass->epv.notifyObjectsReceived = impl_notifyObjectsReceived; + klass->epv.notifyObjectsSent = impl_notifyObjectsSent; + klass->epv.notifyDefaultObjectRequested = impl_notifyDefaultObjectRequested; + klass->epv.notifyObjectRequested = impl_notifyObjectRequested; + klass->epv.notifyObjectListRequested = impl_notifyObjectListRequested; + klass->epv.notifyTimezoneRequested = impl_notifyTimezoneRequested; + klass->epv.notifyTimezoneAdded = impl_notifyTimezoneAdded; + klass->epv.notifyDefaultTimezoneSet = impl_notifyDefaultTimezoneSet; + klass->epv.notifyChanges = impl_notifyChanges; + klass->epv.notifyFreeBusy = impl_notifyFreeBusy; + klass->epv.notifyQuery = impl_notifyQuery; + klass->epv.notifyCalSetMode = impl_notifyCalSetMode; + klass->epv.notifyErrorOccurred = impl_notifyErrorOccurred; + klass->epv.notifyCategoriesChanged = impl_notifyCategoriesChanged; + + object_class->finalize = cal_listener_finalize; + + signals[READ_ONLY] = + g_signal_new ("read_only", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (CalListenerClass, read_only), + NULL, NULL, + cal_marshal_VOID__INT_BOOLEAN, + G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_BOOLEAN); + signals[CAL_ADDRESS] = + g_signal_new ("cal_address", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (CalListenerClass, cal_address), + NULL, NULL, + cal_marshal_VOID__INT_STRING, + G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_STRING); + signals[ALARM_ADDRESS] = + g_signal_new ("alarm_address", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (CalListenerClass, alarm_address), + NULL, NULL, + cal_marshal_VOID__INT_STRING, + G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_STRING); + signals[LDAP_ATTRIBUTE] = + g_signal_new ("ldap_attribute", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (CalListenerClass, ldap_attribute), + NULL, NULL, + cal_marshal_VOID__INT_STRING, + G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_STRING); + signals[STATIC_CAPABILITIES] = + g_signal_new ("static_capabilities", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (CalListenerClass, static_capabilities), + NULL, NULL, + cal_marshal_VOID__INT_STRING, + G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_STRING); + signals[OPEN] = + g_signal_new ("open", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (CalListenerClass, open), + NULL, NULL, + cal_marshal_VOID__INT, + G_TYPE_NONE, 1, G_TYPE_INT); + signals[REMOVE] = + g_signal_new ("remove", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (CalListenerClass, remove), + NULL, NULL, + cal_marshal_VOID__INT, + G_TYPE_NONE, 1, G_TYPE_INT); + signals[CREATE_OBJECT] = + g_signal_new ("create_object", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (CalListenerClass, create_object), + NULL, NULL, + cal_marshal_VOID__INT_STRING, + G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_STRING); + signals[MODIFY_OBJECT] = + g_signal_new ("modify_object", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (CalListenerClass, modify_object), + NULL, NULL, + cal_marshal_VOID__INT, + G_TYPE_NONE, 1, G_TYPE_INT); + signals[REMOVE_OBJECT] = + g_signal_new ("remove_object", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (CalListenerClass, remove_object), + NULL, NULL, + cal_marshal_VOID__INT, + G_TYPE_NONE, 1, G_TYPE_INT); + signals[DISCARD_ALARM] = + g_signal_new ("discard_alarm", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (CalListenerClass, discard_alarm), + NULL, NULL, + cal_marshal_VOID__INT, + G_TYPE_NONE, 1, G_TYPE_INT); + signals[RECEIVE_OBJECTS] = + g_signal_new ("receive_objects", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (CalListenerClass, receive_objects), + NULL, NULL, + cal_marshal_VOID__INT, + G_TYPE_NONE, 1, G_TYPE_INT); + signals[SEND_OBJECTS] = + g_signal_new ("send_objects", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (CalListenerClass, send_objects), + NULL, NULL, + cal_marshal_VOID__INT, + G_TYPE_NONE, 1, G_TYPE_INT); + signals[DEFAULT_OBJECT] = + g_signal_new ("default_object", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (CalListenerClass, default_object), + NULL, NULL, + cal_marshal_VOID__INT_STRING, + G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_STRING); + signals[OBJECT] = + g_signal_new ("object", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (CalListenerClass, object), + NULL, NULL, + cal_marshal_VOID__INT_STRING, + G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_STRING); + signals[OBJECT_LIST] = + g_signal_new ("object_list", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (CalListenerClass, object_list), + NULL, NULL, + cal_marshal_VOID__INT_POINTER, + G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_POINTER); + signals[GET_TIMEZONE] = + g_signal_new ("get_timezone", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (CalListenerClass, get_timezone), + NULL, NULL, + cal_marshal_VOID__INT_STRING, + G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_STRING); + signals[ADD_TIMEZONE] = + g_signal_new ("add_timezone", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (CalListenerClass, add_timezone), + NULL, NULL, + cal_marshal_VOID__INT_STRING, + G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_STRING); + signals[SET_DEFAULT_TIMEZONE] = + g_signal_new ("set_default_timezone", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (CalListenerClass, set_default_timezone), + NULL, NULL, + cal_marshal_VOID__INT, + G_TYPE_NONE, 1, G_TYPE_INT); + signals[GET_CHANGES] = + g_signal_new ("get_changes", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (CalListenerClass, get_changes), + NULL, NULL, + cal_marshal_VOID__INT_POINTER, + G_TYPE_NONE, 1, G_TYPE_INT, G_TYPE_POINTER); + signals[GET_FREE_BUSY] = + g_signal_new ("get_free_busy", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (CalListenerClass, get_free_busy), + NULL, NULL, + cal_marshal_VOID__INT_POINTER, + G_TYPE_NONE, 1, G_TYPE_INT, G_TYPE_POINTER); + signals[QUERY] = + g_signal_new ("query", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (CalListenerClass, query), + NULL, NULL, + cal_marshal_VOID__INT_POINTER, + G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_POINTER); +} + +BONOBO_TYPE_FUNC_FULL (CalListener, + GNOME_Evolution_Calendar_Listener, + BONOBO_TYPE_OBJECT, + cal_listener); + /** * cal_listener_construct: * @listener: A calendar listener. * @cal_opened_fn: Function that will be called to notify that a calendar was * opened. - * @obj_updated_fn: Function that will be called to notify that an object in the - * calendar was updated. - * @obj_removed_fn: Function that will be called to notify that an object in the - * calendar was removed. + * @cal_removed_fn: Function that will be called to notify that a calendar was + * removed * @error_occurred_fn: Function that will be called to notify errors. * @categories_changed_fn: Function that will be called to notify that the list * of categories that are present in the calendar's objects has changed. @@ -297,10 +943,7 @@ impl_notifyCategoriesChanged (PortableServer_Servant servant, **/ CalListener * cal_listener_construct (CalListener *listener, - CalListenerCalOpenedFn cal_opened_fn, CalListenerCalSetModeFn cal_set_mode_fn, - CalListenerObjUpdatedFn obj_updated_fn, - CalListenerObjRemovedFn obj_removed_fn, CalListenerErrorOccurredFn error_occurred_fn, CalListenerCategoriesChangedFn categories_changed_fn, gpointer fn_data) @@ -309,19 +952,13 @@ cal_listener_construct (CalListener *listener, g_return_val_if_fail (listener != NULL, NULL); g_return_val_if_fail (IS_CAL_LISTENER (listener), NULL); - g_return_val_if_fail (cal_opened_fn != NULL, NULL); g_return_val_if_fail (cal_set_mode_fn != NULL, NULL); - g_return_val_if_fail (obj_updated_fn != NULL, NULL); - g_return_val_if_fail (obj_removed_fn != NULL, NULL); g_return_val_if_fail (error_occurred_fn != NULL, NULL); g_return_val_if_fail (categories_changed_fn != NULL, NULL); priv = listener->priv; - priv->cal_opened_fn = cal_opened_fn; priv->cal_set_mode_fn = cal_set_mode_fn; - priv->obj_updated_fn = obj_updated_fn; - priv->obj_removed_fn = obj_removed_fn; priv->error_occurred_fn = error_occurred_fn; priv->categories_changed_fn = categories_changed_fn; priv->fn_data = fn_data; @@ -333,10 +970,6 @@ cal_listener_construct (CalListener *listener, * cal_listener_new: * @cal_opened_fn: Function that will be called to notify that a calendar was * opened. - * @obj_updated_fn: Function that will be called to notify that an object in the - * calendar was updated. - * @obj_removed_fn: Function that will be called to notify that an object in the - * calendar was removed. * @error_occurred_fn: Function that will be called to notify errors. * @categories_changed_fn: Function that will be called to notify that the list * of categories that are present in the calendar's objects has changed. @@ -348,28 +981,22 @@ cal_listener_construct (CalListener *listener, * Return value: A newly-created #CalListener object. **/ CalListener * -cal_listener_new (CalListenerCalOpenedFn cal_opened_fn, - CalListenerCalSetModeFn cal_set_mode_fn, - CalListenerObjUpdatedFn obj_updated_fn, - CalListenerObjRemovedFn obj_removed_fn, +cal_listener_new (CalListenerCalSetModeFn cal_set_mode_fn, CalListenerErrorOccurredFn error_occurred_fn, CalListenerCategoriesChangedFn categories_changed_fn, gpointer fn_data) { CalListener *listener; - g_return_val_if_fail (cal_opened_fn != NULL, NULL); - g_return_val_if_fail (obj_updated_fn != NULL, NULL); - g_return_val_if_fail (obj_removed_fn != NULL, NULL); g_return_val_if_fail (error_occurred_fn != NULL, NULL); g_return_val_if_fail (categories_changed_fn != NULL, NULL); - listener = g_object_new (CAL_LISTENER_TYPE, NULL); + listener = g_object_new (CAL_LISTENER_TYPE, + "poa", bonobo_poa_get_threaded (ORBIT_THREAD_HINT_PER_REQUEST, NULL), + NULL); + return cal_listener_construct (listener, - cal_opened_fn, cal_set_mode_fn, - obj_updated_fn, - obj_removed_fn, error_occurred_fn, categories_changed_fn, fn_data); diff --git a/calendar/cal-client/cal-listener.h b/calendar/cal-client/cal-listener.h index d0f9a718a4..1230104999 100644 --- a/calendar/cal-client/cal-listener.h +++ b/calendar/cal-client/cal-listener.h @@ -23,6 +23,7 @@ #include <bonobo/bonobo-object.h> #include "evolution-calendar.h" +#include "cal-client-types.h" G_BEGIN_DECLS @@ -48,26 +49,46 @@ typedef struct { BonoboObjectClass parent_class; POA_GNOME_Evolution_Calendar_Listener__epv epv; + + /* Signals */ + void (*read_only) (CalListener *listener, ECalendarStatus status, gboolean read_only); + void (*cal_address) (CalListener *listener, ECalendarStatus status, const char *address); + void (*alarm_address) (CalListener *listener, ECalendarStatus status, const char *address); + void (*ldap_attribute) (CalListener *listener, ECalendarStatus status, const char *ldap_attribute); + void (*static_capabilities) (CalListener *listener, ECalendarStatus status, const char *capabilities); + + void (*open) (CalListener *listener, ECalendarStatus status); + void (*remove) (CalListener *listener, ECalendarStatus status); + + void (*create_object) (CalListener *listener, ECalendarStatus status, const char *id); + void (*modify_object) (CalListener *listener, ECalendarStatus status); + void (*remove_object) (CalListener *listener, ECalendarStatus status); + + void (*discard_alarm) (CalListener *listener, ECalendarStatus status); + + void (*receive_objects) (CalListener *listener, ECalendarStatus status); + void (*send_objects) (CalListener *listener, ECalendarStatus status); + + void (*default_object) (CalListener *listener, ECalendarStatus status, const char *object); + void (*object) (CalListener *listener, ECalendarStatus status, const char *object); + void (*object_list) (CalListener *listener, ECalendarStatus status, GList **objects); + + void (*get_timezone) (CalListener *listener, ECalendarStatus status, const char *object); + void (*add_timezone) (CalListener *listener, ECalendarStatus status, const char *tzid); + void (*set_default_timezone) (CalListener *listener, ECalendarStatus status, const char *tzid); + + void (*get_changes) (CalListener *listener, ECalendarStatus status, GList *changes); + void (*get_free_busy) (CalListener *listener, ECalendarStatus status, GList *freebusy); + + void (*query) (CalListener *listener, ECalendarStatus status, GNOME_Evolution_Calendar_Query query); } CalListenerClass; /* Notification functions */ -typedef void (* CalListenerCalOpenedFn) (CalListener *listener, - GNOME_Evolution_Calendar_Listener_OpenStatus status, - GNOME_Evolution_Calendar_Cal cal, - gpointer data); - typedef void (* CalListenerCalSetModeFn) (CalListener *listener, GNOME_Evolution_Calendar_Listener_SetModeStatus status, GNOME_Evolution_Calendar_CalMode mode, gpointer data); -typedef void (* CalListenerObjUpdatedFn) (CalListener *listener, - const CORBA_char *uid, - gpointer data); -typedef void (* CalListenerObjRemovedFn) (CalListener *listener, - const CORBA_char *uid, - gpointer data); - typedef void (* CalListenerErrorOccurredFn) (CalListener *listener, const char *message, gpointer data); @@ -80,18 +101,12 @@ typedef void (* CalListenerCategoriesChangedFn) (CalListener *listener, GType cal_listener_get_type (void); CalListener *cal_listener_construct (CalListener *listener, - CalListenerCalOpenedFn cal_opened_fn, CalListenerCalSetModeFn cal_set_mode_fn, - CalListenerObjUpdatedFn obj_updated_fn, - CalListenerObjRemovedFn obj_removed_fn, CalListenerErrorOccurredFn error_occurred_fn, CalListenerCategoriesChangedFn categories_changed_fn, gpointer fn_data); -CalListener *cal_listener_new (CalListenerCalOpenedFn cal_opened_fn, - CalListenerCalSetModeFn cal_set_mode_fn, - CalListenerObjUpdatedFn obj_updated_fn, - CalListenerObjRemovedFn obj_removed_fn, +CalListener *cal_listener_new (CalListenerCalSetModeFn cal_set_mode_fn, CalListenerErrorOccurredFn error_occurred_fn, CalListenerCategoriesChangedFn categories_changed_fn, gpointer fn_data); diff --git a/calendar/cal-client/cal-marshal.list b/calendar/cal-client/cal-marshal.list new file mode 100644 index 0000000000..e0ca019669 --- /dev/null +++ b/calendar/cal-client/cal-marshal.list @@ -0,0 +1,6 @@ +NONE:INT +NONE:POINTER +NONE:INT,STRING +NONE:INT,BOOL +NONE:INT,POINTER +NONE:STRING,INT diff --git a/calendar/cal-client/cal-query.c b/calendar/cal-client/cal-query.c index 914af5db28..e77f5ad3e9 100644 --- a/calendar/cal-client/cal-query.c +++ b/calendar/cal-client/cal-query.c @@ -24,7 +24,8 @@ #include <string.h> #include <bonobo/bonobo-exception.h> -#include "cal-util/cal-util-marshal.h" +#include "cal-marshal.h" +#include "cal-client.h" #include "cal-query.h" #include "query-listener.h" @@ -32,143 +33,88 @@ /* Private part of the CalQuery structure */ struct _CalQueryPrivate { - /* Our query listener implementation */ - QueryListener *ql; - /* Handle to the query in the server */ - GNOME_Evolution_Calendar_Query corba_query; + GNOME_Evolution_Calendar_Query query; + + /* Our query listener implementation */ + QueryListener *listener; /* The CalClient associated with this query */ CalClient *client; }; - - -static void cal_query_class_init (CalQueryClass *klass); -static void cal_query_init (CalQuery *query, CalQueryClass *klass); -static void cal_query_finalize (GObject *object); +/* Property IDs */ +enum props { + PROP_0, + PROP_QUERY, + PROP_LISTENER, + PROP_CLIENT +}; /* Signal IDs */ enum { - OBJ_UPDATED, - OBJ_REMOVED, + OBJECTS_ADDED, + OBJECTS_MODIFIED, + OBJECTS_REMOVED, + QUERY_PROGRESS, QUERY_DONE, - EVAL_ERROR, LAST_SIGNAL }; -static guint query_signals[LAST_SIGNAL]; +static guint signals[LAST_SIGNAL]; static GObjectClass *parent_class; -/** - * cal_query_get_type: - * - * Registers the #CalQuery class if necessary, and returns the type ID assigned - * to it. - * - * Return value: The type ID of the #CalQuery class. - **/ -GType -cal_query_get_type (void) +static void +objects_added_cb (QueryListener *listener, GList *objects, gpointer data) { - static GType cal_query_type = 0; + CalQuery *query; - if (!cal_query_type) { - static GTypeInfo info = { - sizeof (CalQueryClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) cal_query_class_init, - NULL, NULL, - sizeof (CalQuery), - 0, - (GInstanceInitFunc) cal_query_init - }; - cal_query_type = g_type_register_static (G_TYPE_OBJECT, "CalQuery", &info, 0); - } + query = CAL_QUERY (data); - return cal_query_type; + g_signal_emit (G_OBJECT (query), signals[OBJECTS_ADDED], 0, objects); } -GType -cal_query_done_status_enum_get_type (void) +static void +objects_modified_cb (QueryListener *listener, GList *objects, gpointer data) { - static GType cal_query_done_status_enum_type = 0; + CalQuery *query; - if (!cal_query_done_status_enum_type) { - static GEnumValue values [] = { - { CAL_QUERY_DONE_SUCCESS, "CalQueryDoneSuccess", "success" }, - { CAL_QUERY_DONE_PARSE_ERROR, "CalQueryDoneParseError", "parse-error" }, - { -1, NULL, NULL } - }; + query = CAL_QUERY (data); - cal_query_done_status_enum_type = - g_enum_register_static ("CalQueryDoneStatusEnum", values); - } + g_signal_emit (G_OBJECT (query), signals[OBJECTS_MODIFIED], 0, objects); +} + +static void +objects_removed_cb (QueryListener *listener, GList *uids, gpointer data) +{ + CalQuery *query; + + query = CAL_QUERY (data); - return cal_query_done_status_enum_type; + g_signal_emit (G_OBJECT (query), signals[OBJECTS_REMOVED], 0, uids); } -/* Class initialization function for the calendar query */ static void -cal_query_class_init (CalQueryClass *klass) +query_progress_cb (QueryListener *listener, const char *message, int percent, gpointer data) { - GObjectClass *object_class; + CalQuery *query; - object_class = (GObjectClass *) klass; + query = CAL_QUERY (data); - parent_class = g_type_class_peek_parent (klass); + g_signal_emit (G_OBJECT (query), signals[QUERY_PROGRESS], 0, message, percent); +} - query_signals[OBJ_UPDATED] = - g_signal_new ("obj_updated", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (CalQueryClass, obj_updated), - NULL, NULL, - cal_util_marshal_VOID__STRING_BOOLEAN_INT_INT, - G_TYPE_NONE, 4, - G_TYPE_STRING, - G_TYPE_BOOLEAN, - G_TYPE_INT, - G_TYPE_INT); - query_signals[OBJ_REMOVED] = - g_signal_new ("obj_removed", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (CalQueryClass, obj_removed), - NULL, NULL, - g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, 1, - G_TYPE_STRING); - query_signals[QUERY_DONE] = - g_signal_new ("query_done", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (CalQueryClass, query_done), - NULL, NULL, - cal_util_marshal_VOID__ENUM_STRING, - G_TYPE_NONE, 2, - CAL_QUERY_DONE_STATUS_ENUM_TYPE, - G_TYPE_STRING); - query_signals[EVAL_ERROR] = - g_signal_new ("eval_error", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (CalQueryClass, eval_error), - NULL, NULL, - g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, 1, - G_TYPE_STRING); +static void +query_done_cb (QueryListener *listener, ECalendarStatus status, gpointer data) +{ + CalQuery *query; - klass->obj_updated = NULL; - klass->obj_removed = NULL; - klass->query_done = NULL; - klass->eval_error = NULL; + query = CAL_QUERY (data); - object_class->finalize = cal_query_finalize; + g_signal_emit (G_OBJECT (query), signals[QUERY_DONE], 0, status); } /* Object initialization function for the calendar query */ @@ -180,191 +126,193 @@ cal_query_init (CalQuery *query, CalQueryClass *klass) priv = g_new0 (CalQueryPrivate, 1); query->priv = priv; - priv->ql = NULL; - priv->corba_query = CORBA_OBJECT_NIL; + priv->listener = NULL; + priv->query = CORBA_OBJECT_NIL; } -/* Finalize handler for the calendar query */ static void -cal_query_finalize (GObject *object) +cal_query_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { CalQuery *query; CalQueryPrivate *priv; - - g_return_if_fail (object != NULL); - g_return_if_fail (IS_CAL_QUERY (object)); - + query = CAL_QUERY (object); priv = query->priv; - - /* The server keeps a copy of the query listener, so we must unref it */ - query_listener_stop_notification (priv->ql); - bonobo_object_unref (BONOBO_OBJECT (priv->ql)); - priv->ql = NULL; - - if (priv->corba_query != CORBA_OBJECT_NIL) { - CORBA_Environment ev; - - CORBA_exception_init (&ev); - bonobo_object_release_unref (priv->corba_query, &ev); - - if (BONOBO_EX (&ev)) - g_message ("cal_query_destroy(): Could not release/unref the query"); - - CORBA_exception_free (&ev); - priv->corba_query = CORBA_OBJECT_NIL; + + switch (property_id) { + case PROP_QUERY: + priv->query = bonobo_object_dup_ref (g_value_get_pointer (value), NULL); + break; + case PROP_LISTENER: + priv->listener = bonobo_object_ref (g_value_get_pointer (value)); + + g_signal_connect (G_OBJECT (priv->listener), "objects_added", + G_CALLBACK (objects_added_cb), query); + g_signal_connect (G_OBJECT (priv->listener), "objects_modified", + G_CALLBACK (objects_modified_cb), query); + g_signal_connect (G_OBJECT (priv->listener), "objects_removed", + G_CALLBACK (objects_removed_cb), query); + g_signal_connect (G_OBJECT (priv->listener), "query_progress", + G_CALLBACK (query_progress_cb), query); + g_signal_connect (G_OBJECT (priv->listener), "query_done", + G_CALLBACK (query_done_cb), query); + break; + case PROP_CLIENT: + priv->client = CAL_CLIENT (g_value_dup_object (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; } - - g_free (priv); - query->priv = NULL; - - if (G_OBJECT_CLASS (parent_class)->finalize) - (* G_OBJECT_CLASS (parent_class)->finalize) (object); } - - -/* Callback used when an object is updated in the query */ static void -obj_updated_cb (QueryListener *ql, - const GNOME_Evolution_Calendar_CalObjUIDSeq *uids, - CORBA_boolean query_in_progress, - CORBA_long n_scanned, - CORBA_long total, - gpointer data) +cal_query_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { CalQuery *query; - int n; - - query = CAL_QUERY (data); + CalQueryPrivate *priv; + + query = CAL_QUERY (object); + priv = query->priv; - for (n = 0; n < uids->_length; n++) { - g_signal_emit (G_OBJECT (query), query_signals[OBJ_UPDATED], 0, - uids->_buffer[n], query_in_progress, - (int) n_scanned, (int) total); + switch (property_id) { + case PROP_QUERY: + g_value_set_pointer (value, priv->query); + break; + case PROP_LISTENER: + g_value_set_pointer (value, priv->listener); + break; + case PROP_CLIENT: + g_value_set_object (value, priv->client); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; } } -/* Callback used when an object is removed from the query */ -static void -obj_removed_cb (QueryListener *ql, - const CORBA_char *uid, - gpointer data) -{ - CalQuery *query; - - query = CAL_QUERY (data); - - g_signal_emit (G_OBJECT (query), query_signals[OBJ_REMOVED], - 0, uid); -} -/* Callback used when the query terminates */ +/* Finalize handler for the calendar query */ static void -query_done_cb (QueryListener *ql, - GNOME_Evolution_Calendar_QueryListener_QueryDoneStatus corba_status, - const CORBA_char *error_str, - gpointer data) +cal_query_finalize (GObject *object) { CalQuery *query; - CalQueryDoneStatus status; + CalQueryPrivate *priv; - query = CAL_QUERY (data); + g_return_if_fail (object != NULL); + g_return_if_fail (IS_CAL_QUERY (object)); - switch (corba_status) { - case GNOME_Evolution_Calendar_QueryListener_SUCCESS: - status = CAL_QUERY_DONE_SUCCESS; - break; + query = CAL_QUERY (object); + priv = query->priv; - case GNOME_Evolution_Calendar_QueryListener_PARSE_ERROR: - status = CAL_QUERY_DONE_PARSE_ERROR; - break; + /* The server keeps a copy of the query listener, so we must unref it */ + g_signal_handlers_disconnect_matched (priv->listener, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, query); + bonobo_object_unref (BONOBO_OBJECT (priv->listener)); - default: - g_assert_not_reached (); - return; - } + if (priv->query != CORBA_OBJECT_NIL) + bonobo_object_release_unref (priv->query, NULL); - g_signal_emit (G_OBJECT (query), query_signals[QUERY_DONE], 0, - status, error_str); + g_free (priv); + + if (G_OBJECT_CLASS (parent_class)->finalize) + (* G_OBJECT_CLASS (parent_class)->finalize) (object); } -/* Callback used when an error occurs when evaluating the query */ +/* Class initialization function for the calendar query */ static void -eval_error_cb (QueryListener *ql, - const CORBA_char *error_str, - gpointer data) +cal_query_class_init (CalQueryClass *klass) { - CalQuery *query; + GObjectClass *object_class; + GParamSpec *param; + + object_class = (GObjectClass *) klass; - query = CAL_QUERY (data); + parent_class = g_type_class_peek_parent (klass); + + object_class->set_property = cal_query_set_property; + object_class->get_property = cal_query_get_property; + object_class->finalize = cal_query_finalize; - g_signal_emit (G_OBJECT (query), query_signals[EVAL_ERROR], 0, - error_str); + param = g_param_spec_pointer ("query", NULL, NULL, + G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY); + g_object_class_install_property (object_class, PROP_QUERY, param); + param = g_param_spec_pointer ("listener", NULL, NULL, + G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY); + g_object_class_install_property (object_class, PROP_LISTENER, param); + param = g_param_spec_object ("client", NULL, NULL, CAL_CLIENT_TYPE, + G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY); + g_object_class_install_property (object_class, PROP_CLIENT, param); + + signals[OBJECTS_ADDED] = + g_signal_new ("objects_added", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (CalQueryClass, objects_added), + NULL, NULL, + cal_marshal_VOID__POINTER, + G_TYPE_NONE, 1, G_TYPE_POINTER); + signals[OBJECTS_MODIFIED] = + g_signal_new ("objects_modified", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (CalQueryClass, objects_modified), + NULL, NULL, + cal_marshal_VOID__POINTER, + G_TYPE_NONE, 1, G_TYPE_POINTER); + signals[OBJECTS_REMOVED] = + g_signal_new ("objects_removed", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (CalQueryClass, objects_removed), + NULL, NULL, + cal_marshal_VOID__POINTER, + G_TYPE_NONE, 1, G_TYPE_POINTER); + signals[QUERY_PROGRESS] = + g_signal_new ("query_progress", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (CalQueryClass, query_progress), + NULL, NULL, + cal_marshal_VOID__POINTER, + G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_INT); + signals[QUERY_DONE] = + g_signal_new ("query_done", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (CalQueryClass, query_done), + NULL, NULL, + cal_marshal_VOID__INT, + G_TYPE_NONE, 1, G_TYPE_INT); } /** - * cal_query_construct: - * @query: A calendar query. - * @cal: Handle to an open calendar. - * @sexp: S-expression that defines the query. + * cal_query_get_type: * - * Constructs a query object by issuing the query creation request to the - * calendar server. + * Registers the #CalQuery class if necessary, and returns the type ID assigned + * to it. * - * Return value: The same value as @query on success, or NULL if the request - * failed. + * Return value: The type ID of the #CalQuery class. **/ -CalQuery * -cal_query_construct (CalQuery *query, - GNOME_Evolution_Calendar_Cal cal, - const char *sexp) +GType +cal_query_get_type (void) { - CalQueryPrivate *priv; - GNOME_Evolution_Calendar_QueryListener corba_ql; - CORBA_Environment ev; - - g_return_val_if_fail (query != NULL, NULL); - g_return_val_if_fail (IS_CAL_QUERY (query), NULL); - g_return_val_if_fail (sexp != NULL, NULL); - - priv = query->priv; - - priv->ql = query_listener_new (obj_updated_cb, - obj_removed_cb, - query_done_cb, - eval_error_cb, - query); - if (!priv->ql) { - g_message ("cal_query_construct(): Could not create the query listener"); - return NULL; - } + static GType cal_query_type = 0; - corba_ql = BONOBO_OBJREF (priv->ql); - - CORBA_exception_init (&ev); - priv->corba_query = GNOME_Evolution_Calendar_Cal_getQuery (cal, sexp, corba_ql, &ev); - - if (BONOBO_USER_EX (&ev, ex_GNOME_Evolution_Calendar_Cal_CouldNotCreate)) { - g_message ("cal_query_construct(): The server could not create the query"); - goto error; - } else if (BONOBO_EX (&ev)) { - g_message ("cal_query_construct(): Could not issue the getQuery() request"); - goto error; + if (!cal_query_type) { + static GTypeInfo info = { + sizeof (CalQueryClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) cal_query_class_init, + NULL, NULL, + sizeof (CalQuery), + 0, + (GInstanceInitFunc) cal_query_init + }; + cal_query_type = g_type_register_static (G_TYPE_OBJECT, "CalQuery", &info, 0); } - CORBA_exception_free (&ev); - - return query; - - error: - - CORBA_exception_free (&ev); - - bonobo_object_unref (BONOBO_OBJECT (priv->ql)); - priv->ql = NULL; - priv->corba_query = CORBA_OBJECT_NIL; - return NULL; + return cal_query_type; } /** @@ -379,20 +327,12 @@ cal_query_construct (CalQuery *query, * Return value: A newly-created query object, or NULL if the request failed. **/ CalQuery * -cal_query_new (CalClient *client, - GNOME_Evolution_Calendar_Cal cal, - const char *sexp) +cal_query_new (GNOME_Evolution_Calendar_Query corba_query, QueryListener *listener, CalClient *client) { CalQuery *query; - query = g_object_new (CAL_QUERY_TYPE, NULL); - - if (!cal_query_construct (query, cal, sexp)) { - g_object_unref (G_OBJECT (query)); - return NULL; - } - - query->priv->client = client; + query = g_object_new (CAL_QUERY_TYPE, "query", corba_query, "listener", + listener, "client", client, NULL); return query; } @@ -412,3 +352,23 @@ cal_query_get_client (CalQuery *query) return query->priv->client; } + +void +cal_query_start (CalQuery *query) +{ + CalQueryPrivate *priv; + CORBA_Environment ev; + + g_return_if_fail (query != NULL); + g_return_if_fail (IS_CAL_QUERY (query)); + + priv = query->priv; + + CORBA_exception_init (&ev); + + GNOME_Evolution_Calendar_Query_start (priv->query, &ev); + if (BONOBO_EX (&ev)) + g_warning (G_STRLOC ": Unable to start query"); + + CORBA_exception_free (&ev); +} diff --git a/calendar/cal-client/cal-query.h b/calendar/cal-client/cal-query.h index 77429035fa..05390dd12a 100644 --- a/calendar/cal-client/cal-query.h +++ b/calendar/cal-client/cal-query.h @@ -22,7 +22,8 @@ #define CAL_QUERY_H #include <glib-object.h> - +#include "cal-client-types.h" +#include "query-listener.h" #include "evolution-calendar.h" G_BEGIN_DECLS @@ -37,14 +38,6 @@ typedef struct _CalClient CalClient; #define IS_CAL_QUERY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CAL_QUERY_TYPE)) #define IS_CAL_QUERY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CAL_QUERY_TYPE)) -#define CAL_QUERY_DONE_STATUS_ENUM_TYPE (cal_query_done_status_enum_get_type ()) - -/* Status values when a query terminates */ -typedef enum { - CAL_QUERY_DONE_SUCCESS, - CAL_QUERY_DONE_PARSE_ERROR -} CalQueryDoneStatus; - typedef struct _CalQueryPrivate CalQueryPrivate; typedef struct { @@ -58,30 +51,18 @@ typedef struct { GObjectClass parent_class; /* Notification signals */ - - void (* obj_updated) (CalQuery *query, const char *uid, - gboolean query_in_progress, int n_scanned, int total); - void (* obj_removed) (CalQuery *query, const char *uid); - - void (* query_done) (CalQuery *query, CalQueryDoneStatus status, const char *error_str); - - void (* eval_error) (CalQuery *query, const char *error_str); + void (* objects_added) (CalQuery *query, GList *objects); + void (* objects_modified) (CalQuery *query, GList *objects); + void (* objects_removed) (CalQuery *query, GList *uids); + void (* query_progress) (CalQuery *query, char *message, int percent); + void (* query_done) (CalQuery *query, ECalendarStatus status); } CalQueryClass; GType cal_query_get_type (void); -GType cal_query_done_status_enum_get_type (void); - -CalQuery *cal_query_construct (CalQuery *query, - GNOME_Evolution_Calendar_Cal cal, - const char *sexp); - -CalQuery *cal_query_new (CalClient *client, - GNOME_Evolution_Calendar_Cal cal, - const char *sexp); +CalQuery *cal_query_new (GNOME_Evolution_Calendar_Query corba_query, QueryListener *listener, CalClient *client); CalClient *cal_query_get_client (CalQuery *query); - - +void cal_query_start (CalQuery *query); G_END_DECLS diff --git a/calendar/cal-client/client-test.c b/calendar/cal-client/client-test.c index cb6eed17b2..48763be50a 100644 --- a/calendar/cal-client/client-test.c +++ b/calendar/cal-client/client-test.c @@ -45,24 +45,37 @@ cl_printf (CalClient *client, const char *format, ...) va_end (args); } -/* Dumps some interesting data from a component */ static void -dump_component (CalComponent *comp) +objects_added_cb (GObject *object, GList *objects, gpointer data) { - const char *uid; - CalComponentText summary; + GList *l; + + for (l = objects; l; l = l->next) + cl_printf (data, "Object added %s\n", icalcomponent_get_uid (l->data)); +} - cal_component_get_uid (comp, &uid); +static void +objects_modified_cb (GObject *object, GList *objects, gpointer data) +{ + GList *l; + + for (l = objects; l; l = l->next) + cl_printf (data, "Object modified %s\n", icalcomponent_get_uid (l->data)); +} - printf ("UID %s\n", uid); +static void +objects_removed_cb (GObject *object, GList *objects, gpointer data) +{ + GList *l; + + for (l = objects; l; l = l->next) + cl_printf (data, "Object removed %s\n", icalcomponent_get_uid (l->data)); +} - cal_component_get_summary (comp, &summary); - if (summary.value) - printf ("\tSummary: `%s', altrep `%s'\n", - summary.value, - summary.altrep ? summary.altrep : "NONE"); - else - printf ("\tNo summary\n"); +static void +query_done_cb (GObject *object, ECalendarStatus status, gpointer data) +{ + cl_printf (data, "Query done\n"); } /* Lists the UIDs of objects in a calendar, called as an idle handler */ @@ -70,47 +83,38 @@ static gboolean list_uids (gpointer data) { CalClient *client; - GList *uids; + GList *objects = NULL; GList *l; - + client = CAL_CLIENT (data); - uids = cal_client_get_uids (client, CALOBJ_TYPE_ANY); - - cl_printf (client, "UIDs: "); + g_message ("Blah"); + + if (!cal_client_get_object_list (client, "(contains? \"any\" \"Test4\")", &objects, NULL)) + return FALSE; + + cl_printf (client, "UIDS: "); - if (!uids) + if (!objects) printf ("none\n"); else { - for (l = uids; l; l = l->next) { - char *uid; + for (l = objects; l; l = l->next) { + const char *uid; - uid = l->data; + uid = icalcomponent_get_uid (l->data); printf ("`%s' ", uid); } printf ("\n"); - for (l = uids; l; l = l->next) { - char *uid; - CalComponent *comp; - CalClientGetStatus status; - - uid = l->data; - status = cal_client_get_object (client, uid, &comp); - - if (status == CAL_CLIENT_GET_SUCCESS) { - printf ("------------------------------\n"); - dump_component (comp); - printf ("------------------------------\n"); - g_object_unref (comp); - } else { - printf ("FAILED: %d\n", status); - } + for (l = objects; l; l = l->next) { + printf ("------------------------------\n"); + printf ("%s", icalcomponent_as_ical_string (l->data)); + printf ("------------------------------\n"); } } - cal_obj_uid_list_free (uids); + cal_client_free_object_list (objects); g_object_unref (client); @@ -121,6 +125,8 @@ list_uids (gpointer data) static void cal_opened_cb (CalClient *client, CalClientOpenStatus status, gpointer data) { + CalQuery *query; + cl_printf (client, "Load/create %s\n", ((status == CAL_CLIENT_OPEN_SUCCESS) ? "success" : (status == CAL_CLIENT_OPEN_ERROR) ? "error" : @@ -129,40 +135,29 @@ cal_opened_cb (CalClient *client, CalClientOpenStatus status, gpointer data) "unknown status value")); if (status == CAL_CLIENT_OPEN_SUCCESS) { - GList *comp_list; - - /* get free/busy information */ - comp_list = cal_client_get_free_busy (client, NULL, 0, time (NULL)); - if (comp_list) { - GList *l; - - for (l = comp_list; l; l = l->next) { - char *comp_str; - - comp_str = cal_component_get_as_string (CAL_COMPONENT (l->data)); - g_object_unref (l->data); - cl_printf (client, "Free/Busy -> %s\n", comp_str); - g_free (comp_str); - } - g_list_free (comp_list); - } - + if (!cal_client_get_query (client, "(contains? \"any\" \"Test4\")", &query, NULL)) + g_warning (G_STRLOC ": Unable to obtain query"); + + g_signal_connect (G_OBJECT (query), "objects_added", + G_CALLBACK (objects_added_cb), client); + g_signal_connect (G_OBJECT (query), "objects_modified", + G_CALLBACK (objects_modified_cb), client); + g_signal_connect (G_OBJECT (query), "objects_removed", + G_CALLBACK (objects_removed_cb), client); + g_signal_connect (G_OBJECT (query), "query_done", + G_CALLBACK (query_done_cb), client); + + cal_query_start (query); + g_idle_add (list_uids, client); } else g_object_unref (client); } -/* Callback used when an object is updated */ -static void -obj_updated_cb (CalClient *client, const char *uid, gpointer data) -{ - cl_printf (client, "Object updated: %s\n", uid); -} - /* Callback used when a client is destroyed */ static void -client_destroy_cb (GObject *object, gpointer data) +client_destroy_cb (gpointer data, GObject *object) { if (CAL_CLIENT (object) == client1) client1 = NULL; @@ -177,33 +172,24 @@ client_destroy_cb (GObject *object, gpointer data) /* Creates a calendar client and tries to load the specified URI into it */ static void -create_client (CalClient **client, const char *uri, gboolean only_if_exists) +create_client (CalClient **client, const char *uri, CalObjType type, gboolean only_if_exists) { - gboolean result; - - *client = cal_client_new (); + *client = cal_client_new (uri, type); if (!*client) { - g_message ("create_client(): could not create the client"); + g_message (G_STRLOC ": could not create the client"); exit (1); } - g_signal_connect (*client, "destroy", - G_CALLBACK (client_destroy_cb), - NULL); + g_object_weak_ref (G_OBJECT (*client), client_destroy_cb, NULL); g_signal_connect (*client, "cal_opened", G_CALLBACK (cal_opened_cb), NULL); - g_signal_connect (*client, "obj_updated", - G_CALLBACK (obj_updated_cb), - NULL); printf ("Calendar loading `%s'...\n", uri); - result = cal_client_open_calendar (*client, uri, only_if_exists); - - if (!result) { - g_message ("create_client(): failure when issuing calendar open request `%s'", + if (!cal_client_open (*client, only_if_exists, NULL)) { + g_message (G_STRLOC ": failure when issuing calendar open request `%s'", uri); exit (1); } @@ -212,8 +198,6 @@ create_client (CalClient **client, const char *uri, gboolean only_if_exists) int main (int argc, char **argv) { - char *dir; - bindtextdomain (GETTEXT_PACKAGE, EVOLUTION_LOCALEDIR); textdomain (GETTEXT_PACKAGE); @@ -225,10 +209,9 @@ main (int argc, char **argv) exit (1); } - dir = g_strdup_printf ("%s/evolution/local/Calendar/calendar.ics", g_get_home_dir ()); - create_client (&client1, dir, FALSE); - g_free (dir); - create_client (&client2, "/cvs/evolution/calendar/cal-client/test.ics", TRUE); + create_client (&client1, "file:///home/gnome24-evolution-new-calendar/evolution/local/Calendar", + CALOBJ_TYPE_EVENT, FALSE); +// create_client (&client2, "file:///tmp/tasks", TRUE); bonobo_main (); return 0; diff --git a/calendar/cal-client/query-listener.c b/calendar/cal-client/query-listener.c index 6bd7bfc6f7..4c8cbb4fe5 100644 --- a/calendar/cal-client/query-listener.c +++ b/calendar/cal-client/query-listener.c @@ -22,6 +22,7 @@ #include <config.h> #endif +#include "cal-marshal.h" #include "query-listener.h" @@ -29,166 +30,164 @@ /* Private part of the QueryListener structure */ struct _QueryListenerPrivate { - /* Callbacks for notification and their closure data */ - QueryListenerObjUpdatedFn obj_updated_fn; - QueryListenerObjRemovedFn obj_removed_fn; - QueryListenerQueryDoneFn query_done_fn; - QueryListenerEvalErrorFn eval_error_fn; - gpointer fn_data; - - /* Whether notification is desired */ - gboolean notify : 1; + int dummy; }; - - -static void query_listener_class_init (QueryListenerClass *class); -static void query_listener_init (QueryListener *ql, QueryListenerClass *class); -static void query_listener_finalize (GObject *object); - -static void impl_notifyObjUpdated (PortableServer_Servant servant, - const GNOME_Evolution_Calendar_CalObjUIDSeq *uids, - CORBA_boolean query_in_progress, - CORBA_long n_scanned, - CORBA_long total, - CORBA_Environment *ev); - -static void impl_notifyObjRemoved (PortableServer_Servant servant, - const CORBA_char *uid, - CORBA_Environment *ev); - -static void impl_notifyQueryDone (PortableServer_Servant servant, - GNOME_Evolution_Calendar_QueryListener_QueryDoneStatus corba_status, - const CORBA_char *error_str, - CORBA_Environment *ev); +/* Signal IDs */ +enum { + OBJECTS_ADDED, + OBJECTS_MODIFIED, + OBJECTS_REMOVED, + QUERY_PROGRESS, + QUERY_DONE, + LAST_SIGNAL +}; -static void impl_notifyEvalError (PortableServer_Servant servant, - const CORBA_char *error_str, - CORBA_Environment *ev); +static guint signals[LAST_SIGNAL] = { 0 }; static BonoboObjectClass *parent_class; - - -BONOBO_TYPE_FUNC_FULL (QueryListener, - GNOME_Evolution_Calendar_QueryListener, - BONOBO_TYPE_OBJECT, - query_listener); - -/* Class initialization function for the live search query listener */ -static void -query_listener_class_init (QueryListenerClass *class) +/* CORBA method implementations */ +/* FIXME This is duplicated from cal-listener.c */ +static ECalendarStatus +convert_status (const GNOME_Evolution_Calendar_CallStatus status) { - GObjectClass *object_class; + switch (status) { + case GNOME_Evolution_Calendar_Success: + return E_CALENDAR_STATUS_OK; + case GNOME_Evolution_Calendar_RepositoryOffline: + return E_CALENDAR_STATUS_REPOSITORY_OFFLINE; + case GNOME_Evolution_Calendar_PermissionDenied: + return E_CALENDAR_STATUS_PERMISSION_DENIED; + case GNOME_Evolution_Calendar_ObjectNotFound: + return E_CALENDAR_STATUS_OBJECT_NOT_FOUND; + case GNOME_Evolution_Calendar_CardIdAlreadyExists: + return E_CALENDAR_STATUS_CARD_ID_ALREADY_EXISTS; + case GNOME_Evolution_Calendar_AuthenticationFailed: + return E_CALENDAR_STATUS_AUTHENTICATION_FAILED; + case GNOME_Evolution_Calendar_AuthenticationRequired: + return E_CALENDAR_STATUS_AUTHENTICATION_REQUIRED; + case GNOME_Evolution_Calendar_OtherError: + default: + return E_CALENDAR_STATUS_OTHER_ERROR; + } +} - object_class = (GObjectClass *) class; +/* FIXME This is duplicated from cal-listener.c */ +static GList * +build_object_list (const GNOME_Evolution_Calendar_stringlist *seq) +{ + GList *list; + int i; + + list = NULL; + for (i = 0; i < seq->_length; i++) { + icalcomponent *comp; + + comp = icalcomponent_new_from_string (seq->_buffer[i]); + if (!comp) + continue; + + list = g_list_prepend (list, comp); + } + + return list; +} - parent_class = g_type_class_peek_parent (class); +static GList * +build_uid_list (const GNOME_Evolution_Calendar_CalObjUIDSeq *seq) +{ + GList *list; + int i; - object_class->finalize = query_listener_finalize; + list = NULL; + for (i = 0; i < seq->_length; i++) + list = g_list_prepend (list, g_strdup (seq->_buffer[i])); - class->epv.notifyObjUpdated = impl_notifyObjUpdated; - class->epv.notifyObjRemoved = impl_notifyObjRemoved; - class->epv.notifyQueryDone = impl_notifyQueryDone; - class->epv.notifyEvalError = impl_notifyEvalError; + return list; } -/* Object initialization function for the live search query listener */ static void -query_listener_init (QueryListener *ql, QueryListenerClass *class) +impl_notifyObjectsAdded (PortableServer_Servant servant, + const GNOME_Evolution_Calendar_stringlist *objects, + CORBA_Environment *ev) { + QueryListener *ql; QueryListenerPrivate *priv; + GList *object_list, *l; + + ql = QUERY_LISTENER (bonobo_object_from_servant (servant)); + priv = ql->priv; - priv = g_new0 (QueryListenerPrivate, 1); - ql->priv = priv; - - priv->obj_updated_fn = NULL; - priv->obj_removed_fn = NULL; - priv->query_done_fn = NULL; - priv->eval_error_fn = NULL; - priv->fn_data = NULL; + object_list = build_object_list (objects); + + g_signal_emit (G_OBJECT (ql), signals[OBJECTS_ADDED], 0, object_list); - priv->notify = TRUE; + for (l = object_list; l; l = l->next) + icalcomponent_free (l->data); + g_list_free (object_list); } -/* Finalize handler for the live search query listener */ static void -query_listener_finalize (GObject *object) +impl_notifyObjectsModified (PortableServer_Servant servant, + const GNOME_Evolution_Calendar_stringlist *objects, + CORBA_Environment *ev) { QueryListener *ql; QueryListenerPrivate *priv; - - g_return_if_fail (object != NULL); - g_return_if_fail (IS_QUERY_LISTENER (object)); - - ql = QUERY_LISTENER (object); + GList *object_list, *l; + + ql = QUERY_LISTENER (bonobo_object_from_servant (servant)); priv = ql->priv; - priv->obj_updated_fn = NULL; - priv->obj_removed_fn = NULL; - priv->query_done_fn = NULL; - priv->eval_error_fn = NULL; - priv->fn_data = NULL; - - priv->notify = FALSE; + object_list = build_object_list (objects); + + g_signal_emit (G_OBJECT (ql), signals[OBJECTS_MODIFIED], 0, object_list); - g_free (priv); - ql->priv = NULL; - - if (G_OBJECT_CLASS (parent_class)->finalize) - (* G_OBJECT_CLASS (parent_class)->finalize) (object); + for (l = object_list; l; l = l->next) + icalcomponent_free (l->data); + g_list_free (object_list); } - - -/* CORBA method implementations */ - -/* ::notifyObjUpdated() method */ static void -impl_notifyObjUpdated (PortableServer_Servant servant, - const GNOME_Evolution_Calendar_CalObjUIDSeq *uids, - CORBA_boolean query_in_progress, - CORBA_long n_scanned, - CORBA_long total, - CORBA_Environment *ev) +impl_notifyObjectsRemoved (PortableServer_Servant servant, + const GNOME_Evolution_Calendar_CalObjUIDSeq *uids, + CORBA_Environment *ev) { QueryListener *ql; QueryListenerPrivate *priv; - + GList *uid_list, *l; + ql = QUERY_LISTENER (bonobo_object_from_servant (servant)); priv = ql->priv; - if (!priv->notify) - return; + uid_list = build_uid_list (uids); + + g_signal_emit (G_OBJECT (ql), signals[OBJECTS_REMOVED], 0, uid_list); - g_assert (priv->obj_updated_fn != NULL); - (* priv->obj_updated_fn) (ql, uids, query_in_progress, n_scanned, total, priv->fn_data); + for (l = uid_list; l; l = l->next) + g_free (l->data); + g_list_free (uid_list); } -/* ::notifyObjRemoved() method */ static void -impl_notifyObjRemoved (PortableServer_Servant servant, - const CORBA_char *uid, - CORBA_Environment *ev) +impl_notifyQueryProgress (PortableServer_Servant servant, + const CORBA_char *message, + const CORBA_short percent, + CORBA_Environment *ev) { QueryListener *ql; QueryListenerPrivate *priv; ql = QUERY_LISTENER (bonobo_object_from_servant (servant)); priv = ql->priv; - - if (!priv->notify) - return; - - g_assert (priv->obj_removed_fn != NULL); - (* priv->obj_removed_fn) (ql, uid, priv->fn_data); + + g_signal_emit (G_OBJECT (ql), signals[QUERY_PROGRESS], 0, message, percent); } -/* ::notifyQueryDone() method */ static void impl_notifyQueryDone (PortableServer_Servant servant, - GNOME_Evolution_Calendar_QueryListener_QueryDoneStatus corba_status, - const CORBA_char *error_str, + const GNOME_Evolution_Calendar_CallStatus status, CORBA_Environment *ev) { QueryListener *ql; @@ -196,126 +195,110 @@ impl_notifyQueryDone (PortableServer_Servant servant, ql = QUERY_LISTENER (bonobo_object_from_servant (servant)); priv = ql->priv; + + g_signal_emit (G_OBJECT (ql), signals[QUERY_DONE], 0, convert_status (status)); +} - if (!priv->notify) - return; +/* Object initialization function for the live search query listener */ +static void +query_listener_init (QueryListener *ql, QueryListenerClass *class) +{ + QueryListenerPrivate *priv; - g_assert (priv->query_done_fn != NULL); - (* priv->query_done_fn) (ql, corba_status, error_str, priv->fn_data); + priv = g_new0 (QueryListenerPrivate, 1); + ql->priv = priv; } -/* ::notifyEvalError() method */ +/* Finalize handler for the live search query listener */ static void -impl_notifyEvalError (PortableServer_Servant servant, - const CORBA_char *error_str, - CORBA_Environment *ev) +query_listener_finalize (GObject *object) { QueryListener *ql; QueryListenerPrivate *priv; - ql = QUERY_LISTENER (bonobo_object_from_servant (servant)); + g_return_if_fail (object != NULL); + g_return_if_fail (IS_QUERY_LISTENER (object)); + + ql = QUERY_LISTENER (object); priv = ql->priv; - if (!priv->notify) - return; + g_free (priv); - g_assert (priv->eval_error_fn != NULL); - (* priv->eval_error_fn) (ql, error_str, priv->fn_data); + if (G_OBJECT_CLASS (parent_class)->finalize) + (* G_OBJECT_CLASS (parent_class)->finalize) (object); } - - -/** - * query_listener_construct: - * @ql: A query listener. - * @obj_updated_fn: Callback to use when a component is updated in the query. - * @obj_removed_fn: Callback to use when a component is removed from the query. - * @query_done_fn: Callback to use when a query is done. - * @eval_error_fn: Callback to use when an evaluation error happens during a query. - * @fn_data: Closure data to pass to the callbacks. - * - * Constructs a query listener by setting the callbacks it will use for - * notification from the calendar server. - * - * Return value: The same value as @ql. - **/ -QueryListener * -query_listener_construct (QueryListener *ql, - QueryListenerObjUpdatedFn obj_updated_fn, - QueryListenerObjRemovedFn obj_removed_fn, - QueryListenerQueryDoneFn query_done_fn, - QueryListenerEvalErrorFn eval_error_fn, - gpointer fn_data) +/* Class initialization function for the live search query listener */ +static void +query_listener_class_init (QueryListenerClass *klass) { - QueryListenerPrivate *priv; + GObjectClass *object_class; - g_return_val_if_fail (ql != NULL, NULL); - g_return_val_if_fail (IS_QUERY_LISTENER (ql), NULL); - g_return_val_if_fail (obj_updated_fn != NULL, NULL); - g_return_val_if_fail (obj_removed_fn != NULL, NULL); - g_return_val_if_fail (query_done_fn != NULL, NULL); - g_return_val_if_fail (eval_error_fn != NULL, NULL); + object_class = (GObjectClass *) klass; - priv = ql->priv; + parent_class = g_type_class_peek_parent (klass); - priv->obj_updated_fn = obj_updated_fn; - priv->obj_removed_fn = obj_removed_fn; - priv->query_done_fn = query_done_fn; - priv->eval_error_fn = eval_error_fn; - priv->fn_data = fn_data; + object_class->finalize = query_listener_finalize; - return ql; + klass->epv.notifyObjectsAdded = impl_notifyObjectsAdded; + klass->epv.notifyObjectsModified = impl_notifyObjectsModified; + klass->epv.notifyObjectsRemoved = impl_notifyObjectsRemoved; + klass->epv.notifyQueryProgress = impl_notifyQueryProgress; + klass->epv.notifyQueryDone = impl_notifyQueryDone; + + signals[OBJECTS_ADDED] = + g_signal_new ("objects_added", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (QueryListenerClass, objects_added), + NULL, NULL, + cal_marshal_VOID__POINTER, + G_TYPE_NONE, 1, G_TYPE_POINTER); + signals[OBJECTS_MODIFIED] = + g_signal_new ("objects_modified", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (QueryListenerClass, objects_modified), + NULL, NULL, + cal_marshal_VOID__POINTER, + G_TYPE_NONE, 1, G_TYPE_POINTER); + signals[OBJECTS_REMOVED] = + g_signal_new ("objects_removed", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (QueryListenerClass, objects_removed), + NULL, NULL, + cal_marshal_VOID__POINTER, + G_TYPE_NONE, 1, G_TYPE_POINTER); + signals[QUERY_PROGRESS] = + g_signal_new ("query_progress", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (QueryListenerClass, query_progress), + NULL, NULL, + cal_marshal_VOID__POINTER, + G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_INT); + signals[QUERY_DONE] = + g_signal_new ("query_done", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (QueryListenerClass, query_done), + NULL, NULL, + cal_marshal_VOID__INT, + G_TYPE_NONE, 1, G_TYPE_INT); } -/** - * query_listener_new: - * @obj_updated_fn: Callback to use when a component is updated in the query. - * @obj_removed_fn: Callback to use when a component is removed from the query. - * @query_done_fn: Callback to use when a query is done. - * @eval_error_fn: Callback to use when an evaluation error happens during a query. - * @fn_data: Closure data to pass to the callbacks. - * - * Creates a new query listener object. - * - * Return value: A newly-created query listener object. - **/ +BONOBO_TYPE_FUNC_FULL (QueryListener, + GNOME_Evolution_Calendar_QueryListener, + BONOBO_TYPE_OBJECT, + query_listener); + QueryListener * -query_listener_new (QueryListenerObjUpdatedFn obj_updated_fn, - QueryListenerObjRemovedFn obj_removed_fn, - QueryListenerQueryDoneFn query_done_fn, - QueryListenerEvalErrorFn eval_error_fn, - gpointer fn_data) +query_listener_new (void) { QueryListener *ql; ql = g_object_new (QUERY_LISTENER_TYPE, NULL); - return query_listener_construct (ql, - obj_updated_fn, - obj_removed_fn, - query_done_fn, - eval_error_fn, - fn_data); -} - -/** - * query_listener_stop_notification: - * @ql: A query listener. - * - * Informs a query listener that no further notification is desired. The - * callbacks specified when the listener was created will no longer be invoked - * after this function is called. - **/ -void -query_listener_stop_notification (QueryListener *ql) -{ - QueryListenerPrivate *priv; - - g_return_if_fail (ql != NULL); - g_return_if_fail (IS_QUERY_LISTENER (ql)); - - priv = ql->priv; - g_return_if_fail (priv->notify != FALSE); - - priv->notify = FALSE; + return ql; } diff --git a/calendar/cal-client/query-listener.h b/calendar/cal-client/query-listener.h index eeb42afc7e..6a204bbf77 100644 --- a/calendar/cal-client/query-listener.h +++ b/calendar/cal-client/query-listener.h @@ -22,6 +22,7 @@ #define QUERY_LISTENER_H #include <bonobo/bonobo-object.h> +#include "cal-client-types.h" #include "evolution-calendar.h" G_BEGIN_DECLS @@ -48,47 +49,18 @@ typedef struct { BonoboObjectClass parent_class; POA_GNOME_Evolution_Calendar_QueryListener__epv epv; + + void (*objects_added) (QueryListener *listener, GList *objects); + void (*objects_modified) (QueryListener *listener, GList *objects); + void (*objects_removed) (QueryListener *listener, GList *uids); + void (*query_progress) (QueryListener *listener, const char *message, int percent); + void (*query_done) (QueryListener *listener, ECalendarStatus status); } QueryListenerClass; /* Notification functions */ -typedef void (* QueryListenerObjUpdatedFn) (QueryListener *ql, - const GNOME_Evolution_Calendar_CalObjUIDSeq *uids, - CORBA_boolean query_in_progress, - CORBA_long n_scanned, - CORBA_long total, - gpointer data); - -typedef void (* QueryListenerObjRemovedFn) (QueryListener *ql, - const CORBA_char *uid, - gpointer data); - -typedef void (* QueryListenerQueryDoneFn) ( - QueryListener *ql, - GNOME_Evolution_Calendar_QueryListener_QueryDoneStatus status, - const CORBA_char *error_str, - gpointer data); - -typedef void (* QueryListenerEvalErrorFn) (QueryListener *ql, - const CORBA_char *error_str, - gpointer data); - GType query_listener_get_type (void); - -QueryListener *query_listener_construct (QueryListener *ql, - QueryListenerObjUpdatedFn obj_updated_fn, - QueryListenerObjRemovedFn obj_removed_fn, - QueryListenerQueryDoneFn query_done_fn, - QueryListenerEvalErrorFn eval_error_fn, - gpointer fn_data); - -QueryListener *query_listener_new (QueryListenerObjUpdatedFn obj_updated_fn, - QueryListenerObjRemovedFn obj_removed_fn, - QueryListenerQueryDoneFn query_done_fn, - QueryListenerEvalErrorFn eval_error_fn, - gpointer fn_data); - -void query_listener_stop_notification (QueryListener *ql); +QueryListener *query_listener_new (void); |