aboutsummaryrefslogtreecommitdiffstats
path: root/calendar
diff options
context:
space:
mode:
Diffstat (limited to 'calendar')
-rw-r--r--calendar/ChangeLog32
-rw-r--r--calendar/cal-client/Makefile.am2
-rw-r--r--calendar/cal-client/cal-client-multi.c707
-rw-r--r--calendar/cal-client/cal-client-multi.h105
-rw-r--r--calendar/cal-client/cal-client.c86
-rw-r--r--calendar/cal-client/cal-client.h4
-rw-r--r--calendar/cal-client/client-test.c24
-rw-r--r--calendar/gui/calendar-commands.c28
-rw-r--r--calendar/gui/calendar-component.c333
-rw-r--r--calendar/gui/component-factory.c333
-rw-r--r--calendar/gui/e-itip-control.c17
-rw-r--r--calendar/idl/evolution-calendar.idl6
-rw-r--r--calendar/pcs/cal-backend-file.c55
-rw-r--r--calendar/pcs/cal-backend.c9
-rw-r--r--calendar/pcs/cal-backend.h4
-rw-r--r--calendar/pcs/cal.c55
16 files changed, 1436 insertions, 364 deletions
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 <rodrigo@ximian.com>
+
+ * 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 <rodrigo@ximian.com>
+
+ * 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 <damon@ximian.com>
* 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 <rodrigo@ximian.com>
+ *
+ * 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 <config.h>
+#endif
+#include <gtk/gtksignal.h>
+#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 <rodrigo@ximian.com>
+ *
+ * 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 <cal-client/cal-client.h>
+
+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 <libgnomevfs/gnome-vfs-types.h>
#include <libgnomevfs/gnome-vfs-uri.h>
#include <libgnomevfs/gnome-vfs-ops.h>
+#include <libgnomevfs/gnome-vfs-directory.h>
#include <bonobo/bonobo-generic-factory.h>
#include <bonobo/bonobo-context.h>
@@ -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 <libgnomevfs/gnome-vfs-types.h>
#include <libgnomevfs/gnome-vfs-uri.h>
#include <libgnomevfs/gnome-vfs-ops.h>
+#include <libgnomevfs/gnome-vfs-directory.h>
#include <bonobo/bonobo-generic-factory.h>
#include <bonobo/bonobo-context.h>
@@ -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<CalObj> 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<CalComponentAlarms> CalComponentAlarmsSeq;
+ /* Used to represent users and lists of users */
+ typedef string User;
+ typedef sequence<User> 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 */