From 2b78b5294a6a047a971446595c9e7f5f32f583a2 Mon Sep 17 00:00:00 2001 From: Rodrigo Moya Date: Tue, 18 Sep 2001 20:16:39 +0000 Subject: new class for managing multiple calendars, with an API very similar to the 2001-09-18 Rodrigo Moya * cal-client/cal-client-multi.[ch]: new class for managing multiple calendars, with an API very similar to the CalClient one, for ease of transition from one to the other * gui/component-factory.c (xfer_folder, remove_folder, create_folder): reworked to be able to manage folders for any calendar backend, and not only the file: one 2001-09-18 Rodrigo Moya * idl/evolution-calendar.idl: changed signature for the getFreeBusy method, to return a sequence of CalObj's, and added sequence of users as a new parameter to that method * cal-client/cal-client.c (cal_client_get_free_busy): adapted to new IDL method signature, by adding a new "GList *users" parameter, for callers to be able to specify a list of users * pcs/cal-backend.[ch] (cal_backend_get_free_busy): * pcs/cal-backend-file.c (cal_backend_file_get_free_busy): add the "GList *users" parameter. In cal_backend_file_get_free_busy, call lookup_component to get the CalComponent for each uid, instead of calling cal_backend_get_object, which meant converting the component to a string and then parsing it again. * cal-client/client-test.c (cal_opened_cb): * gui/e-itip-control.c (send_freebusy): * gui/calendar-commands.c (publish_freebusy_cmd): adapted to new getFreeBusy method signature svn path=/trunk/; revision=12951 --- calendar/ChangeLog | 32 ++ calendar/cal-client/Makefile.am | 2 + calendar/cal-client/cal-client-multi.c | 707 +++++++++++++++++++++++++++++++++ calendar/cal-client/cal-client-multi.h | 105 +++++ calendar/cal-client/cal-client.c | 86 ++-- calendar/cal-client/cal-client.h | 4 +- calendar/cal-client/client-test.c | 24 +- calendar/gui/calendar-commands.c | 28 +- calendar/gui/calendar-component.c | 333 ++++++++++------ calendar/gui/component-factory.c | 333 ++++++++++------ calendar/gui/e-itip-control.c | 17 +- calendar/idl/evolution-calendar.idl | 6 +- calendar/pcs/cal-backend-file.c | 55 ++- calendar/pcs/cal-backend.c | 9 +- calendar/pcs/cal-backend.h | 4 +- calendar/pcs/cal.c | 55 ++- 16 files changed, 1436 insertions(+), 364 deletions(-) create mode 100644 calendar/cal-client/cal-client-multi.c create mode 100644 calendar/cal-client/cal-client-multi.h diff --git a/calendar/ChangeLog b/calendar/ChangeLog index 880521239a..3ec0905c43 100644 --- a/calendar/ChangeLog +++ b/calendar/ChangeLog @@ -1,3 +1,35 @@ +2001-09-18 Rodrigo Moya + + * cal-client/cal-client-multi.[ch]: new class for managing multiple + calendars, with an API very similar to the CalClient one, + for ease of transition from one to the other + + * gui/component-factory.c (xfer_folder, remove_folder, create_folder): + reworked to be able to manage folders for any calendar backend, and + not only the file: one + +2001-09-18 Rodrigo Moya + + * idl/evolution-calendar.idl: changed signature for the getFreeBusy + method, to return a sequence of CalObj's, and added sequence of users + as a new parameter to that method + + * cal-client/cal-client.c (cal_client_get_free_busy): adapted to new + IDL method signature, by adding a new "GList *users" parameter, for + callers to be able to specify a list of users + + * pcs/cal-backend.[ch] (cal_backend_get_free_busy): + * pcs/cal-backend-file.c (cal_backend_file_get_free_busy): add the + "GList *users" parameter. In cal_backend_file_get_free_busy, call + lookup_component to get the CalComponent for each uid, instead + of calling cal_backend_get_object, which meant converting the + component to a string and then parsing it again. + + * cal-client/client-test.c (cal_opened_cb): + * gui/e-itip-control.c (send_freebusy): + * gui/calendar-commands.c (publish_freebusy_cmd): adapted to + new getFreeBusy method signature + 2001-09-17 Damon Chaplin * gui/calendar-model.c: added a timeout to refresh the list every diff --git a/calendar/cal-client/Makefile.am b/calendar/cal-client/Makefile.am index e910aa9610..28bab236ae 100644 --- a/calendar/cal-client/Makefile.am +++ b/calendar/cal-client/Makefile.am @@ -38,6 +38,7 @@ libcal_clientincludedir = $(includedir)/evolution/cal-client libcal_client_la_SOURCES = \ $(CORBA_GENERATED) \ + cal-client-multi.c \ cal-client-types.c \ cal-client.c \ cal-listener.c \ @@ -48,6 +49,7 @@ libcal_client_la_SOURCES = \ libcal_clientinclude_HEADERS = \ $(CORBA_HEADERS_GENERATED) \ + cal-client-multi.h \ cal-client-types.h \ cal-client.h \ cal-query.h diff --git a/calendar/cal-client/cal-client-multi.c b/calendar/cal-client/cal-client-multi.c new file mode 100644 index 0000000000..c351d6cbd6 --- /dev/null +++ b/calendar/cal-client/cal-client-multi.c @@ -0,0 +1,707 @@ +/* Evolution calendar client + * + * Copyright (C) 2001 Ximian, Inc. + * + * Author: Rodrigo Moya + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include "cal-client-multi.h" + +/* Private part of the CalClientMulti structure */ +struct _CalClientMultiPrivate { + GHashTable *calendars; + GList *uris; +}; + +static void cal_client_multi_class_init (CalClientMultiClass *klass); +static void cal_client_multi_init (CalClientMulti *multi); +static void cal_client_multi_destroy (GtkObject *object); + +/* signal IDs */ +enum { + CAL_OPENED, + OBJ_UPDATED, + OBJ_REMOVED, + CATEGORIES_CHANGED, + FORGET_PASSWORD, + LAST_SIGNAL +}; + +static guint cal_multi_signals[LAST_SIGNAL]; +static GtkObjectClass *parent_class = NULL; + +/* + * Private functions + */ + +/** + * cal_client_multi_get_type + * + * Registers the #CalClientMulti class if necessary, and returns the type ID + * assigned to it. + * + * Returns: The type ID of the #CalClientMulti class + */ +GtkType +cal_client_multi_get_type (void) +{ + static GtkType type = 0; + + if (!type) { + static const GtkTypeInfo info = { + "CalClientMulti", + sizeof (CalClientMulti), + sizeof (CalClientMultiClass), + (GtkClassInitFunc) cal_client_multi_class_init, + (GtkObjectInitFunc) cal_client_multi_init, + NULL, + NULL, + (GtkClassInitFunc) NULL + }; + + type = gtk_type_unique (GTK_TYPE_OBJECT, &info); + } + + return type; +} + +/* class initialization function for the multi calendar client */ +static void +cal_client_multi_class_init (CalClientMultiClass *klass) +{ + GtkObjectClass *object_class = GTK_OBJECT_CLASS (klass); + + parent_class = gtk_type_class (GTK_TYPE_OBJECT); + + cal_multi_signals[CAL_OPENED] = + gtk_signal_new ("cal_opened", + GTK_RUN_FIRST, + object_class->type, + GTK_SIGNAL_OFFSET (CalClientMultiClass, cal_opened), + gtk_marshal_NONE__POINTER_INT, + GTK_TYPE_NONE, 2, + GTK_TYPE_POINTER, GTK_TYPE_ENUM); + cal_multi_signals[OBJ_UPDATED] = + gtk_signal_new ("obj_updated", + GTK_RUN_FIRST, + object_class->type, + GTK_SIGNAL_OFFSET (CalClientMultiClass, obj_updated), + gtk_marshal_NONE__POINTER_POINTER, + GTK_TYPE_NONE, 2, + GTK_TYPE_POINTER, GTK_TYPE_STRING); + cal_multi_signals[OBJ_REMOVED] = + gtk_signal_new ("obj_removed", + GTK_RUN_FIRST, + object_class->type, + GTK_SIGNAL_OFFSET (CalClientMultiClass, obj_removed), + gtk_marshal_NONE__POINTER_POINTER, + GTK_TYPE_NONE, 2, + GTK_TYPE_POINTER, GTK_TYPE_STRING); + cal_multi_signals[CATEGORIES_CHANGED] = + gtk_signal_new ("categories_changed", + GTK_RUN_FIRST, + object_class->type, + GTK_SIGNAL_OFFSET (CalClientMultiClass, categories_changed), + gtk_marshal_NONE__POINTER_POINTER, + GTK_TYPE_NONE, 2, + GTK_TYPE_POINTER, GTK_TYPE_POINTER); + cal_multi_signals[FORGET_PASSWORD] = + gtk_signal_new ("forget_password", + GTK_RUN_FIRST, + object_class->type, + GTK_SIGNAL_OFFSET (CalClientMultiClass, forget_password), + gtk_marshal_NONE__POINTER_POINTER, + GTK_TYPE_NONE, 2, + GTK_TYPE_STRING, GTK_TYPE_STRING); + + object_class->destroy = cal_client_multi_destroy; +} + +/* object initialization function for the multi calendar client */ +static void +cal_client_multi_init (CalClientMulti *multi) +{ + multi->priv = g_new0 (CalClientMultiPrivate, 1); + multi->priv->calendars = g_hash_table_new (g_str_hash, g_str_equal); + multi->priv->uris = NULL; +} + +static void +free_calendar (gpointer key, gpointer value, gpointer data) +{ + CalClientMulti *multi = (CalClientMulti *) data; + + g_return_if_fail (IS_CAL_CLIENT_MULTI (multi)); + + multi->priv->uris = g_list_remove (multi->priv->uris, key); + + g_free (key); + gtk_object_unref (GTK_OBJECT (value)); +} + +/* destroy handler for the multi calendar client */ +static void +cal_client_multi_destroy (GtkObject *object) +{ + CalClientMulti *multi = (CalClientMulti *) object; + + g_return_if_fail (IS_CAL_CLIENT_MULTI (multi)); + + /* free memory */ + g_hash_table_foreach (multi->priv->calendars, free_calendar, multi); + g_hash_table_destroy (multi->priv->calendars); + g_list_free (multi->priv->uris); + + g_free (multi->priv); + multi->priv = NULL; + + /* chain to parent class' destroy handler */ + if (GTK_OBJECT_CLASS (parent_class)->destroy) + (* GTK_OBJECT_CLASS (parent_class)->destroy) (object); +} + +/** + * cal_client_multi_new + * + * Creates a new multi-calendar client. This allows you to merge several + * #CalClient objects into one entity, making it easier to manage + * multiple calendars. + * + * Returns: A newly-created multi-calendar client. + */ +CalClientMulti * +cal_client_multi_new (void) +{ + CalClientMulti *multi; + + multi = gtk_type_new (CAL_CLIENT_MULTI_TYPE); + return multi; +} + +/* CalClient's signal handlers */ +static void +client_cal_opened_cb (CalClient *client, CalClientOpenStatus status, gpointer user_data) +{ + CalClientMulti *multi = (CalClientMulti *) user_data; + + g_return_if_fail (IS_CAL_CLIENT (client)); + g_return_if_fail (IS_CAL_CLIENT_MULTI (multi)); + + gtk_signal_emit (GTK_OBJECT (multi), + cal_multi_signals[CAL_OPENED], + client, status); +} + +static void +client_obj_updated_cb (CalClient *client, const char *uid, gpointer user_data) +{ + CalClientMulti *multi = (CalClientMulti *) user_data; + + g_return_if_fail (IS_CAL_CLIENT (client)); + g_return_if_fail (IS_CAL_CLIENT_MULTI (multi)); + + gtk_signal_emit (GTK_OBJECT (multi), + cal_multi_signals[OBJ_UPDATED], + client, uid); +} + +static void +client_obj_removed_cb (CalClient *client, const char *uid, gpointer user_data) +{ + CalClientMulti *multi = (CalClientMulti *) user_data; + + g_return_if_fail (IS_CAL_CLIENT (client)); + g_return_if_fail (IS_CAL_CLIENT_MULTI (multi)); + + gtk_signal_emit (GTK_OBJECT (multi), + cal_multi_signals[OBJ_REMOVED], + client, uid); +} + +static void +client_categories_changed_cb (CalClient *client, GPtrArray *categories, gpointer user_data) +{ + CalClientMulti *multi = (CalClientMulti *) user_data; + + g_return_if_fail (IS_CAL_CLIENT (client)); + g_return_if_fail (IS_CAL_CLIENT_MULTI (multi)); + + gtk_signal_emit (GTK_OBJECT (multi), + cal_multi_signals[CATEGORIES_CHANGED], + client, categories); +} + +static void +client_forget_password_cb (CalClient *client, const char *key, gpointer user_data) +{ + CalClientMulti *multi = (CalClientMulti *) user_data; + + g_return_if_fail (IS_CAL_CLIENT (client)); + g_return_if_fail (IS_CAL_CLIENT_MULTI (multi)); + + gtk_signal_emit (GTK_OBJECT (multi), + cal_multi_signals[FORGET_PASSWORD], + client, key); +} +/** + * cal_client_multi_add_client + * @multi: A #CalClientMulti object. + * @client: The #CalClient object to be added. + * + * Aggregates the given #CalClient to a #CalClientMulti object, + * thus adding it to the list of managed calendars. + */ +void +cal_client_multi_add_client (CalClientMulti *multi, CalClient *client) +{ + char *uri; + CalClient *old_client; + + g_return_if_fail (IS_CAL_CLIENT_MULTI (multi)); + g_return_if_fail (IS_CAL_CLIENT (client)); + + uri = g_strdup (cal_client_get_uri (client)); + old_client = g_hash_table_lookup (multi->priv->calendars, uri); + if (old_client) { + g_free (uri); + return; + } + + gtk_object_ref (GTK_OBJECT (client)); + multi->priv->uris = g_list_append (multi->priv->uris, uri); + g_hash_table_insert (multi->priv->calendars, uri, client); + + /* set up CalClient's signal handlers */ + gtk_signal_disconnect_by_data (GTK_OBJECT (client), multi); + gtk_signal_connect (GTK_OBJECT (client), + "cal_opened", + GTK_SIGNAL_FUNC (client_cal_opened_cb), + multi); + gtk_signal_connect (GTK_OBJECT (client), + "obj_updated", + GTK_SIGNAL_FUNC (client_obj_updated_cb), + multi); + gtk_signal_connect (GTK_OBJECT (client), + "obj_removed", + GTK_SIGNAL_FUNC (client_obj_removed_cb), + multi); + gtk_signal_connect (GTK_OBJECT (client), + "categories_changed", + GTK_SIGNAL_FUNC (client_categories_changed_cb), + multi); + gtk_signal_connect (GTK_OBJECT (client), + "forget_password", + GTK_SIGNAL_FUNC (client_forget_password_cb), + multi); +} + +typedef struct { + CalClientAuthFunc func; + gpointer user_data; +} AuthFuncData; + +static void +set_auth_func (gpointer key, gpointer value, gpointer user_data) +{ + AuthFuncData *cb_data = (AuthFuncData *) user_data; + CalClient *client = (CalClient *) value; + + g_return_if_fail (IS_CAL_CLIENT (client)); + g_return_if_fail (cb_data != NULL); + + cal_client_set_auth_func (client, cb_data->func, cb_data->user_data); +} + +/** + * cal_client_multi_set_auth_func + * @multi: A #CalClientMulti object. + * @func: The authentication function. + * @user_data: Data to be passed to the authentication function. + * + * Sets the authentication function for all the clients in the + * given #CalClientMulti. + */ +void +cal_client_multi_set_auth_func (CalClientMulti *multi, + CalClientAuthFunc func, + gpointer user_data) +{ + AuthFuncData *cb_data; + + g_return_if_fail (IS_CAL_CLIENT_MULTI (multi)); + + cb_data = g_new0 (AuthFuncData, 1); + cb_data->func = func; + cb_data->user_data = user_data; + g_hash_table_foreach (multi->priv->calendars, set_auth_func, cb_data); + + g_free (cb_data); +} + +/** + * cal_client_multi_open_calendar + * @multi: A #CalClientMulti object. + * @str_uri: The URI of the calendar to be open + * @only_if_exists: + * + * Open a new calendar in the given #CalClientMulti object. + * + * Returns: a pointer to the new #CalClient + */ +CalClient * +cal_client_multi_open_calendar (CalClientMulti *multi, + const char *str_uri, + gboolean only_if_exists) +{ + CalClient *client; + gboolean result; + + g_return_val_if_fail (IS_CAL_CLIENT_MULTI (multi), FALSE); + + client = cal_client_new (); + + result = cal_client_open_calendar (client, str_uri, only_if_exists); + if (result) { + cal_client_multi_add_client (multi, client); + gtk_object_unref (GTK_OBJECT (client)); + return client; + } + + gtk_object_unref (GTK_OBJECT (client)); + + return NULL; +} + +/** + * cal_client_multi_get_client_for_uri + * @multi: A #CalClientMulti object. + * @uri: The URI for the client. + * + * Returns the #CalClient object associated with the given + * @uri for the given #CalClientMulti object. + * + * Returns: a pointer to the client or NULL if no client is + * associated with that URI. + */ +CalClient * +cal_client_multi_get_client_for_uri (CalClientMulti *multi, const char *uri) +{ + g_return_val_if_fail (IS_CAL_CLIENT_MULTI (multi), NULL); + g_return_val_if_fail (uri != NULL, NULL); + + return g_hash_table_lookup (multi->priv->calendars, uri); +} + +/** + * cal_client_multi_get_n_objects + * @multi: A #CalClientMulti object. + * @type: Type for objects + * + * Get the count of objects of the given type(s) for a #CalClientMulti + * object. + * + * Returns: The count of objects of the given type(s). + */ +int +cal_client_multi_get_n_objects (CalClientMulti *multi, + CalObjType type) +{ + CalClient *client; + GList *l; + int count = 0; + + g_return_val_if_fail (IS_CAL_CLIENT_MULTI (multi), -1); + + for (l = multi->priv->uris; l; l = l->next) { + client = cal_client_multi_get_client_for_uri (multi, + (const char *) l->data); + if (IS_CAL_CLIENT (client)) + count += cal_client_get_n_objects (client, type); + } + + return count; +} + +/** + * cal_client_multi_get_object + */ +CalClientGetStatus +cal_client_multi_get_object (CalClientMulti *multi, + const char *uid, + CalComponent **comp) +{ + CalClient *client; + GList *l; + + g_return_val_if_fail (IS_CAL_CLIENT_MULTI (multi), CAL_CLIENT_GET_NOT_FOUND); + g_return_val_if_fail (uid != NULL, CAL_CLIENT_GET_NOT_FOUND); + + for (l = multi->priv->uris; l; l = l->next) { + client = cal_client_multi_get_client_for_uri (multi, + (const char *) l->data); + if (IS_CAL_CLIENT (client)) { + CalClientGetStatus status; + + status = cal_client_get_object (client, uid, comp); + if (status == CAL_CLIENT_GET_SUCCESS) + return status; + } + } + + return CAL_CLIENT_GET_NOT_FOUND; +} + +/** + * cal_client_multi_get_timezone + * @multi: A #CalClientMulti object. + * @tzid: ID for the timezone to be retrieved. + * @zone: A pointer to where the icaltimezone object will be copied. + */ +CalClientGetStatus +cal_client_multi_get_timezone (CalClientMulti *multi, + const char *tzid, + icaltimezone **zone) +{ + CalClient *client; + GList *l; + + g_return_val_if_fail (IS_CAL_CLIENT_MULTI (multi), CAL_CLIENT_GET_NOT_FOUND); + g_return_val_if_fail (tzid != NULL, CAL_CLIENT_GET_NOT_FOUND); + + for (l = multi->priv->uris; l; l = l->next) { + client = cal_client_multi_get_client_for_uri (multi, + (const char *) l->data); + if (IS_CAL_CLIENT (client)) { + CalClientGetStatus status; + + status = cal_client_get_timezone (client, tzid, zone); + if (status == CAL_CLIENT_GET_SUCCESS) + return status; + } + } + + return CAL_CLIENT_GET_NOT_FOUND; +} + +/** + * cal_client_multi_get_uids + * @multi: A #CalClientMulti object. + * @type: Type of objects whose IDs will be returned. + * + * Returns a list of UIDs for all the objects of the given + * type(s) that are in the calendars managed by a + * #CalClientMulti object + * + * Returns: a GList of UIDs. + */ +GList * +cal_client_multi_get_uids (CalClientMulti *multi, CalObjType type) +{ + CalClient *client; + GList *l; + GList *result = NULL; + + g_return_val_if_fail (IS_CAL_CLIENT_MULTI (multi), NULL); + + for (l = multi->priv->uris; l; l = l->next) { + client = cal_client_multi_get_client_for_uri (multi, + (const char *) l->data); + if (IS_CAL_CLIENT (client)) { + GList *tmp; + + tmp = cal_client_get_uids (client, type); + if (tmp) + result = g_list_concat (result, tmp); + } + } + + return result; +} + +/** + * cal_client_multi_get_changes + * @multi: A #CalClientMulti object. + * @type: Object type. + * @change_id: Change ID. + * + * Returns a list of changes for the given #CalClientMulti + * object. + */ +GList * +cal_client_multi_get_changes (CalClientMulti *multi, + CalObjType type, + const char *change_id) +{ + CalClient *client; + GList *l; + GList *result = NULL; + + g_return_val_if_fail (IS_CAL_CLIENT_MULTI (multi), NULL); + + for (l = multi->priv->uris; l; l = l->next) { + client = cal_client_multi_get_client_for_uri (multi, + (const char *) l->data); + if (IS_CAL_CLIENT (client)) { + GList *tmp; + + tmp = cal_client_get_changes (client, type, change_id); + if (tmp) + result = g_list_concat (result, tmp); + } + } + + return result; +} + +/** + * cal_client_multi_get_objects_in_range + * @multi: A #CalClientMulti object. + * @type: Type for objects. + * @start: Start time. + * @end: End time. + * + * Retrieves a list of all calendar components that are + * scheduled within the given time range. The information is + * retrieved from all the calendars being managed by the + * given #CalClientMulti object. + * + * Returns: A list of UID strings. This should be freed using the + * #cal_obj_uid_list_free() function. + **/ +GList * +cal_client_multi_get_objects_in_range (CalClientMulti *multi, + CalObjType type, + time_t start, + time_t end) +{ + CalClient *client; + GList *l; + GList *result = NULL; + + g_return_val_if_fail (IS_CAL_CLIENT_MULTI (multi), NULL); + + for (l = multi->priv->uris; l; l = l->next) { + client = cal_client_multi_get_client_for_uri (multi, + (const char *) l->data); + if (IS_CAL_CLIENT (client)) { + GList *tmp; + + tmp = cal_client_get_objects_in_range (client, type, start, end); + if (tmp) + result = g_list_concat (result, tmp); + } + } + + return result; +} + +/** + * cal_client_multi_get_free_busy + * @multi: A #CalClientMulti object. + * @users: List of users to retrieve F/B information for. + * @start: Start time. + * @end: End time. + * + * Retrieves Free/Busy information for the given users in all + * the calendars being managed by the given #CalClient multi + * object. + * + * Returns: A GList of VFREEBUSY CalComponents + */ +GList * +cal_client_multi_get_free_busy (CalClientMulti *multi, + GList *users, + time_t start, + time_t end) +{ + CalClient *client; + GList *l; + GList *result = NULL; + + g_return_val_if_fail (IS_CAL_CLIENT_MULTI (multi), NULL); + + for (l = multi->priv->uris; l; l = l->next) { + client = cal_client_multi_get_client_for_uri (multi, + (const char *) l->data); + if (IS_CAL_CLIENT (client)) { + GList *tmp; + + tmp = cal_client_get_free_busy (client, users, start, end); + if (tmp) + result = g_list_concat (result, tmp); + } + } + + return result; +} + +/** + * cal_client_multi_generate_instances + */ +void +cal_client_multi_generate_instances (CalClientMulti *multi, + CalObjType type, + time_t start, + time_t end, + CalRecurInstanceFn cb, + gpointer cb_data) +{ + CalClient *client; + GList *l; + + g_return_if_fail (IS_CAL_CLIENT_MULTI (multi)); + + for (l = multi->priv->uris; l; l = l->next) { + client = cal_client_multi_get_client_for_uri (multi, + (const char *) l->data); + if (IS_CAL_CLIENT (client)) { + cal_client_generate_instances ( + client, type, start, end, cb, cb_data); + } + } +} + +/** + * cal_client_multi_get_alarms_in_range + */ +GSList * +cal_client_multi_get_alarms_in_range (CalClientMulti *multi, time_t start, time_t end) +{ + CalClient *client; + GList *l; + GSList *result = NULL; + + g_return_val_if_fail (IS_CAL_CLIENT_MULTI (multi), NULL); + + for (l = multi->priv->uris; l; l = l->next) { + client = cal_client_multi_get_client_for_uri (multi, + (const char *) l->data); + if (IS_CAL_CLIENT (client)) { + GSList *tmp; + + tmp = cal_client_get_alarms_in_range (client, start, end); + if (tmp) + result = g_slist_concat (result, tmp); + } + } + + return result; +} diff --git a/calendar/cal-client/cal-client-multi.h b/calendar/cal-client/cal-client-multi.h new file mode 100644 index 0000000000..0b7eec40e4 --- /dev/null +++ b/calendar/cal-client/cal-client-multi.h @@ -0,0 +1,105 @@ +/* Evolution calendar client + * + * Copyright (C) 2001 Ximian, Inc. + * + * Author: Rodrigo Moya + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef CAL_CLIENT_MULTI_H +#define CAL_CLIENT_MULTI_H + +#include + +BEGIN_GNOME_DECLS + +#define CAL_CLIENT_MULTI_TYPE (cal_client_multi_get_type ()) +#define CAL_CLIENT_MULTI(obj) (GTK_CHECK_CAST ((obj), CAL_CLIENT_MULTI_TYPE, CalClientMulti)) +#define CAL_CLIENT_MULTI_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), CAL_CLIENT_MULTI_TYPE, CalClientMultiClass)) +#define IS_CAL_CLIENT_MULTI(obj) (GTK_CHECK_TYPE ((obj), CAL_CLIENT_MULTI_TYPE)) +#define IS_CAL_CLIENT_MULTI_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), CAL_CLIENT_MULTI_TYPE)) + +typedef struct _CalClientMulti CalClientMulti; +typedef struct _CalClientMultiClass CalClientMultiClass; +typedef struct _CalClientMultiPrivate CalClientMultiPrivate; + +struct _CalClientMulti { + GtkObject object; + + /* Private data */ + CalClientMultiPrivate *priv; +}; + +struct _CalClientMultiClass { + GtkObjectClass parent_class; + + /* notification signals */ + void (* cal_opened) (CalClientMulti *multi, CalClient *client, CalClientOpenStatus status); + + void (* obj_updated) (CalClientMulti *multi, CalClient *client, const char *uid); + void (* obj_removed) (CalClientMulti *multi, CalClient *client, const char *uid); + + void (* categories_changed) (CalClientMulti *multi, CalClient *client, GPtrArray *categories); + + void (* forget_password) (CalClientMulti *multi, CalClient *client, const char *key); +}; + +GtkType cal_client_multi_get_type (void); + +CalClientMulti *cal_client_multi_new (void); + +void cal_client_multi_add_client (CalClientMulti *multi, CalClient *client); +void cal_client_multi_set_auth_func (CalClientMulti *multi, + CalClientAuthFunc func, + gpointer user_data); + +CalClient *cal_client_multi_open_calendar (CalClientMulti *multi, + const char *str_uri, + gboolean only_if_exists); +CalClient *cal_client_multi_get_client_for_uri (CalClientMulti *multi, + const char *uri); + +int cal_client_multi_get_n_objects (CalClientMulti *multi, CalObjType type); +CalClientGetStatus cal_client_multi_get_object (CalClientMulti *multi, + const char *uid, + CalComponent **comp); +CalClientGetStatus cal_client_multi_get_timezone (CalClientMulti *multi, + const char *tzid, + icaltimezone **zone); +GList *cal_client_multi_get_uids (CalClientMulti *multi, CalObjType type); +GList *cal_client_multi_get_changes (CalClientMulti *multi, + CalObjType type, + const char *change_id); +GList *cal_client_multi_get_objects_in_range (CalClientMulti *multi, + CalObjType type, + time_t start, + time_t end); +GList *cal_client_multi_get_free_busy (CalClientMulti *multi, + GList *users, + time_t start, + time_t end); +void cal_client_multi_generate_instances (CalClientMulti *multi, + CalObjType type, + time_t start, + time_t end, + CalRecurInstanceFn cb, + gpointer cb_data); +GSList *cal_client_multi_get_alarms_in_range (CalClientMulti *multi, + time_t start, time_t end); + +END_GNOME_DECLS + +#endif diff --git a/calendar/cal-client/cal-client.c b/calendar/cal-client/cal-client.c index f0519057d6..e0a37159f5 100644 --- a/calendar/cal-client/cal-client.c +++ b/calendar/cal-client/cal-client.c @@ -1224,56 +1224,86 @@ cal_client_get_objects_in_range (CalClient *client, CalObjType type, time_t star /** * cal_client_get_free_busy * @client:: A calendar client. + * @users: List of users to retrieve free/busy information for. * @start: Start time for query. * @end: End time for query. * - * Gets free/busy information from the calendar server + * Gets free/busy information from the calendar server. + * + * Returns: a GList of VFREEBUSY CalComponents */ -CalClientGetStatus -cal_client_get_free_busy (CalClient *client, time_t start, time_t end, CalComponent **comp) +GList * +cal_client_get_free_busy (CalClient *client, GList *users, + time_t start, time_t end) { CalClientPrivate *priv; CORBA_Environment ev; - CORBA_char *calobj; - icalcomponent *icalcomp; + GNOME_Evolution_Calendar_UserList *corba_list; + GNOME_Evolution_Calendar_CalObjSeq *calobj_list; + GList *l; + GList *comp_list = NULL; + int len, i; - 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, NULL); + g_return_val_if_fail (IS_CAL_CLIENT (client), NULL); 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 (priv->load_state == CAL_CLIENT_LOAD_LOADED, NULL); - g_return_val_if_fail (start != -1 && end != -1, CAL_CLIENT_GET_NOT_FOUND); - g_return_val_if_fail (start <= end, CAL_CLIENT_GET_NOT_FOUND); - g_return_val_if_fail (comp != NULL, CAL_CLIENT_GET_NOT_FOUND); + g_return_val_if_fail (start != -1 && end != -1, NULL); + g_return_val_if_fail (start <= end, NULL); - *comp = NULL; + /* 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); + + for (l = g_list_first (users), i = 0; l; l = l->next, i++) + corba_list->_buffer[i] = CORBA_string_dup ((CORBA_char *) l->data); + + /* call the method on the backend */ CORBA_exception_init (&ev); - calobj = GNOME_Evolution_Calendar_Cal_getFreeBusy (priv->cal, start, end, &ev); - if (ev._major != CORBA_NO_EXCEPTION) { + calobj_list = GNOME_Evolution_Calendar_Cal_getFreeBusy (priv->cal, corba_list, + start, end, &ev); + CORBA_free (corba_list); + if (ev._major != CORBA_NO_EXCEPTION || !calobj_list) { g_message ("cal_client_get_free_busy(): could not get the objects"); CORBA_exception_free (&ev); - return CAL_CLIENT_GET_NOT_FOUND; + return NULL; } - CORBA_exception_free (&ev); - icalcomp = icalparser_parse_string (calobj); - CORBA_free (calobj); - if (!icalcomp) { - return CAL_CLIENT_GET_SYNTAX_ERROR; - } + for (i = 0; i < calobj_list->_length; i++) { + CalComponent *comp; + icalcomponent *icalcomp; + icalcomponent_kind kind; - *comp = cal_component_new (); - if (!cal_component_set_icalcomponent (*comp, icalcomp)) { - icalcomponent_free (icalcomp); - gtk_object_unref (GTK_OBJECT (*comp)); - *comp = NULL; - return CAL_CLIENT_GET_SYNTAX_ERROR; + icalcomp = icalparser_parse_string (calobj_list->_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); + gtk_object_unref (GTK_OBJECT (comp)); + continue; + } + + comp_list = g_list_append (comp_list, comp); + } + else + icalcomponent_free (icalcomp); } - return CAL_CLIENT_GET_SUCCESS; + 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 */ diff --git a/calendar/cal-client/cal-client.h b/calendar/cal-client/cal-client.h index a5facbd1c6..315f05e054 100644 --- a/calendar/cal-client/cal-client.h +++ b/calendar/cal-client/cal-client.h @@ -122,8 +122,8 @@ GList *cal_client_get_changes (CalClient *client, CalObjType type, const char *c GList *cal_client_get_objects_in_range (CalClient *client, CalObjType type, time_t start, time_t end); -CalClientGetStatus cal_client_get_free_busy (CalClient *client, time_t start, time_t end, - CalComponent **comp); +GList *cal_client_get_free_busy (CalClient *client, GList *users, + time_t start, time_t end); void cal_client_generate_instances (CalClient *client, CalObjType type, time_t start, time_t end, diff --git a/calendar/cal-client/client-test.c b/calendar/cal-client/client-test.c index f9c53bb74c..42d933f881 100644 --- a/calendar/cal-client/client-test.c +++ b/calendar/cal-client/client-test.c @@ -134,15 +134,22 @@ cal_opened_cb (CalClient *client, CalClientOpenStatus status, gpointer data) "unknown status value")); if (status == CAL_CLIENT_OPEN_SUCCESS) { - CalComponent *comp; + GList *comp_list; /* get free/busy information */ - cal_client_get_free_busy (client, 0, time (NULL), &comp); - if (IS_CAL_COMPONENT (comp)) { - char *comp_str = cal_component_get_as_string (comp); - gtk_object_unref (GTK_OBJECT (comp)); - cl_printf (client, "Free/Busy -> %s\n", comp_str); - g_free (comp_str); + 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)); + gtk_object_unref (GTK_OBJECT (l->data)); + cl_printf (client, "Free/Busy -> %s\n", comp_str); + g_free (comp_str); + } + g_list_free (comp_list); } g_idle_add (list_uids, client); @@ -225,9 +232,8 @@ main (int argc, char **argv) dir = g_strdup_printf ("%s/evolution/local/Calendar/calendar.ics", g_get_home_dir ()); create_client (&client1, dir, FALSE); - create_client (&client2, "/cvs/evolution/calendar/cal-client/test.ics", TRUE); - g_free (dir); + create_client (&client2, "/cvs/evolution/calendar/cal-client/test.ics", TRUE); bonobo_main (); return 0; diff --git a/calendar/gui/calendar-commands.c b/calendar/gui/calendar-commands.c index 7c510024c3..83693bab25 100644 --- a/calendar/gui/calendar-commands.c +++ b/calendar/gui/calendar-commands.c @@ -332,21 +332,27 @@ publish_freebusy_cmd (BonoboUIComponent *uic, gpointer data, const gchar *path) { GnomeCalendar *gcal; CalClient *client; - CalClientGetStatus status; - CalComponent *comp; - icaltimezone *utc; - time_t start = time (NULL), end; + GList *comp_list; + time_t start, end; gcal = GNOME_CALENDAR (data); - - utc = icaltimezone_get_utc_timezone (); - start = time_day_begin_with_zone (start, utc); - end = time_add_week_with_zone (start, 6, utc); + gnome_calendar_get_current_time_range (gcal, &start, &end); client = gnome_calendar_get_cal_client (gcal); - status = cal_client_get_free_busy (client, start, end, &comp); - if (status == CAL_CLIENT_GET_SUCCESS) - itip_send_comp (CAL_COMPONENT_METHOD_PUBLISH, comp); + /* FIXME: use the "users" parameter */ + comp_list = cal_client_get_free_busy (client, NULL, start, end); + if (comp_list) { + GList *l; + + for (l = comp_list; l; l = l->next) { + CalComponent *comp = CAL_COMPONENT (l->data); + itip_send_comp (CAL_COMPONENT_METHOD_PUBLISH, comp); + + gtk_object_unref (GTK_OBJECT (comp)); + } + + g_free (comp_list); + } } /* Does a queryInterface on the control's parent control frame for the ShellView interface */ diff --git a/calendar/gui/calendar-component.c b/calendar/gui/calendar-component.c index 786aa70003..2e6186974f 100644 --- a/calendar/gui/calendar-component.c +++ b/calendar/gui/calendar-component.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -121,17 +122,35 @@ create_folder (EvolutionShellComponent *shell_component, void *closure) { CORBA_Environment ev; + GnomeVFSURI *uri; - CORBA_exception_init(&ev); - /* FIXME: I don't think we have to do anything to create a calendar - or tasks folder - the '.ics' files are created automatically when - needed. But I'm not sure - Damon. */ - if (!strcmp(type, "calendar") || !strcmp(type, "tasks")) { - GNOME_Evolution_ShellComponentListener_notifyResult(listener, GNOME_Evolution_ShellComponentListener_OK, &ev); - } else { - GNOME_Evolution_ShellComponentListener_notifyResult(listener, GNOME_Evolution_ShellComponentListener_UNSUPPORTED_TYPE, &ev); + CORBA_exception_init (&ev); + + if (strcmp (type, FOLDER_CALENDAR) && strcmp (type, FOLDER_TASKS)) { + GNOME_Evolution_ShellComponentListener_notifyResult ( + listener, + GNOME_Evolution_ShellComponentListener_UNSUPPORTED_TYPE, + &ev); + CORBA_exception_free (&ev); + return; } - CORBA_exception_free(&ev); + + uri = gnome_vfs_uri_new_private (physical_uri, TRUE, TRUE, TRUE); + if (uri) { + /* we don't need to do anything */ + GNOME_Evolution_ShellComponentListener_notifyResult ( + listener, + GNOME_Evolution_ShellComponentListener_OK, &ev); + gnome_vfs_uri_unref (uri); + } + else { + GNOME_Evolution_ShellComponentListener_notifyResult ( + listener, + GNOME_Evolution_ShellComponentListener_INVALID_URI, + &ev); + } + + CORBA_exception_free (&ev); } static void @@ -142,68 +161,91 @@ remove_folder (EvolutionShellComponent *shell_component, void *closure) { CORBA_Environment ev; - const char *file_name; - gchar *path; - int rv; + GnomeVFSURI *uri; + GnomeVFSResult result; + GList *file_list; CORBA_exception_init(&ev); - /* check URI */ - if (strncmp (physical_uri, "file://", 7)) { + /* check type */ + if (strcmp (type, FOLDER_CALENDAR) && strcmp (type, FOLDER_TASKS)) { GNOME_Evolution_ShellComponentListener_notifyResult ( listener, - GNOME_Evolution_ShellComponentListener_INVALID_URI, + GNOME_Evolution_ShellComponentListener_UNSUPPORTED_TYPE, &ev); CORBA_exception_free (&ev); return; } - /* FIXME: check if there are subfolders? */ - - file_name = get_local_file_name_for_folder_type (type); - if (file_name == NULL) { - GNOME_Evolution_ShellComponentListener_notifyResult (listener, - GNOME_Evolution_ShellComponentListener_UNSUPPORTED_TYPE, - &ev); - CORBA_exception_free (&ev); - return; - } - - /* remove the .ics file */ - path = g_concat_dir_and_file (physical_uri + 7, file_name); - rv = unlink (path); - g_free (path); - if (rv == 0) { - /* everything OK; notify the listener */ + /* check URI */ + uri = gnome_vfs_uri_new_private (physical_uri, TRUE, TRUE, TRUE); + if (!uri) { GNOME_Evolution_ShellComponentListener_notifyResult ( listener, - GNOME_Evolution_ShellComponentListener_OK, + GNOME_Evolution_ShellComponentListener_INVALID_URI, &ev); + CORBA_exception_free (&ev); + return; } - else { - if (errno == EACCES || errno == EPERM) - GNOME_Evolution_ShellComponentListener_notifyResult ( - listener, - GNOME_Evolution_ShellComponentListener_PERMISSION_DENIED, - &ev); - else + + /* remove all files in that directory */ + result = gnome_vfs_directory_list_load (&file_list, physical_uri, 0, NULL); + if (result == GNOME_VFS_OK) { + GList *l; + gboolean success = TRUE; + + for (l = file_list; l; l = l->next) { + GnomeVFSFileInfo *file_info; + GnomeVFSURI *tmp_uri; + + /* ignore hidden files */ + file_info = (GnomeVFSFileInfo *) l->data; + if (!file_info || file_info->name[0] == '.') + continue; + + if (file_info->type == GNOME_VFS_FILE_TYPE_DIRECTORY) { + GNOME_Evolution_ShellComponentListener_notifyResult ( + listener, + GNOME_Evolution_ShellComponentListener_HAS_SUBFOLDERS, + &ev); + success = FALSE; + break; + } + + tmp_uri = gnome_vfs_uri_new_private (physical_uri, TRUE, TRUE, TRUE); + tmp_uri = gnome_vfs_uri_append_file_name (tmp_uri, file_info->name); + + result = gnome_vfs_unlink_from_uri (tmp_uri); + gnome_vfs_uri_unref (tmp_uri); + if (result != GNOME_VFS_OK) { + GNOME_Evolution_ShellComponentListener_notifyResult ( + listener, + GNOME_Evolution_ShellComponentListener_PERMISSION_DENIED, + &ev); + success = FALSE; + break; + } + } + + if (success) { GNOME_Evolution_ShellComponentListener_notifyResult ( listener, - GNOME_Evolution_ShellComponentListener_INVALID_URI, /*XXX*/ + GNOME_Evolution_ShellComponentListener_OK, &ev); + } + } + else { + GNOME_Evolution_ShellComponentListener_notifyResult ( + listener, + GNOME_Evolution_ShellComponentListener_PERMISSION_DENIED, + &ev); } - CORBA_exception_free(&ev); -} - -/* callback used from icalparser_parse */ -static char * -get_line_fn (char *s, size_t size, void *data) -{ - FILE *file; + /* free memory */ + gnome_vfs_file_info_list_free (file_list); + gnome_vfs_uri_unref (uri); - file = data; - return fgets (s, size, file); + CORBA_exception_free(&ev); } static void @@ -216,110 +258,139 @@ xfer_folder (EvolutionShellComponent *shell_component, void *closure) { CORBA_Environment ev; - gchar *source_path; - FILE *fin; - icalparser *parser; - icalcomponent *icalcomp; - GnomeVFSHandle *handle; - GnomeVFSURI *uri; - GnomeVFSFileSize out; - char *buf; - const char *file_name; + GnomeVFSURI *src_uri; + GnomeVFSURI *dest_uri; + GnomeVFSResult result; + GList *file_list; + GList *l; + gboolean success = TRUE; CORBA_exception_init (&ev); - /* check URI */ - if (strncmp (source_physical_uri, "file://", 7) - || strncmp (destination_physical_uri, "file://", 7)) { + /* check type */ + if (strcmp (type, FOLDER_CALENDAR) && strcmp (type, FOLDER_TASKS)) { GNOME_Evolution_ShellComponentListener_notifyResult ( listener, - GNOME_Evolution_ShellComponentListener_INVALID_URI, + GNOME_Evolution_ShellComponentListener_UNSUPPORTED_TYPE, &ev); CORBA_exception_free (&ev); return; } - file_name = get_local_file_name_for_folder_type (type); - if (file_name == NULL) { - GNOME_Evolution_ShellComponentListener_notifyResult (listener, - GNOME_Evolution_ShellComponentListener_UNSUPPORTED_TYPE, - &ev); - CORBA_exception_free (&ev); - return; - } - - /* open source and destination files */ - source_path = g_concat_dir_and_file (source_physical_uri + 7, "calendar.ics"); - - fin = fopen (source_path, "r"); - if (!fin) { + /* check URIs */ + src_uri = gnome_vfs_uri_new_private (source_physical_uri, TRUE, TRUE, TRUE); + dest_uri = gnome_vfs_uri_new_private (destination_physical_uri, TRUE, TRUE, TRUE); + if (!src_uri || ! dest_uri) { GNOME_Evolution_ShellComponentListener_notifyResult ( listener, - GNOME_Evolution_ShellComponentListener_PERMISSION_DENIED, - &ev); - g_free (source_path); - CORBA_exception_free (&ev); - return; - } - parser = icalparser_new (); - icalparser_set_gen_data (parser, fin); - icalcomp = icalparser_parse (parser, get_line_fn); - icalparser_free (parser); - if (!icalcomp - || icalcomponent_isa (icalcomp) != ICAL_VCALENDAR_COMPONENT) { - GNOME_Evolution_ShellComponentListener_notifyResult ( - listener, - GNOME_Evolution_ShellComponentListener_PERMISSION_DENIED, + GNOME_Evolution_ShellComponentListener_INVALID_URI, &ev); - fclose (fin); - g_free (source_path); - if (icalcomp) - icalcomponent_free (icalcomp); + gnome_vfs_uri_unref (src_uri); + gnome_vfs_uri_unref (dest_uri); CORBA_exception_free (&ev); return; } - /* now, write the new file out */ - uri = gnome_vfs_uri_new (destination_physical_uri); - if (gnome_vfs_create_uri (&handle, uri, GNOME_VFS_OPEN_WRITE, FALSE, 0666) - != GNOME_VFS_OK) { + gnome_vfs_uri_unref (src_uri); + gnome_vfs_uri_unref (dest_uri); + + /* remove all files in that directory */ + result = gnome_vfs_directory_list_load (&file_list, source_physical_uri, 0, NULL); + if (result != GNOME_VFS_OK) { GNOME_Evolution_ShellComponentListener_notifyResult ( listener, GNOME_Evolution_ShellComponentListener_INVALID_URI, - &ev); - fclose (fin); - g_free (source_path); - icalcomponent_free (icalcomp); + &ev); CORBA_exception_free (&ev); return; } - buf = icalcomponent_as_ical_string (icalcomp); - if (gnome_vfs_write (handle, buf, strlen (buf) * sizeof (char), &out) - != GNOME_VFS_OK) { - GNOME_Evolution_ShellComponentListener_notifyResult ( - listener, - GNOME_Evolution_ShellComponentListener_PERMISSION_DENIED, - &ev); - } - else { - GNOME_Evolution_ShellComponentListener_notifyResult ( - listener, - GNOME_Evolution_ShellComponentListener_OK, - &ev); - } - gnome_vfs_close (handle); - gnome_vfs_uri_unref (uri); - - /* free resources */ - fclose (fin); - - if (remove_source) - unlink (source_path); - - g_free (source_path); - icalcomponent_free (icalcomp); - CORBA_exception_free (&ev); + for (l = file_list; l; l = l->next) { + GnomeVFSFileInfo *file_info; + GnomeVFSHandle *hin; + GnomeVFSHandle *hout; + gpointer buffer; + GnomeVFSFileSize size; + + file_info = (GnomeVFSFileInfo *) l->data; + if (!file_info || file_info->name[0] == '.') + continue; + + /* open source and destination files */ + src_uri = gnome_vfs_uri_new_private (source_physical_uri, TRUE, TRUE, TRUE); + src_uri = gnome_vfs_uri_append_file_name (src_uri, file_info->name); + + result = gnome_vfs_open_uri (&hin, src_uri, GNOME_VFS_OPEN_READ); + gnome_vfs_uri_unref (src_uri); + if (result != GNOME_VFS_OK) { + GNOME_Evolution_ShellComponentListener_notifyResult ( + listener, + GNOME_Evolution_ShellComponentListener_PERMISSION_DENIED, + &ev); + success = FALSE; + break; + } + + dest_uri = gnome_vfs_uri_new_private (destination_physical_uri, TRUE, TRUE, TRUE); + dest_uri = gnome_vfs_uri_append_file_name (dest_uri, file_info->name); + + result = gnome_vfs_create_uri (&hout, dest_uri, GNOME_VFS_OPEN_WRITE, FALSE, 0); + gnome_vfs_uri_unref (dest_uri); + if (result != GNOME_VFS_OK) { + gnome_vfs_close (hin); + GNOME_Evolution_ShellComponentListener_notifyResult ( + listener, + GNOME_Evolution_ShellComponentListener_PERMISSION_DENIED, + &ev); + success = FALSE; + break; + } + + /* write source file to destination file */ + buffer = g_malloc (file_info->size); + result = gnome_vfs_read (hin, buffer, file_info->size, &size); + if (result != GNOME_VFS_OK) { + gnome_vfs_close (hin); + gnome_vfs_close (hout); + g_free (buffer); + + GNOME_Evolution_ShellComponentListener_notifyResult ( + listener, + GNOME_Evolution_ShellComponentListener_PERMISSION_DENIED, + &ev); + success = FALSE; + break; + } + result = gnome_vfs_write (hout, buffer, file_info->size, &size); + if (result != GNOME_VFS_OK) { + gnome_vfs_close (hin); + gnome_vfs_close (hout); + g_free (buffer); + + GNOME_Evolution_ShellComponentListener_notifyResult ( + listener, + GNOME_Evolution_ShellComponentListener_PERMISSION_DENIED, + &ev); + success = FALSE; + break; + } + + /* free memory */ + gnome_vfs_close (hin); + gnome_vfs_close (hout); + g_free (buffer); + } + + if (success) { + GNOME_Evolution_ShellComponentListener_notifyResult ( + listener, + GNOME_Evolution_ShellComponentListener_OK, + &ev); + } + + /* free memory */ + gnome_vfs_file_info_list_free (file_list); + CORBA_exception_free (&ev); } static GList *shells = NULL; diff --git a/calendar/gui/component-factory.c b/calendar/gui/component-factory.c index 786aa70003..2e6186974f 100644 --- a/calendar/gui/component-factory.c +++ b/calendar/gui/component-factory.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -121,17 +122,35 @@ create_folder (EvolutionShellComponent *shell_component, void *closure) { CORBA_Environment ev; + GnomeVFSURI *uri; - CORBA_exception_init(&ev); - /* FIXME: I don't think we have to do anything to create a calendar - or tasks folder - the '.ics' files are created automatically when - needed. But I'm not sure - Damon. */ - if (!strcmp(type, "calendar") || !strcmp(type, "tasks")) { - GNOME_Evolution_ShellComponentListener_notifyResult(listener, GNOME_Evolution_ShellComponentListener_OK, &ev); - } else { - GNOME_Evolution_ShellComponentListener_notifyResult(listener, GNOME_Evolution_ShellComponentListener_UNSUPPORTED_TYPE, &ev); + CORBA_exception_init (&ev); + + if (strcmp (type, FOLDER_CALENDAR) && strcmp (type, FOLDER_TASKS)) { + GNOME_Evolution_ShellComponentListener_notifyResult ( + listener, + GNOME_Evolution_ShellComponentListener_UNSUPPORTED_TYPE, + &ev); + CORBA_exception_free (&ev); + return; } - CORBA_exception_free(&ev); + + uri = gnome_vfs_uri_new_private (physical_uri, TRUE, TRUE, TRUE); + if (uri) { + /* we don't need to do anything */ + GNOME_Evolution_ShellComponentListener_notifyResult ( + listener, + GNOME_Evolution_ShellComponentListener_OK, &ev); + gnome_vfs_uri_unref (uri); + } + else { + GNOME_Evolution_ShellComponentListener_notifyResult ( + listener, + GNOME_Evolution_ShellComponentListener_INVALID_URI, + &ev); + } + + CORBA_exception_free (&ev); } static void @@ -142,68 +161,91 @@ remove_folder (EvolutionShellComponent *shell_component, void *closure) { CORBA_Environment ev; - const char *file_name; - gchar *path; - int rv; + GnomeVFSURI *uri; + GnomeVFSResult result; + GList *file_list; CORBA_exception_init(&ev); - /* check URI */ - if (strncmp (physical_uri, "file://", 7)) { + /* check type */ + if (strcmp (type, FOLDER_CALENDAR) && strcmp (type, FOLDER_TASKS)) { GNOME_Evolution_ShellComponentListener_notifyResult ( listener, - GNOME_Evolution_ShellComponentListener_INVALID_URI, + GNOME_Evolution_ShellComponentListener_UNSUPPORTED_TYPE, &ev); CORBA_exception_free (&ev); return; } - /* FIXME: check if there are subfolders? */ - - file_name = get_local_file_name_for_folder_type (type); - if (file_name == NULL) { - GNOME_Evolution_ShellComponentListener_notifyResult (listener, - GNOME_Evolution_ShellComponentListener_UNSUPPORTED_TYPE, - &ev); - CORBA_exception_free (&ev); - return; - } - - /* remove the .ics file */ - path = g_concat_dir_and_file (physical_uri + 7, file_name); - rv = unlink (path); - g_free (path); - if (rv == 0) { - /* everything OK; notify the listener */ + /* check URI */ + uri = gnome_vfs_uri_new_private (physical_uri, TRUE, TRUE, TRUE); + if (!uri) { GNOME_Evolution_ShellComponentListener_notifyResult ( listener, - GNOME_Evolution_ShellComponentListener_OK, + GNOME_Evolution_ShellComponentListener_INVALID_URI, &ev); + CORBA_exception_free (&ev); + return; } - else { - if (errno == EACCES || errno == EPERM) - GNOME_Evolution_ShellComponentListener_notifyResult ( - listener, - GNOME_Evolution_ShellComponentListener_PERMISSION_DENIED, - &ev); - else + + /* remove all files in that directory */ + result = gnome_vfs_directory_list_load (&file_list, physical_uri, 0, NULL); + if (result == GNOME_VFS_OK) { + GList *l; + gboolean success = TRUE; + + for (l = file_list; l; l = l->next) { + GnomeVFSFileInfo *file_info; + GnomeVFSURI *tmp_uri; + + /* ignore hidden files */ + file_info = (GnomeVFSFileInfo *) l->data; + if (!file_info || file_info->name[0] == '.') + continue; + + if (file_info->type == GNOME_VFS_FILE_TYPE_DIRECTORY) { + GNOME_Evolution_ShellComponentListener_notifyResult ( + listener, + GNOME_Evolution_ShellComponentListener_HAS_SUBFOLDERS, + &ev); + success = FALSE; + break; + } + + tmp_uri = gnome_vfs_uri_new_private (physical_uri, TRUE, TRUE, TRUE); + tmp_uri = gnome_vfs_uri_append_file_name (tmp_uri, file_info->name); + + result = gnome_vfs_unlink_from_uri (tmp_uri); + gnome_vfs_uri_unref (tmp_uri); + if (result != GNOME_VFS_OK) { + GNOME_Evolution_ShellComponentListener_notifyResult ( + listener, + GNOME_Evolution_ShellComponentListener_PERMISSION_DENIED, + &ev); + success = FALSE; + break; + } + } + + if (success) { GNOME_Evolution_ShellComponentListener_notifyResult ( listener, - GNOME_Evolution_ShellComponentListener_INVALID_URI, /*XXX*/ + GNOME_Evolution_ShellComponentListener_OK, &ev); + } + } + else { + GNOME_Evolution_ShellComponentListener_notifyResult ( + listener, + GNOME_Evolution_ShellComponentListener_PERMISSION_DENIED, + &ev); } - CORBA_exception_free(&ev); -} - -/* callback used from icalparser_parse */ -static char * -get_line_fn (char *s, size_t size, void *data) -{ - FILE *file; + /* free memory */ + gnome_vfs_file_info_list_free (file_list); + gnome_vfs_uri_unref (uri); - file = data; - return fgets (s, size, file); + CORBA_exception_free(&ev); } static void @@ -216,110 +258,139 @@ xfer_folder (EvolutionShellComponent *shell_component, void *closure) { CORBA_Environment ev; - gchar *source_path; - FILE *fin; - icalparser *parser; - icalcomponent *icalcomp; - GnomeVFSHandle *handle; - GnomeVFSURI *uri; - GnomeVFSFileSize out; - char *buf; - const char *file_name; + GnomeVFSURI *src_uri; + GnomeVFSURI *dest_uri; + GnomeVFSResult result; + GList *file_list; + GList *l; + gboolean success = TRUE; CORBA_exception_init (&ev); - /* check URI */ - if (strncmp (source_physical_uri, "file://", 7) - || strncmp (destination_physical_uri, "file://", 7)) { + /* check type */ + if (strcmp (type, FOLDER_CALENDAR) && strcmp (type, FOLDER_TASKS)) { GNOME_Evolution_ShellComponentListener_notifyResult ( listener, - GNOME_Evolution_ShellComponentListener_INVALID_URI, + GNOME_Evolution_ShellComponentListener_UNSUPPORTED_TYPE, &ev); CORBA_exception_free (&ev); return; } - file_name = get_local_file_name_for_folder_type (type); - if (file_name == NULL) { - GNOME_Evolution_ShellComponentListener_notifyResult (listener, - GNOME_Evolution_ShellComponentListener_UNSUPPORTED_TYPE, - &ev); - CORBA_exception_free (&ev); - return; - } - - /* open source and destination files */ - source_path = g_concat_dir_and_file (source_physical_uri + 7, "calendar.ics"); - - fin = fopen (source_path, "r"); - if (!fin) { + /* check URIs */ + src_uri = gnome_vfs_uri_new_private (source_physical_uri, TRUE, TRUE, TRUE); + dest_uri = gnome_vfs_uri_new_private (destination_physical_uri, TRUE, TRUE, TRUE); + if (!src_uri || ! dest_uri) { GNOME_Evolution_ShellComponentListener_notifyResult ( listener, - GNOME_Evolution_ShellComponentListener_PERMISSION_DENIED, - &ev); - g_free (source_path); - CORBA_exception_free (&ev); - return; - } - parser = icalparser_new (); - icalparser_set_gen_data (parser, fin); - icalcomp = icalparser_parse (parser, get_line_fn); - icalparser_free (parser); - if (!icalcomp - || icalcomponent_isa (icalcomp) != ICAL_VCALENDAR_COMPONENT) { - GNOME_Evolution_ShellComponentListener_notifyResult ( - listener, - GNOME_Evolution_ShellComponentListener_PERMISSION_DENIED, + GNOME_Evolution_ShellComponentListener_INVALID_URI, &ev); - fclose (fin); - g_free (source_path); - if (icalcomp) - icalcomponent_free (icalcomp); + gnome_vfs_uri_unref (src_uri); + gnome_vfs_uri_unref (dest_uri); CORBA_exception_free (&ev); return; } - /* now, write the new file out */ - uri = gnome_vfs_uri_new (destination_physical_uri); - if (gnome_vfs_create_uri (&handle, uri, GNOME_VFS_OPEN_WRITE, FALSE, 0666) - != GNOME_VFS_OK) { + gnome_vfs_uri_unref (src_uri); + gnome_vfs_uri_unref (dest_uri); + + /* remove all files in that directory */ + result = gnome_vfs_directory_list_load (&file_list, source_physical_uri, 0, NULL); + if (result != GNOME_VFS_OK) { GNOME_Evolution_ShellComponentListener_notifyResult ( listener, GNOME_Evolution_ShellComponentListener_INVALID_URI, - &ev); - fclose (fin); - g_free (source_path); - icalcomponent_free (icalcomp); + &ev); CORBA_exception_free (&ev); return; } - buf = icalcomponent_as_ical_string (icalcomp); - if (gnome_vfs_write (handle, buf, strlen (buf) * sizeof (char), &out) - != GNOME_VFS_OK) { - GNOME_Evolution_ShellComponentListener_notifyResult ( - listener, - GNOME_Evolution_ShellComponentListener_PERMISSION_DENIED, - &ev); - } - else { - GNOME_Evolution_ShellComponentListener_notifyResult ( - listener, - GNOME_Evolution_ShellComponentListener_OK, - &ev); - } - gnome_vfs_close (handle); - gnome_vfs_uri_unref (uri); - - /* free resources */ - fclose (fin); - - if (remove_source) - unlink (source_path); - - g_free (source_path); - icalcomponent_free (icalcomp); - CORBA_exception_free (&ev); + for (l = file_list; l; l = l->next) { + GnomeVFSFileInfo *file_info; + GnomeVFSHandle *hin; + GnomeVFSHandle *hout; + gpointer buffer; + GnomeVFSFileSize size; + + file_info = (GnomeVFSFileInfo *) l->data; + if (!file_info || file_info->name[0] == '.') + continue; + + /* open source and destination files */ + src_uri = gnome_vfs_uri_new_private (source_physical_uri, TRUE, TRUE, TRUE); + src_uri = gnome_vfs_uri_append_file_name (src_uri, file_info->name); + + result = gnome_vfs_open_uri (&hin, src_uri, GNOME_VFS_OPEN_READ); + gnome_vfs_uri_unref (src_uri); + if (result != GNOME_VFS_OK) { + GNOME_Evolution_ShellComponentListener_notifyResult ( + listener, + GNOME_Evolution_ShellComponentListener_PERMISSION_DENIED, + &ev); + success = FALSE; + break; + } + + dest_uri = gnome_vfs_uri_new_private (destination_physical_uri, TRUE, TRUE, TRUE); + dest_uri = gnome_vfs_uri_append_file_name (dest_uri, file_info->name); + + result = gnome_vfs_create_uri (&hout, dest_uri, GNOME_VFS_OPEN_WRITE, FALSE, 0); + gnome_vfs_uri_unref (dest_uri); + if (result != GNOME_VFS_OK) { + gnome_vfs_close (hin); + GNOME_Evolution_ShellComponentListener_notifyResult ( + listener, + GNOME_Evolution_ShellComponentListener_PERMISSION_DENIED, + &ev); + success = FALSE; + break; + } + + /* write source file to destination file */ + buffer = g_malloc (file_info->size); + result = gnome_vfs_read (hin, buffer, file_info->size, &size); + if (result != GNOME_VFS_OK) { + gnome_vfs_close (hin); + gnome_vfs_close (hout); + g_free (buffer); + + GNOME_Evolution_ShellComponentListener_notifyResult ( + listener, + GNOME_Evolution_ShellComponentListener_PERMISSION_DENIED, + &ev); + success = FALSE; + break; + } + result = gnome_vfs_write (hout, buffer, file_info->size, &size); + if (result != GNOME_VFS_OK) { + gnome_vfs_close (hin); + gnome_vfs_close (hout); + g_free (buffer); + + GNOME_Evolution_ShellComponentListener_notifyResult ( + listener, + GNOME_Evolution_ShellComponentListener_PERMISSION_DENIED, + &ev); + success = FALSE; + break; + } + + /* free memory */ + gnome_vfs_close (hin); + gnome_vfs_close (hout); + g_free (buffer); + } + + if (success) { + GNOME_Evolution_ShellComponentListener_notifyResult ( + listener, + GNOME_Evolution_ShellComponentListener_OK, + &ev); + } + + /* free memory */ + gnome_vfs_file_info_list_free (file_list); + CORBA_exception_free (&ev); } static GList *shells = NULL; diff --git a/calendar/gui/e-itip-control.c b/calendar/gui/e-itip-control.c index c6638bfa29..bc528ac8c0 100644 --- a/calendar/gui/e-itip-control.c +++ b/calendar/gui/e-itip-control.c @@ -1193,9 +1193,9 @@ send_freebusy (EItipControl *itip) EItipControlPrivate *priv; CalComponent *comp; CalComponentDateTime datetime; - CalClientGetStatus status; time_t start, end; GtkWidget *dialog; + GList *comp_list; priv = itip->priv; @@ -1204,11 +1204,20 @@ send_freebusy (EItipControl *itip) start = icaltime_as_timet (*datetime.value); cal_component_get_dtend (priv->comp, &datetime); end = icaltime_as_timet (*datetime.value); - status = cal_client_get_free_busy (priv->event_client, start, end, &comp); + comp_list = cal_client_get_free_busy (priv->event_client, NULL, start, end); - if (status == CAL_CLIENT_GET_SUCCESS) { - itip_send_comp (CAL_COMPONENT_METHOD_REPLY, comp); + if (comp_list) { + GList *l; + + for (l = comp_list; l; l = l->next) { + CalComponent *comp = CAL_COMPONENT (l->data); + itip_send_comp (CAL_COMPONENT_METHOD_REPLY, comp); + + gtk_object_unref (GTK_OBJECT (comp)); + } dialog = gnome_ok_dialog (_("Item sent!\n")); + + g_list_free (comp_list); } else { dialog = gnome_warning_dialog (_("The item could not be sent!\n")); } diff --git a/calendar/idl/evolution-calendar.idl b/calendar/idl/evolution-calendar.idl index c236f26649..b3158dc487 100644 --- a/calendar/idl/evolution-calendar.idl +++ b/calendar/idl/evolution-calendar.idl @@ -21,6 +21,7 @@ module Calendar { * iCalendar string. */ typedef string CalObj; + typedef sequence CalObjSeq; /* A unique identifier for a calendar component */ typedef string CalObjUID; @@ -108,6 +109,9 @@ module Calendar { /* Used to represent a list of components plus their triggers */ typedef sequence CalComponentAlarmsSeq; + /* Used to represent users and lists of users */ + typedef string User; + typedef sequence UserList; interface Query; @@ -155,7 +159,7 @@ module Calendar { raises (InvalidRange); /* Returns free/busy objects for the given interval */ - CalObj getFreeBusy (in Time_t start, in Time_t end); + CalObjSeq getFreeBusy (in UserList users, in Time_t start, in Time_t end); /* Gets the alarms for the specified component that trigger in * the specified time range. diff --git a/calendar/pcs/cal-backend-file.c b/calendar/pcs/cal-backend-file.c index fd4e3a2cd0..5649cc39f5 100644 --- a/calendar/pcs/cal-backend-file.c +++ b/calendar/pcs/cal-backend-file.c @@ -92,7 +92,7 @@ static char *cal_backend_file_get_timezone_object (CalBackend *backend, const ch static GList *cal_backend_file_get_uids (CalBackend *backend, CalObjType type); static GList *cal_backend_file_get_objects_in_range (CalBackend *backend, CalObjType type, time_t start, time_t end); -static char *cal_backend_file_get_free_busy (CalBackend *backend, time_t start, time_t end); +static GList *cal_backend_file_get_free_busy (CalBackend *backend, GList *users, time_t start, time_t end); static GNOME_Evolution_Calendar_CalObjChangeSeq *cal_backend_file_get_changes ( CalBackend *backend, CalObjType type, const char *change_id); @@ -1113,16 +1113,16 @@ cal_backend_file_get_objects_in_range (CalBackend *backend, CalObjType type, } /* Get_free_busy handler for the file backend */ -static char * -cal_backend_file_get_free_busy (CalBackend *backend, time_t start, time_t end) +static GList * +cal_backend_file_get_free_busy (CalBackend *backend, GList *users, time_t start, time_t end) { CalBackendFile *cbfile; CalBackendFilePrivate *priv; - icalcomponent *vfb; - char *calobj; - struct icaltimetype itime; GList *uids; GList *l; + icalcomponent *vfb; + char *calobj; + GList *obj_list = NULL; cbfile = CAL_BACKEND_FILE (backend); priv = cbfile->priv; @@ -1131,34 +1131,28 @@ cal_backend_file_get_free_busy (CalBackend *backend, time_t start, time_t end) g_return_val_if_fail (start != -1 && end != -1, NULL); g_return_val_if_fail (start <= end, NULL); - /* create the iCal VFREEBUSY component */ + /* create the (unique) VFREEBUSY object that we'll return */ vfb = icalcomponent_new_vfreebusy (); - itime = icaltime_from_timet (start, 1); - icalcomponent_set_dtstart (vfb, itime); - itime = icaltime_from_timet (end, 1); - icalcomponent_set_dtend (vfb, itime); + icalcomponent_set_dtstart (vfb, icaltime_from_timet (start, 1)); + icalcomponent_set_dtend (vfb, icaltime_from_timet (end, 1)); /* add all objects in the given interval */ uids = cal_backend_get_objects_in_range (CAL_BACKEND (cbfile), CALOBJ_TYPE_ANY, start, end); for (l = uids; l != NULL; l = l->next) { - char *comp_str; + CalComponent *comp; icalcomponent *icalcomp; - icalproperty *icalprop, *prop; + icalparameter *param; + icalproperty *prop; struct icalperiodtype ipt; char *uid = (char *) l->data; - /* FIXME: This looks quite inefficient. It is converting the - component to a string and then parsing it again. It would - be better to use lookup_component(). It needs to handle - timezones as well, so it is probably easier to use the - CalComponent wrapper functions. - Damon. */ - comp_str = cal_backend_get_object (CAL_BACKEND (cbfile), uid); - if (!comp_str) + /* get the component from our internal list */ + comp = lookup_component (cbfile, uid); + if (!comp) continue; - icalcomp = icalparser_parse_string (comp_str); - g_free (comp_str); + icalcomp = cal_component_get_icalcomponent (comp); if (!icalcomp) continue; @@ -1177,17 +1171,22 @@ cal_backend_file_get_free_busy (CalBackend *backend, time_t start, time_t end) ipt.duration = icalcomponent_get_duration (icalcomp); /* add busy information to the vfb component */ - icalprop = icalproperty_new (ICAL_FREEBUSY_PROPERTY); - icalproperty_set_freebusy (icalprop, ipt); - icalcomponent_add_property (vfb, icalprop); - } + prop = icalproperty_new (ICAL_FREEBUSY_PROPERTY); + icalproperty_set_freebusy (prop, ipt); - calobj = g_strdup (icalcomponent_as_ical_string (vfb)); + param = icalparameter_new_fbtype (ICAL_FBTYPE_BUSY); + icalproperty_add_parameter (prop, param); + icalcomponent_add_property (vfb, prop); + } + + calobj = icalcomponent_as_ical_string (vfb); + obj_list = g_list_append (obj_list, g_strdup (calobj)); icalcomponent_free (vfb); + cal_obj_uid_list_free (uids); - return calobj; + return obj_list; } typedef struct diff --git a/calendar/pcs/cal-backend.c b/calendar/pcs/cal-backend.c index b19c141446..20f3a74ee1 100644 --- a/calendar/pcs/cal-backend.c +++ b/calendar/pcs/cal-backend.c @@ -476,15 +476,16 @@ cal_backend_get_objects_in_range (CalBackend *backend, CalObjType type, /** * cal_backend_get_free_busy: * @backend: A calendar backend. + * @users: List of users to get free/busy information for. * @start: Start time for query. * @end: End time for query. * * Gets a free/busy object for the given time interval * - * Return value: a free/busy object + * Return value: a list of CalObj's **/ -char * -cal_backend_get_free_busy (CalBackend *backend, time_t start, time_t end) +GList * +cal_backend_get_free_busy (CalBackend *backend, GList *users, time_t start, time_t end) { g_return_val_if_fail (backend != NULL, NULL); g_return_val_if_fail (IS_CAL_BACKEND (backend), NULL); @@ -492,7 +493,7 @@ cal_backend_get_free_busy (CalBackend *backend, time_t start, time_t end) g_return_val_if_fail (start <= end, NULL); g_assert (CLASS (backend)->get_free_busy != NULL); - return (* CLASS (backend)->get_free_busy) (backend, start, end); + return (* CLASS (backend)->get_free_busy) (backend, users, start, end); } /** diff --git a/calendar/pcs/cal-backend.h b/calendar/pcs/cal-backend.h index 59b5023a7d..1864a08f73 100644 --- a/calendar/pcs/cal-backend.h +++ b/calendar/pcs/cal-backend.h @@ -91,7 +91,7 @@ struct _CalBackendClass { GList *(* get_objects_in_range) (CalBackend *backend, CalObjType type, time_t start, time_t end); - char *(* get_free_busy) (CalBackend *backend, time_t start, time_t end); + GList *(* get_free_busy) (CalBackend *backend, GList *users, time_t start, time_t end); /* Change related virtual methods */ GNOME_Evolution_Calendar_CalObjChangeSeq * (* get_changes) ( @@ -138,7 +138,7 @@ GList *cal_backend_get_uids (CalBackend *backend, CalObjType type); GList *cal_backend_get_objects_in_range (CalBackend *backend, CalObjType type, time_t start, time_t end); -char *cal_backend_get_free_busy (CalBackend *backend, time_t start, time_t end); +GList *cal_backend_get_free_busy (CalBackend *backend, GList *users, time_t start, time_t end); GNOME_Evolution_Calendar_CalObjChangeSeq * cal_backend_get_changes ( CalBackend *backend, CalObjType type, const char *change_id); diff --git a/calendar/pcs/cal.c b/calendar/pcs/cal.c index 213ad35c31..9532e8265a 100644 --- a/calendar/pcs/cal.c +++ b/calendar/pcs/cal.c @@ -233,16 +233,19 @@ impl_Cal_get_objects_in_range (PortableServer_Servant servant, } /* Cal::get_free_busy method */ -static GNOME_Evolution_Calendar_CalObj +static GNOME_Evolution_Calendar_CalObjSeq * impl_Cal_get_free_busy (PortableServer_Servant servant, - GNOME_Evolution_Calendar_Time_t start, - GNOME_Evolution_Calendar_Time_t end, + const GNOME_Evolution_Calendar_UserList *user_list, + const GNOME_Evolution_Calendar_Time_t start, + const GNOME_Evolution_Calendar_Time_t end, CORBA_Environment *ev) { Cal *cal; CalPrivate *priv; time_t t_start, t_end; - char *calobj; + GList *users = NULL; + GList *obj_list; + GNOME_Evolution_Calendar_CalObjSeq *seq; cal = CAL (bonobo_object_from_servant (servant)); priv = cal->priv; @@ -257,20 +260,46 @@ impl_Cal_get_free_busy (PortableServer_Servant servant, return NULL; } - calobj = cal_backend_get_free_busy (priv->backend, t_start, t_end); - if (calobj) { - CORBA_char *calobj_copy; + /* convert the CORBA user list to a GList */ + if (user_list) { + int i; - calobj_copy = CORBA_string_dup (calobj); - g_free (calobj); - return calobj_copy; + for (i = 0; i < user_list->_length; i++) + users = g_list_append (users, user_list->_buffer[i]); + } + + /* call the backend's get_free_busy method */ + obj_list = cal_backend_get_free_busy (priv->backend, users, t_start, t_end); + g_list_free (users); + if (obj_list) { + GList *l; + gint count; + gint n; + + count = g_list_length (obj_list); + + seq = GNOME_Evolution_Calendar_CalObjSeq__alloc (); + CORBA_sequence_set_release (seq, TRUE); + seq->_length = count; + seq->_buffer = CORBA_sequence_GNOME_Evolution_Calendar_CalObj_allocbuf (count); + + for (l = obj_list, n = 0; l; l = l->next, n++) { + gchar *calobj = (gchar *) l->data; + + seq->_buffer[n] = CORBA_string_dup (calobj); + g_free (calobj); + } + + g_list_free (obj_list); + + return seq; } CORBA_exception_set (ev, CORBA_USER_EXCEPTION, - ex_GNOME_Evolution_Calendar_Cal_NotFound, - NULL); + ex_GNOME_Evolution_Calendar_Cal_NotFound, + NULL); - return NULL; + return NULL; } /* Cal::get_alarms_in_range method */ -- cgit v1.2.3