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/cal-client/cal-client-multi.c | 707 +++++++++++++++++++++++++++++++++ 1 file changed, 707 insertions(+) create mode 100644 calendar/cal-client/cal-client-multi.c (limited to 'calendar/cal-client/cal-client-multi.c') 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; +} -- cgit v1.2.3