[evolution-data-server] Modernize ECalBackend's public API.
- From: Matthew Barnes <mbarnes src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server] Modernize ECalBackend's public API.
- Date: Fri, 29 Mar 2013 22:31:37 +0000 (UTC)
commit 91749f78251580a5a6d72a9d77a706e37a1512b2
Author: Matthew Barnes <mbarnes redhat com>
Date: Tue Mar 26 11:57:47 2013 -0400
Modernize ECalBackend's public API.
This leaves ECalBackend and EDataCal engaging in a somewhat ridiculous
kind of ping-pong game for the moment, but the desired public API (in as
much as a backend has a public API) is starting to take shape.
With the scaffolding now in place, we can begin converting backends to
use modern GIO conventions one method at a time, and eventually remove
all the "respond" functions in EDataCal.
calendar/libedata-cal/e-cal-backend.c | 3411 +++++++++++++++++---
calendar/libedata-cal/e-cal-backend.h | 272 ++-
calendar/libedata-cal/e-data-cal.c | 2140 +++++++------
calendar/libedata-cal/e-data-cal.h | 28 +-
configure.ac | 2 +-
.../libedata-cal/libedata-cal-sections.txt | 32 +-
6 files changed, 4405 insertions(+), 1480 deletions(-)
---
diff --git a/calendar/libedata-cal/e-cal-backend.c b/calendar/libedata-cal/e-cal-backend.c
index 5e31a6b..45b8f81 100644
--- a/calendar/libedata-cal/e-cal-backend.c
+++ b/calendar/libedata-cal/e-cal-backend.c
@@ -1,24 +1,19 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/* Evolution calendar - generic backend class
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- * Authors: Federico Mena-Quintero <federico ximian com>
- * JP Rosevear <jpr ximian com>
- * Rodrigo Moya <rodrigo ximian com>
+/*
+ * e-cal-backend.c
*
* This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
- * License as published by the Free Software Foundation.
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
*
* 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 Lesser General Public License for more details.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
*
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <config.h>
@@ -35,9 +30,10 @@
#define EDC_ERROR(_code) e_data_cal_create_error (_code, NULL)
#define EDC_NOT_OPENED_ERROR e_data_cal_create_error (NotOpened, NULL)
+typedef struct _AsyncContext AsyncContext;
+typedef struct _DispatchNode DispatchNode;
typedef struct _SignalClosure SignalClosure;
-/* Private part of the CalBackend structure */
struct _ECalBackendPrivate {
ESourceRegistry *registry;
@@ -56,6 +52,47 @@ struct _ECalBackendPrivate {
GHashTable *zone_cache;
GMutex zone_cache_lock;
+
+ GMutex operation_lock;
+ GHashTable *operation_ids;
+ GQueue pending_operations;
+ guint32 next_operation_id;
+ GSimpleAsyncResult *blocked;
+};
+
+struct _AsyncContext {
+ /* Inputs */
+ gchar *uid;
+ gchar *rid;
+ gchar *alarm_uid;
+ gchar *calobj;
+ gchar *query;
+ gchar *tzid;
+ gchar *tzobject;
+ ECalObjModType mod;
+ const gchar *prop_name;
+ time_t start;
+ time_t end;
+ GSList *compid_list;
+ GSList *string_list;
+
+ /* Outputs */
+ GQueue result_queue;
+
+ /* One of these should point to result_queue
+ * so any leftover resources can be released. */
+ GQueue *object_queue;
+ GQueue *string_queue;
+};
+
+struct _DispatchNode {
+ /* This is the dispatch function
+ * that invokes the class method. */
+ GSimpleAsyncThreadFunc dispatch_func;
+ gboolean blocking_operation;
+
+ GSimpleAsyncResult *simple;
+ GCancellable *cancellable;
};
struct _SignalClosure {
@@ -63,7 +100,6 @@ struct _SignalClosure {
icaltimezone *cached_zone;
};
-/* Property IDs */
enum {
PROP_0,
PROP_CACHE_DIR,
@@ -92,6 +128,47 @@ G_DEFINE_TYPE_WITH_CODE (
e_cal_backend_timezone_cache_init))
static void
+async_context_free (AsyncContext *async_context)
+{
+ GQueue *queue;
+
+ g_free (async_context->uid);
+ g_free (async_context->rid);
+ g_free (async_context->alarm_uid);
+ g_free (async_context->calobj);
+ g_free (async_context->query);
+ g_free (async_context->tzid);
+ g_free (async_context->tzobject);
+
+ g_slist_free_full (
+ async_context->compid_list,
+ (GDestroyNotify) e_cal_component_free_id);
+
+ g_slist_free_full (
+ async_context->string_list,
+ (GDestroyNotify) g_free);
+
+ queue = async_context->object_queue;
+ while (queue != NULL && !g_queue_is_empty (queue))
+ g_object_unref (g_queue_pop_head (queue));
+
+ queue = async_context->string_queue;
+ while (queue != NULL && !g_queue_is_empty (queue))
+ g_free (g_queue_pop_head (queue));
+
+ g_slice_free (AsyncContext, async_context);
+}
+
+static void
+dispatch_node_free (DispatchNode *dispatch_node)
+{
+ g_clear_object (&dispatch_node->simple);
+ g_clear_object (&dispatch_node->cancellable);
+
+ g_slice_free (DispatchNode, dispatch_node);
+}
+
+static void
signal_closure_free (SignalClosure *signal_closure)
{
g_weak_ref_set (&signal_closure->backend, NULL);
@@ -109,6 +186,143 @@ cal_backend_free_zone (icaltimezone *zone)
}
static void
+cal_backend_push_operation (ECalBackend *backend,
+ GSimpleAsyncResult *simple,
+ GCancellable *cancellable,
+ gboolean blocking_operation,
+ GSimpleAsyncThreadFunc dispatch_func)
+{
+ DispatchNode *node;
+
+ g_return_if_fail (G_IS_SIMPLE_ASYNC_RESULT (simple));
+ g_return_if_fail (dispatch_func != NULL);
+
+ g_mutex_lock (&backend->priv->operation_lock);
+
+ node = g_slice_new0 (DispatchNode);
+ node->dispatch_func = dispatch_func;
+ node->blocking_operation = blocking_operation;
+ node->simple = g_object_ref (simple);
+
+ if (G_IS_CANCELLABLE (cancellable))
+ node->cancellable = g_object_ref (cancellable);
+
+ g_queue_push_tail (&backend->priv->pending_operations, node);
+
+ g_mutex_unlock (&backend->priv->operation_lock);
+}
+
+static gboolean
+cal_backend_dispatch_thread (GIOSchedulerJob *job,
+ GCancellable *cancellable,
+ gpointer user_data)
+{
+ DispatchNode *node = user_data;
+ GError *error = NULL;
+
+ if (g_cancellable_set_error_if_cancelled (cancellable, &error)) {
+ g_simple_async_result_take_error (node->simple, error);
+ g_simple_async_result_complete_in_idle (node->simple);
+ } else {
+ GAsyncResult *result;
+ GObject *source_object;
+
+ result = G_ASYNC_RESULT (node->simple);
+ source_object = g_async_result_get_source_object (result);
+ node->dispatch_func (node->simple, source_object, cancellable);
+ g_object_unref (source_object);
+ }
+
+ return FALSE;
+}
+
+static gboolean
+cal_backend_dispatch_next_operation (ECalBackend *backend)
+{
+ DispatchNode *node;
+
+ g_mutex_lock (&backend->priv->operation_lock);
+
+ /* We can't dispatch additional operations
+ * while a blocking operation is in progress. */
+ if (backend->priv->blocked != NULL) {
+ g_mutex_unlock (&backend->priv->operation_lock);
+ return FALSE;
+ }
+
+ /* Pop the next DispatchNode off the queue. */
+ node = g_queue_pop_head (&backend->priv->pending_operations);
+ if (node == NULL) {
+ g_mutex_unlock (&backend->priv->operation_lock);
+ return FALSE;
+ }
+
+ /* If this a blocking operation, block any
+ * further dispatching until this finishes. */
+ if (node->blocking_operation)
+ backend->priv->blocked = g_object_ref (node->simple);
+
+ g_mutex_unlock (&backend->priv->operation_lock);
+
+ g_io_scheduler_push_job (
+ cal_backend_dispatch_thread,
+ node, (GDestroyNotify) dispatch_node_free,
+ G_PRIORITY_DEFAULT,
+ node->cancellable);
+
+ return TRUE;
+}
+
+static guint32
+cal_backend_stash_operation (ECalBackend *backend,
+ GSimpleAsyncResult *simple)
+{
+ guint32 opid;
+
+ g_mutex_lock (&backend->priv->operation_lock);
+
+ if (backend->priv->next_operation_id == 0)
+ backend->priv->next_operation_id = 1;
+
+ opid = backend->priv->next_operation_id++;
+
+ g_hash_table_insert (
+ backend->priv->operation_ids,
+ GUINT_TO_POINTER (opid),
+ g_object_ref (simple));
+
+ g_mutex_unlock (&backend->priv->operation_lock);
+
+ return opid;
+}
+
+static GSimpleAsyncResult *
+cal_backend_claim_operation (ECalBackend *backend,
+ guint32 opid)
+{
+ GSimpleAsyncResult *simple;
+
+ g_return_val_if_fail (opid > 0, NULL);
+
+ g_mutex_lock (&backend->priv->operation_lock);
+
+ simple = g_hash_table_lookup (
+ backend->priv->operation_ids,
+ GUINT_TO_POINTER (opid));
+
+ if (simple != NULL) {
+ /* Steal the hash table's reference. */
+ g_hash_table_steal (
+ backend->priv->operation_ids,
+ GUINT_TO_POINTER (opid));
+ }
+
+ g_mutex_unlock (&backend->priv->operation_lock);
+
+ return simple;
+}
+
+static void
cal_backend_set_default_cache_dir (ECalBackend *backend)
{
ESource *source;
@@ -333,6 +547,13 @@ cal_backend_dispose (GObject *object)
g_clear_object (&priv->registry);
g_clear_object (&priv->data_cal);
+ g_hash_table_remove_all (priv->operation_ids);
+
+ while (!g_queue_is_empty (&priv->pending_operations))
+ g_object_unref (g_queue_pop_head (&priv->pending_operations));
+
+ g_clear_object (&priv->blocked);
+
/* Chain up to parent's dispose() method. */
G_OBJECT_CLASS (e_cal_backend_parent_class)->dispose (object);
}
@@ -352,6 +573,9 @@ cal_backend_finalize (GObject *object)
g_free (priv->cache_dir);
+ g_mutex_clear (&priv->operation_lock);
+ g_hash_table_destroy (priv->operation_ids);
+
/* Chain up to parent's finalize() method. */
G_OBJECT_CLASS (e_cal_backend_parent_class)->finalize (object);
}
@@ -651,6 +875,14 @@ e_cal_backend_init (ECalBackend *backend)
backend->priv->zone_cache = zone_cache;
g_mutex_init (&backend->priv->zone_cache_lock);
+
+ g_mutex_init (&backend->priv->operation_lock);
+
+ backend->priv->operation_ids = g_hash_table_new_full (
+ (GHashFunc) g_direct_hash,
+ (GEqualFunc) g_direct_equal,
+ (GDestroyNotify) NULL,
+ (GDestroyNotify) g_object_unref);
}
/**
@@ -700,7 +932,7 @@ e_cal_backend_ref_data_cal (ECalBackend *backend)
}
/**
- * e_cal_backend_set_data_book:
+ * e_cal_backend_set_data_cal:
* @backend: an #ECalBackend
* @data_cal: an #EDataCal
*
@@ -933,42 +1165,191 @@ e_cal_backend_create_cache_filename (ECalBackend *backend,
const gchar *filename,
gint fileindex)
{
+ const gchar *cache_dir;
+
g_return_val_if_fail (backend != NULL, NULL);
g_return_val_if_fail (E_IS_CAL_BACKEND (backend), NULL);
- return e_filename_mkdir_encoded (e_cal_backend_get_cache_dir (backend), uid, filename, fileindex);
+ cache_dir = e_cal_backend_get_cache_dir (backend);
+
+ return e_filename_mkdir_encoded (cache_dir, uid, filename, fileindex);
+}
+
+/**
+ * e_cal_backend_get_backend_property_sync:
+ * @backend: an #ECalBackend
+ * @prop_name: a backend property name
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Obtains the value of the backend property named @prop_name.
+ *
+ * Despite appearances, this function does not actually block. So the
+ * @cancellable can safely be %NULL. If can, however, return an error
+ * if @prop_name is not recognized.
+ *
+ * The returned string must be freed with g_free() when finished with it.
+ *
+ * Returns: the value for @prop_name
+ *
+ * Since: 3.10
+ **/
+gchar *
+e_cal_backend_get_backend_property_sync (ECalBackend *backend,
+ const gchar *prop_name,
+ GCancellable *cancellable,
+ GError **error)
+{
+ EAsyncClosure *closure;
+ GAsyncResult *result;
+ gchar *prop_value;
+
+ g_return_val_if_fail (E_IS_CAL_BACKEND (backend), NULL);
+ g_return_val_if_fail (prop_name != NULL, NULL);
+
+ closure = e_async_closure_new ();
+
+ e_cal_backend_get_backend_property (
+ backend, prop_name, cancellable,
+ e_async_closure_callback, closure);
+
+ result = e_async_closure_wait (closure);
+
+ prop_value = e_cal_backend_get_backend_property_finish (
+ backend, result, error);
+
+ e_async_closure_free (closure);
+
+ return prop_value;
+}
+
+/* Helper for e_cal_backend_get_backend_property() */
+static void
+cal_backend_get_backend_property_thread (GSimpleAsyncResult *simple,
+ GObject *source_object,
+ GCancellable *cancellable)
+{
+ ECalBackend *backend;
+ ECalBackendClass *class;
+ EDataCal *data_cal;
+ AsyncContext *async_context;
+ guint32 opid;
+
+ backend = E_CAL_BACKEND (source_object);
+
+ class = E_CAL_BACKEND_GET_CLASS (backend);
+ g_return_if_fail (class->get_backend_property != NULL);
+
+ data_cal = e_cal_backend_ref_data_cal (backend);
+ g_return_if_fail (data_cal != NULL);
+
+ async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+ opid = cal_backend_stash_operation (backend, simple);
+
+ class->get_backend_property (
+ backend, data_cal, opid, cancellable,
+ async_context->prop_name);
+
+ g_object_unref (data_cal);
}
/**
* e_cal_backend_get_backend_property:
* @backend: an #ECalBackend
- * @cal: an #EDataCal
- * @opid: the ID to use for this operation
- * @cancellable: a #GCancellable for the operation
- * @prop_name: property name to get value of; cannot be NULL
+ * @prop_name: a backend property name
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied
+ * @user_data: data to pass to the callback function
*
- * Calls the get_backend_property method on the given backend.
- * This might be finished with e_data_cal_respond_get_backend_property().
- * Default implementation takes care of common properties and returns
- * an 'unsupported' error for any unknown properties. The subclass may
- * always call this default implementation for properties which fetching
- * it doesn't overwrite.
+ * Asynchronously obtains the value of the backend property named @prop_name.
*
- * Since: 3.2
+ * Despite appearances, e_cal_backend_get_backend_property_sync() does not
+ * actually block, and is more convenient than this function. This function
+ * exists for the moment merely to invoke the class method and collect the
+ * result from #EDataCal.
+ *
+ * When the operation is finished, @callback will be called. You can then
+ * call e_cal_backend_get_backend_property_finish() to get the result of
+ * the operation.
+ *
+ * Since: 3.10
**/
void
e_cal_backend_get_backend_property (ECalBackend *backend,
- EDataCal *cal,
- guint32 opid,
+ const gchar *prop_name,
GCancellable *cancellable,
- const gchar *prop_name)
+ GAsyncReadyCallback callback,
+ gpointer user_data)
{
- g_return_if_fail (backend != NULL);
+ GSimpleAsyncResult *simple;
+ AsyncContext *async_context;
+
g_return_if_fail (E_IS_CAL_BACKEND (backend));
g_return_if_fail (prop_name != NULL);
- g_return_if_fail (E_CAL_BACKEND_GET_CLASS (backend)->get_backend_property != NULL);
- (* E_CAL_BACKEND_GET_CLASS (backend)->get_backend_property) (backend, cal, opid, cancellable,
prop_name);
+ async_context = g_slice_new0 (AsyncContext);
+ async_context->prop_name = g_intern_string (prop_name);
+ async_context->string_queue = &async_context->result_queue;
+
+ simple = g_simple_async_result_new (
+ G_OBJECT (backend), callback, user_data,
+ e_cal_backend_get_backend_property);
+
+ g_simple_async_result_set_check_cancellable (simple, cancellable);
+
+ g_simple_async_result_set_op_res_gpointer (
+ simple, async_context, (GDestroyNotify) async_context_free);
+
+ cal_backend_push_operation (
+ backend, simple, cancellable, FALSE,
+ cal_backend_get_backend_property_thread);
+
+ cal_backend_dispatch_next_operation (backend);
+
+ g_object_unref (simple);
+}
+
+/**
+ * e_cal_backend_get_backend_property_finish:
+ * @backend: an #ECalBackend
+ * @result: a #GAsyncResult
+ * @error: return location for a #GError, or %NULL
+ *
+ * Finishes the operation started with e_cal_backend_get_backend_property().
+ *
+ * The returned string must be freed with g_free() when finished with it.
+ *
+ * Returns: the requested property value
+ *
+ * Since: 3.10
+ **/
+gchar *
+e_cal_backend_get_backend_property_finish (ECalBackend *backend,
+ GAsyncResult *result,
+ GError **error)
+{
+ GSimpleAsyncResult *simple;
+ AsyncContext *async_context;
+ gchar *prop_value;
+
+ g_return_val_if_fail (
+ g_simple_async_result_is_valid (
+ result, G_OBJECT (backend),
+ e_cal_backend_get_backend_property), NULL);
+
+ simple = G_SIMPLE_ASYNC_RESULT (result);
+ async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+ if (g_simple_async_result_propagate_error (simple, error))
+ return NULL;
+
+ prop_value = g_queue_pop_head (&async_context->result_queue);
+ g_return_val_if_fail (prop_value != NULL, NULL);
+
+ g_warn_if_fail (g_queue_is_empty (&async_context->result_queue));
+
+ return prop_value;
}
/**
@@ -1070,492 +1451,2692 @@ e_cal_backend_list_views (ECalBackend *backend)
}
/**
- * e_cal_backend_open:
+ * e_cal_backend_open_sync:
* @backend: an #ECalBackend
- * @cal: an #EDataCal
- * @opid: the ID to use for this operation
- * @cancellable: a #GCancellable for the operation
- * @only_if_exists: Whether the calendar should be opened only if it already
- * exists. If FALSE, a new calendar will be created when the specified @uri
- * does not exist.
- *
- * Opens a calendar backend with data from a calendar stored at the specified URI.
- * This might be finished with e_data_cal_respond_open() or e_cal_backend_respond_opened(),
- * though the overall opening phase finishes only after call
- * of e_cal_backend_notify_opened() after which call the backend
- * is either fully opened (including authentication against (remote)
- * server/storage) or an error was encountered during this opening phase.
- * 'opened' and 'opening' properties are updated automatically.
- * The backend refuses all other operations until the opening phase is finished.
- *
- * The e_cal_backend_notify_opened() is called either from this function
- * or from e_cal_backend_authenticate_user(), or after necessary steps
- * initiated by these two functions.
- *
- * The opening phase usually works like this:
- * 1) client requests open for the backend
- * 2) server receives this request and calls e_cal_backend_open() - the opening phase begun
- * 3) either the backend is opened during this call, and notifies client
- * with e_cal_backend_notify_opened() about that. This is usually
- * for local backends; their opening phase is finished
- * 4) or the backend requires authentication, thus it notifies client
- * about that with e_cal_backend_notify_auth_required() and is
- * waiting for credentials, which will be received from client
- * by e_cal_backend_authenticate_user() call. Backend's opening
- * phase is still running in this case, thus it doesn't call
- * e_cal_backend_notify_opened() within e_cal_backend_open() call.
- * 5) when backend receives credentials in e_cal_backend_authenticate_user()
- * then it tries to authenticate against a server/storage with them
- * and only after it knows result of the authentication, whether user
- * was or wasn't authenticated, it notifies client with the result
- * by e_cal_backend_notify_opened() and it's opening phase is
- * finished now. If there was no error returned then the backend is
- * considered opened, otherwise it's considered closed. Use AuthenticationFailed
- * error when the given credentials were rejected by the server/store, which
- * will result in a re-prompt on the client side, otherwise use AuthenticationRequired
- * if there was anything wrong with the given credentials. Set error's
- * message to a reason for a re-prompt, it'll be shown to a user.
- * 6) client checks error returned from e_cal_backend_notify_opened() and
- * reprompts for a password if it was AuthenticationFailed. Otherwise
- * considers backend opened based on the error presence (no error means success).
- *
- * In any case, the call of e_cal_backend_open() should be always finished
- * with e_data_cal_respond_open(), which has no influence on the opening phase,
- * or alternatively with e_cal_backend_respond_opened(). Never use authentication
- * errors in e_data_cal_respond_open() to notify the client the authentication is
- * required, there is e_cal_backend_notify_auth_required() for this.
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * "Opens" the @backend. Opening a backend is something of an outdated
+ * concept, but the operation is hanging around for a little while longer.
+ * This usually involves some custom initialization logic, and testing of
+ * remote authentication if applicable.
+ *
+ * If an error occurs, the function will set @error and return %FALSE.
+ *
+ * Returns: %TRUE on success, %FALSE on failure
+ *
+ * Since: 3.10
**/
-void
-e_cal_backend_open (ECalBackend *backend,
- EDataCal *cal,
- guint32 opid,
- GCancellable *cancellable,
- gboolean only_if_exists)
+gboolean
+e_cal_backend_open_sync (ECalBackend *backend,
+ GCancellable *cancellable,
+ GError **error)
{
- g_return_if_fail (backend != NULL);
- g_return_if_fail (E_IS_CAL_BACKEND (backend));
- g_return_if_fail (E_CAL_BACKEND_GET_CLASS (backend)->open != NULL);
+ EAsyncClosure *closure;
+ GAsyncResult *result;
+ gboolean success;
+
+ g_return_val_if_fail (E_IS_CAL_BACKEND (backend), FALSE);
+
+ closure = e_async_closure_new ();
+
+ e_cal_backend_open (
+ backend, cancellable,
+ e_async_closure_callback, closure);
+
+ result = e_async_closure_wait (closure);
+
+ success = e_cal_backend_open_finish (backend, result, error);
+
+ e_async_closure_free (closure);
+
+ return success;
+}
+
+/* Helper for e_cal_backend_open() */
+static void
+cal_backend_open_thread (GSimpleAsyncResult *simple,
+ GObject *source_object,
+ GCancellable *cancellable)
+{
+ ECalBackend *backend;
+ ECalBackendClass *class;
+ EDataCal *data_cal;
+
+ backend = E_CAL_BACKEND (source_object);
+
+ class = E_CAL_BACKEND_GET_CLASS (backend);
+ g_return_if_fail (class->open != NULL);
+
+ data_cal = e_cal_backend_ref_data_cal (backend);
+ g_return_if_fail (data_cal != NULL);
if (e_cal_backend_is_opened (backend)) {
- e_data_cal_respond_open (cal, opid, NULL);
+ g_simple_async_result_complete_in_idle (simple);
+
} else {
- (* E_CAL_BACKEND_GET_CLASS (backend)->open) (backend, cal, opid, cancellable, only_if_exists);
+ guint32 opid;
+
+ opid = cal_backend_stash_operation (backend, simple);
+
+ class->open (backend, data_cal, opid, cancellable, FALSE);
}
+
+ g_object_unref (data_cal);
}
/**
- * e_cal_backend_refresh:
+ * e_cal_backend_open:
* @backend: an #ECalBackend
- * @cal: an #EDataCal
- * @opid: the ID to use for this operation
- * @cancellable: a #GCancellable for the operation
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied
+ * @user_data: data to pass to the callback function
+ *
+ * Asynchronously "opens" the @backend. Opening a backend is something of
+ * an outdated concept, but the operation is hanging around for a little
+ * while longer. This usually involves some custom initialization logic,
+ * and testing of remote authentication if applicable.
*
- * Refreshes the calendar being accessed by the given backend.
- * This might be finished with e_data_cal_respond_refresh(),
- * and it might be called as soon as possible; it doesn't mean
- * that the refreshing is done after calling that, the backend
- * is only notifying client whether it started the refresh process
- * or not.
+ * When the operation is finished, @callback will be called. You can then
+ * call e_cal_backend_open_finish() to get the result of the operation.
*
- * Since: 2.30
+ * Since: 3.10
**/
void
-e_cal_backend_refresh (ECalBackend *backend,
- EDataCal *cal,
- guint32 opid,
- GCancellable *cancellable)
+e_cal_backend_open (ECalBackend *backend,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
{
- g_return_if_fail (backend != NULL);
+ GSimpleAsyncResult *simple;
+
g_return_if_fail (E_IS_CAL_BACKEND (backend));
- if (!E_CAL_BACKEND_GET_CLASS (backend)->refresh)
- e_data_cal_respond_refresh (cal, opid, EDC_ERROR (UnsupportedMethod));
- else if (!e_cal_backend_is_opened (backend))
- e_data_cal_respond_refresh (cal, opid, EDC_NOT_OPENED_ERROR);
- else
- (* E_CAL_BACKEND_GET_CLASS (backend)->refresh) (backend, cal, opid, cancellable);
+ simple = g_simple_async_result_new (
+ G_OBJECT (backend), callback,
+ user_data, e_cal_backend_open);
+
+ g_simple_async_result_set_check_cancellable (simple, cancellable);
+
+ cal_backend_push_operation (
+ backend, simple, cancellable, TRUE,
+ cal_backend_open_thread);
+
+ cal_backend_dispatch_next_operation (backend);
+
+ g_object_unref (simple);
}
/**
- * e_cal_backend_get_object:
+ * e_cal_backend_open_finish:
* @backend: an #ECalBackend
- * @cal: an #EDataCal
- * @opid: the ID to use for this operation
- * @cancellable: a #GCancellable for the operation
- * @uid: Unique identifier for a calendar object.
- * @rid: ID for the object's recurrence to get.
+ * @result: a #GAsyncResult
+ * @error: return location for a #GError, or %NULL
+ *
+ * Finishes the operation started with e_cal_backend_open().
*
- * Queries a calendar backend for a calendar object based on its unique
- * identifier and its recurrence ID (if a recurrent appointment).
- * This might be finished with e_data_cal_respond_get_object().
+ * If an error occurred, the function will set @error and return %FALSE.
+ *
+ * Returns: %TRUE on success, %FALSE on failure
+ *
+ * Since: 3.10
**/
-void
-e_cal_backend_get_object (ECalBackend *backend,
- EDataCal *cal,
- guint32 opid,
- GCancellable *cancellable,
- const gchar *uid,
- const gchar *rid)
+gboolean
+e_cal_backend_open_finish (ECalBackend *backend,
+ GAsyncResult *result,
+ GError **error)
{
- g_return_if_fail (backend != NULL);
- g_return_if_fail (E_IS_CAL_BACKEND (backend));
- g_return_if_fail (uid != NULL);
- g_return_if_fail (E_CAL_BACKEND_GET_CLASS (backend)->get_object != NULL);
-
- if (!e_cal_backend_is_opened (backend))
- e_data_cal_respond_get_object (cal, opid, EDC_NOT_OPENED_ERROR, NULL);
- else
- (* E_CAL_BACKEND_GET_CLASS (backend)->get_object) (backend, cal, opid, cancellable, uid, rid);
+ GSimpleAsyncResult *simple;
+
+ g_return_val_if_fail (
+ g_simple_async_result_is_valid (
+ result, G_OBJECT (backend),
+ e_cal_backend_open), FALSE);
+
+ simple = G_SIMPLE_ASYNC_RESULT (result);
+
+ /* This operation blocks, so we need to let waiting operations
+ * through. (FIXME Centralize this for any blocking operation.) */
+ g_mutex_lock (&backend->priv->operation_lock);
+ if (backend->priv->blocked == simple)
+ g_clear_object (&backend->priv->blocked);
+ g_mutex_unlock (&backend->priv->operation_lock);
+ while (cal_backend_dispatch_next_operation (backend))
+ ;
+
+ /* Assume success unless a GError is set. */
+ return !g_simple_async_result_propagate_error (simple, error);
}
/**
- * e_cal_backend_get_object_list:
+ * e_cal_backend_refresh_sync:
* @backend: an #ECalBackend
- * @cal: an #EDataCal
- * @opid: the ID to use for this operation
- * @cancellable: a #GCancellable for the operation
- * @sexp: Expression to search for.
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Initiates a refresh for @backend, if the @backend supports refreshing.
+ * The actual refresh operation completes on its own time. This function
+ * merely initiates the operation.
+ *
+ * If an error occrs while initiating the refresh, the function will set
+ * @error and return %FALSE. If the @backend does not support refreshing,
+ * the function will set an %UnsupportedMethod error and return %FALSE.
+ *
+ * Returns: %TRUE on success, %FALSE on failure
*
- * Calls the get_object_list method on the given backend.
- * This might be finished with e_data_cal_respond_get_object_list().
+ * Since: 3.10
**/
-void
-e_cal_backend_get_object_list (ECalBackend *backend,
- EDataCal *cal,
- guint32 opid,
- GCancellable *cancellable,
- const gchar *sexp)
+gboolean
+e_cal_backend_refresh_sync (ECalBackend *backend,
+ GCancellable *cancellable,
+ GError **error)
{
- g_return_if_fail (backend != NULL);
- g_return_if_fail (E_IS_CAL_BACKEND (backend));
- g_return_if_fail (E_CAL_BACKEND_GET_CLASS (backend)->get_object_list != NULL);
+ EAsyncClosure *closure;
+ GAsyncResult *result;
+ gboolean success;
- if (!e_cal_backend_is_opened (backend))
- e_data_cal_respond_get_object_list (cal, opid, EDC_NOT_OPENED_ERROR, NULL);
- else
- (* E_CAL_BACKEND_GET_CLASS (backend)->get_object_list) (backend, cal, opid, cancellable,
sexp);
+ g_return_val_if_fail (E_IS_CAL_BACKEND (backend), FALSE);
+
+ closure = e_async_closure_new ();
+
+ e_cal_backend_refresh (
+ backend, cancellable,
+ e_async_closure_callback, closure);
+
+ result = e_async_closure_wait (closure);
+
+ success = e_cal_backend_refresh_finish (backend, result, error);
+
+ e_async_closure_free (closure);
+
+ return success;
+}
+
+/* Helper for e_cal_backend_refresh() */
+static void
+cal_backend_refresh_thread (GSimpleAsyncResult *simple,
+ GObject *source_object,
+ GCancellable *cancellable)
+{
+ ECalBackend *backend;
+ ECalBackendClass *class;
+ EDataCal *data_cal;
+
+ backend = E_CAL_BACKEND (source_object);
+
+ class = E_CAL_BACKEND_GET_CLASS (backend);
+
+ data_cal = e_cal_backend_ref_data_cal (backend);
+ g_return_if_fail (data_cal != NULL);
+
+ if (class->refresh == NULL) {
+ g_simple_async_result_set_error (
+ simple, E_DATA_CAL_ERROR,
+ UnsupportedMethod,
+ "%s", e_data_cal_status_to_string (
+ UnsupportedMethod));
+ g_simple_async_result_complete_in_idle (simple);
+
+ } else if (!e_cal_backend_is_opened (backend)) {
+ g_simple_async_result_set_error (
+ simple, E_DATA_CAL_ERROR,
+ NotOpened,
+ "%s", e_data_cal_status_to_string (
+ NotOpened));
+ g_simple_async_result_complete_in_idle (simple);
+
+ } else {
+ guint32 opid;
+
+ opid = cal_backend_stash_operation (backend, simple);
+
+ class->refresh (backend, data_cal, opid, cancellable);
+ }
+
+ g_object_unref (data_cal);
}
/**
- * e_cal_backend_get_free_busy:
+ * e_cal_backend_refresh:
* @backend: an #ECalBackend
- * @cal: an #EDataCal
- * @opid: the ID to use for this operation
- * @cancellable: a #GCancellable for the operation
- * @users: List of users to get free/busy information for.
- * @start: Start time for query.
- * @end: End time for query.
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied
+ * @user_data: data to pass to the callback function
+ *
+ * Asynchronously initiates a refresh for @backend, if the @backend supports
+ * refreshing. The actual refresh operation completes on its own time. This
+ * function, along with e_cal_backend_refresh_finish(), merely initiates the
+ * operation.
*
- * Gets a free/busy object for the given time interval. Client side is
- * notified about free/busy objects throug e_data_cal_report_free_busy_data().
- * This might be finished with e_data_cal_respond_get_free_busy().
+ * Once the refresh is initiated, @callback will be called. You can then
+ * call e_cal-backend_refresh_finish() to get the result of the initiation.
+ *
+ * Since: 3.10
**/
void
-e_cal_backend_get_free_busy (ECalBackend *backend,
- EDataCal *cal,
- guint32 opid,
- GCancellable *cancellable,
- const GSList *users,
- time_t start,
- time_t end)
+e_cal_backend_refresh (ECalBackend *backend,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
{
- g_return_if_fail (backend != NULL);
+ GSimpleAsyncResult *simple;
+
+ g_return_if_fail (E_IS_CAL_BACKEND (backend));
+
+ simple = g_simple_async_result_new (
+ G_OBJECT (backend), callback,
+ user_data, e_cal_backend_refresh);
+
+ g_simple_async_result_set_check_cancellable (simple, cancellable);
+
+ cal_backend_push_operation (
+ backend, simple, cancellable, FALSE,
+ cal_backend_refresh_thread);
+
+ cal_backend_dispatch_next_operation (backend);
+
+ g_object_unref (simple);
+}
+
+/**
+ * e_cal_backend_refresh_finish:
+ * @backend: an #ECalBackend
+ * @result: a #GAsyncResult
+ * @error: return location for a #GError, or %NULL
+ *
+ * Finishes the refresh initiation started with e_cal_backend_refresh().
+ *
+ * If an error occurred while initiating the refresh, the function will set
+ * @error and return %FALSE. If the @backend does not support refreshing,
+ * the function will set an %UnsupportedMethod error and return %FALSE.
+ *
+ * Returns: %TRUE on success, %FALSE on failure
+ *
+ * Since: 3.10
+ **/
+gboolean
+e_cal_backend_refresh_finish (ECalBackend *backend,
+ GAsyncResult *result,
+ GError **error)
+{
+ GSimpleAsyncResult *simple;
+
+ g_return_val_if_fail (
+ g_simple_async_result_is_valid (
+ result, G_OBJECT (backend),
+ e_cal_backend_refresh), FALSE);
+
+ simple = G_SIMPLE_ASYNC_RESULT (result);
+
+ /* Assume success unless a GError is set. */
+ return !g_simple_async_result_propagate_error (simple, error);
+}
+
+/**
+ * e_cal_backend_get_objects_sync:
+ * @backend: an #ECalBackend
+ * @uid: a unique ID for an iCalendar object
+ * @rid: a recurrence ID, or %NULL
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Obtains an #ECalComponent by its @uid and, optionally, @rid.
+ *
+ * The returned #ECalComponent is referenced for thread-safety and must be
+ * unreferenced with g_object_unref() when finished with it.
+ *
+ * If an error occurs, the function will set @error and return %NULL.
+ *
+ * Returns: an #ECalComponent, or %NULL
+ *
+ * Since: 3.10
+ **/
+ECalComponent *
+e_cal_backend_get_object_sync (ECalBackend *backend,
+ const gchar *uid,
+ const gchar *rid,
+ GCancellable *cancellable,
+ GError **error)
+{
+ EAsyncClosure *closure;
+ GAsyncResult *result;
+ ECalComponent *component;
+
+ g_return_val_if_fail (E_IS_CAL_BACKEND (backend), NULL);
+ g_return_val_if_fail (uid != NULL, NULL);
+ /* rid can be NULL */
+
+ closure = e_async_closure_new ();
+
+ e_cal_backend_get_object (
+ backend, uid, rid, cancellable,
+ e_async_closure_callback, closure);
+
+ result = e_async_closure_wait (closure);
+
+ component = e_cal_backend_get_object_finish (backend, result, error);
+
+ e_async_closure_free (closure);
+
+ return component;
+}
+
+/* Helper for e_cal_backend_get_object() */
+static void
+cal_backend_get_object_thread (GSimpleAsyncResult *simple,
+ GObject *source_object,
+ GCancellable *cancellable)
+{
+ ECalBackend *backend;
+ ECalBackendClass *class;
+ EDataCal *data_cal;
+ AsyncContext *async_context;
+
+ backend = E_CAL_BACKEND (source_object);
+
+ class = E_CAL_BACKEND_GET_CLASS (backend);
+ g_return_if_fail (class->get_object != NULL);
+
+ data_cal = e_cal_backend_ref_data_cal (backend);
+ g_return_if_fail (data_cal != NULL);
+
+ async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+ if (!e_cal_backend_is_opened (backend)) {
+ g_simple_async_result_set_error (
+ simple, E_DATA_CAL_ERROR,
+ NotOpened,
+ "%s", e_data_cal_status_to_string (
+ NotOpened));
+ g_simple_async_result_complete_in_idle (simple);
+
+ } else {
+ guint32 opid;
+
+ opid = cal_backend_stash_operation (backend, simple);
+
+ class->get_object (
+ backend, data_cal, opid, cancellable,
+ async_context->uid,
+ async_context->rid);
+ }
+
+ g_object_unref (data_cal);
+}
+
+/**
+ * e_cal_backend_get_object:
+ * @backend: an #ECalBackend
+ * @uid: a unique ID for an iCalendar object
+ * @rid: a recurrence ID, or %NULL
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied
+ * @user_data: data to pass to the callback function
+ *
+ * Asynchronously obtains an #ECalComponent by its @uid and, optionally, @rid.
+ *
+ * When the operation is finished, @callback will be called. You can then
+ * call e_cal_backend_get_object_finish() to get the result of the operation.
+ *
+ * Since: 3.10
+ **/
+void
+e_cal_backend_get_object (ECalBackend *backend,
+ const gchar *uid,
+ const gchar *rid,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *simple;
+ AsyncContext *async_context;
+
+ g_return_if_fail (E_IS_CAL_BACKEND (backend));
+ g_return_if_fail (uid != NULL);
+ /* rid can be NULL */
+
+ async_context = g_slice_new0 (AsyncContext);
+ async_context->uid = g_strdup (uid);
+ async_context->rid = g_strdup (rid);
+
+ simple = g_simple_async_result_new (
+ G_OBJECT (backend), callback, user_data,
+ e_cal_backend_get_object);
+
+ g_simple_async_result_set_check_cancellable (simple, cancellable);
+
+ g_simple_async_result_set_op_res_gpointer (
+ simple, async_context, (GDestroyNotify) async_context_free);
+
+ cal_backend_push_operation (
+ backend, simple, cancellable, FALSE,
+ cal_backend_get_object_thread);
+
+ cal_backend_dispatch_next_operation (backend);
+
+ g_object_unref (simple);
+}
+
+/**
+ * e_cal_backend_get_object_finish:
+ * @backend: an #ECalBackend
+ * @result: a #GAsyncResult
+ * @error: return location for a #GError, or %NULL
+ *
+ * Finishes the operation started with e_cal_backend_get_object().
+ *
+ * The returned #ECalComponent is referenced for thread-safety and must be
+ * unreferenced with g_object_unref() when finished with it.
+ *
+ * If an error occurs, the function will set @error and return %NULL.
+ *
+ * Returns: an #ECalComponent, or %NULL
+ *
+ * Since: 3.10
+ **/
+ECalComponent *
+e_cal_backend_get_object_finish (ECalBackend *backend,
+ GAsyncResult *result,
+ GError **error)
+{
+ GSimpleAsyncResult *simple;
+ AsyncContext *async_context;
+ ECalComponent *component;
+
+ g_return_val_if_fail (
+ g_simple_async_result_is_valid (
+ result, G_OBJECT (backend),
+ e_cal_backend_get_object), FALSE);
+
+ simple = G_SIMPLE_ASYNC_RESULT (result);
+ async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+ if (g_simple_async_result_propagate_error (simple, error))
+ return FALSE;
+
+ component = g_queue_pop_head (&async_context->result_queue);
+ g_return_val_if_fail (E_IS_CAL_COMPONENT (component), NULL);
+
+ g_warn_if_fail (g_queue_is_empty (&async_context->result_queue));
+
+ return component;
+}
+
+/**
+ * e_cal_backend_get_object_list_sync:
+ * @backend: an #ECalBackend
+ * @query: a search query in S-expression format
+ * @out_objects: a #GQueue in which to deposit results
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Obtains a set of #ECalComponent instances which satisfy the criteria
+ * specified in @query, and deposits them in @out_objects.
+ *
+ * The returned #ECalComponent instances are referenced for thread-safety
+ * and must be unreferenced with g_object_unref() when finished with them.
+ *
+ * If an error occurs, the function will set @error and return %FALSE.
+ * Note that an empty result set does not necessarily imply an error.
+ *
+ * Returns: %TRUE on success, %FALSE on failure
+ *
+ * Since: 3.10
+ **/
+gboolean
+e_cal_backend_get_object_list_sync (ECalBackend *backend,
+ const gchar *query,
+ GQueue *out_objects,
+ GCancellable *cancellable,
+ GError **error)
+{
+ EAsyncClosure *closure;
+ GAsyncResult *result;
+ gboolean success;
+
+ g_return_val_if_fail (E_IS_CAL_BACKEND (backend), FALSE);
+ g_return_val_if_fail (query != NULL, FALSE);
+
+ closure = e_async_closure_new ();
+
+ e_cal_backend_get_object_list (
+ backend, query, cancellable,
+ e_async_closure_callback, closure);
+
+ result = e_async_closure_wait (closure);
+
+ success = e_cal_backend_get_object_list_finish (
+ backend, result, out_objects, error);
+
+ e_async_closure_free (closure);
+
+ return success;
+}
+
+/* Helper for e_cal_backend_get_object_list() */
+static void
+cal_backend_get_object_list_thread (GSimpleAsyncResult *simple,
+ GObject *source_object,
+ GCancellable *cancellable)
+{
+ ECalBackend *backend;
+ ECalBackendClass *class;
+ EDataCal *data_cal;
+ AsyncContext *async_context;
+
+ backend = E_CAL_BACKEND (source_object);
+
+ class = E_CAL_BACKEND_GET_CLASS (backend);
+ g_return_if_fail (class->get_object_list != NULL);
+
+ data_cal = e_cal_backend_ref_data_cal (backend);
+ g_return_if_fail (data_cal != NULL);
+
+ async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+ if (!e_cal_backend_is_opened (backend)) {
+ g_simple_async_result_set_error (
+ simple, E_DATA_CAL_ERROR,
+ NotOpened,
+ "%s", e_data_cal_status_to_string (
+ NotOpened));
+ g_simple_async_result_complete_in_idle (simple);
+
+ } else {
+ guint32 opid;
+
+ opid = cal_backend_stash_operation (backend, simple);
+
+ class->get_object_list (
+ backend, data_cal, opid, cancellable,
+ async_context->query);
+ }
+
+ g_object_unref (data_cal);
+}
+
+/**
+ * e_cal_backend_get_object_list:
+ * @backend: an #ECalBackend
+ * @query: a search query in S-expression format
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied
+ * @user_data: data to pass to the callback function
+ *
+ * Asynchronously obtains a set of #ECalComponent instances which satisfy
+ * the criteria specified in @query.
+ *
+ * When the operation in finished, @callback will be called. You can then
+ * call e_cal_backend_get_object_list_finish() to get the result of the
+ * operation.
+ *
+ * Since: 3.10
+ **/
+void
+e_cal_backend_get_object_list (ECalBackend *backend,
+ const gchar *query,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *simple;
+ AsyncContext *async_context;
+
+ g_return_if_fail (E_IS_CAL_BACKEND (backend));
+ g_return_if_fail (query != NULL);
+
+ async_context = g_slice_new0 (AsyncContext);
+ async_context->query = g_strdup (query);
+
+ simple = g_simple_async_result_new (
+ G_OBJECT (backend), callback, user_data,
+ e_cal_backend_get_object_list);
+
+ g_simple_async_result_set_check_cancellable (simple, cancellable);
+
+ g_simple_async_result_set_op_res_gpointer (
+ simple, async_context, (GDestroyNotify) async_context_free);
+
+ cal_backend_push_operation (
+ backend, simple, cancellable, FALSE,
+ cal_backend_get_object_list_thread);
+
+ cal_backend_dispatch_next_operation (backend);
+
+ g_object_unref (simple);
+}
+
+/**
+ * e_cal_backend_get_object_list_finish:
+ * @backend: an #ECalBackend
+ * @result: a #GAsyncResult
+ * @out_objects: a #GQueue in which to deposit results
+ * @error: return location for a #GError, or %NULL
+ *
+ * Finishes the operation started with e_cal_backend_get_object_list().
+ *
+ * The matching #ECalComponent instances are deposited in @out_objects.
+ * The returned #ECalComponent instances are referenced for thread-safety
+ * and must be unreferenced with g_object_unref() when finished with them.
+ *
+ * If an error occurred, the function will set @error and return %FALSE.
+ * Note that an empty result set does not necessarily imply an error.
+ *
+ * Returns: %TRUE on success, %FALSE on failure
+ *
+ * Since: 3.10
+ **/
+gboolean
+e_cal_backend_get_object_list_finish (ECalBackend *backend,
+ GAsyncResult *result,
+ GQueue *out_objects,
+ GError **error)
+{
+ GSimpleAsyncResult *simple;
+ AsyncContext *async_context;
+
+ g_return_val_if_fail (
+ g_simple_async_result_is_valid (
+ result, G_OBJECT (backend),
+ e_cal_backend_get_object_list), FALSE);
+ g_return_val_if_fail (out_objects != NULL, FALSE);
+
+ simple = G_SIMPLE_ASYNC_RESULT (result);
+ async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+ if (g_simple_async_result_propagate_error (simple, error))
+ return FALSE;
+
+ e_queue_transfer (&async_context->result_queue, out_objects);
+
+ return TRUE;
+}
+
+/**
+ * e_cal_backend_get_free_busy_sync:
+ * @backend: an #ECalBackend
+ * @start: start time
+ * @end: end time
+ * @users: a %NULL-terminated array of user strings
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Obtains a free/busy object for the list of @users in the time interval
+ * between @start and @end. The free/busy results are returned through the
+ * e_data_cal_report_free_busy_data() function rather than directly through
+ * this function.
+ *
+ * If an error occurs, the function will set @error and return %FALSE.
+ *
+ * Returns: %TRUE on success, %FALSE on failure.
+ *
+ * Since: 3.10
+ **/
+gboolean
+e_cal_backend_get_free_busy_sync (ECalBackend *backend,
+ time_t start,
+ time_t end,
+ const gchar * const *users,
+ GCancellable *cancellable,
+ GError **error)
+{
+ EAsyncClosure *closure;
+ GAsyncResult *result;
+ gboolean success;
+
+ g_return_val_if_fail (E_IS_CAL_BACKEND (backend), FALSE);
+ g_return_val_if_fail (users != NULL, FALSE);
+
+ closure = e_async_closure_new ();
+
+ e_cal_backend_get_free_busy (
+ backend, start, end, users, cancellable,
+ e_async_closure_callback, closure);
+
+ result = e_async_closure_wait (closure);
+
+ success = e_cal_backend_get_free_busy_finish (
+ backend, result, error);
+
+ e_async_closure_free (closure);
+
+ return success;
+}
+
+static void
+cal_backend_get_free_busy_thread (GSimpleAsyncResult *simple,
+ GObject *source_object,
+ GCancellable *cancellable)
+{
+ ECalBackend *backend;
+ ECalBackendClass *class;
+ EDataCal *data_cal;
+ AsyncContext *async_context;
+
+ backend = E_CAL_BACKEND (source_object);
+
+ class = E_CAL_BACKEND_GET_CLASS (backend);
+ g_return_if_fail (class->get_free_busy != NULL);
+
+ data_cal = e_cal_backend_ref_data_cal (backend);
+ g_return_if_fail (data_cal != NULL);
+
+ async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+ if (!e_cal_backend_is_opened (backend)) {
+ g_simple_async_result_set_error (
+ simple, E_DATA_CAL_ERROR,
+ NotOpened,
+ "%s", e_data_cal_status_to_string (
+ NotOpened));
+ g_simple_async_result_complete_in_idle (simple);
+
+ } else {
+ guint32 opid;
+
+ opid = cal_backend_stash_operation (backend, simple);
+
+ class->get_free_busy (
+ backend, data_cal, opid, cancellable,
+ async_context->string_list,
+ async_context->start,
+ async_context->end);
+ }
+
+ g_object_unref (data_cal);
+}
+
+/**
+ * e_cal_backend_get_free_busy:
+ * @backend: an #ECalBackend
+ * @start: start time
+ * @end: end time
+ * @users: a %NULL-terminated array of user strings
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied
+ * @user_data: data to pass to the callback function
+ *
+ * Asynchronously obtains a free/busy object for the list of @users in the
+ * time interval between @start and @end.
+ *
+ * When the operation is finished, @callback will be called. You can
+ * then call e_cal_backend_get_free_busy_finish() to get the result of
+ * the operation.
+ *
+ * Since: 3.10
+ **/
+void
+e_cal_backend_get_free_busy (ECalBackend *backend,
+ time_t start,
+ time_t end,
+ const gchar * const *users,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *simple;
+ AsyncContext *async_context;
+ GSList *list = NULL;
+ gint ii;
+
g_return_if_fail (E_IS_CAL_BACKEND (backend));
g_return_if_fail (start != -1 && end != -1);
g_return_if_fail (start <= end);
- g_return_if_fail (E_CAL_BACKEND_GET_CLASS (backend)->get_free_busy != NULL);
+ g_return_if_fail (users != NULL);
+
+ for (ii = 0; users[ii] != NULL; ii++)
+ list = g_slist_prepend (list, g_strdup (users[ii]));
+
+ async_context = g_slice_new0 (AsyncContext);
+ async_context->start = start;
+ async_context->end = end;
+ async_context->string_list = g_slist_reverse (list);
+
+ simple = g_simple_async_result_new (
+ G_OBJECT (backend), callback, user_data,
+ e_cal_backend_get_free_busy);
+
+ g_simple_async_result_set_check_cancellable (simple, cancellable);
+
+ g_simple_async_result_set_op_res_gpointer (
+ simple, async_context, (GDestroyNotify) async_context_free);
+
+ cal_backend_push_operation (
+ backend, simple, cancellable, FALSE,
+ cal_backend_get_free_busy_thread);
+
+ cal_backend_dispatch_next_operation (backend);
+
+ g_object_unref (simple);
+}
+
+/**
+ * e_cal_backend_get_free_busy_finish:
+ * @backend: an #ECalBackend
+ * @result: a #GAsyncResult
+ * @error: return location for a #GError, or %NULL
+ *
+ * Finishes the operation started with e_cal_backend_get_free_busy().
+ *
+ * The free/busy results are returned through the
+ * e_data_cal_report_free_busy_data() function rather than directly through
+ * this function.
+ *
+ * If an error occurred, the function will set @error and return %FALSE.
+ *
+ * Returns: %TRUE on success, %FALSE on failure
+ *
+ * Since: 3.10
+ **/
+gboolean
+e_cal_backend_get_free_busy_finish (ECalBackend *backend,
+ GAsyncResult *result,
+ GError **error)
+{
+ GSimpleAsyncResult *simple;
+
+ g_return_val_if_fail (
+ g_simple_async_result_is_valid (
+ result, G_OBJECT (backend),
+ e_cal_backend_get_free_busy), FALSE);
+
+ simple = G_SIMPLE_ASYNC_RESULT (result);
+
+ /* Assume success unless a GError is set. */
+ return !g_simple_async_result_propagate_error (simple, error);
+}
+
+/**
+ * e_cal_backend_create_objects_sync:
+ * @backend: an #ECalBackend
+ * @calobjs: a %NULL-terminated array of iCalendar strings
+ * @out_uids: a #GQueue in which to deposit results
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Creates one or more new iCalendar objects from @calobjs, and deposits
+ * the unique ID string for each newly-created object in @out_uids.
+ *
+ * Free the returned ID strings with g_free() when finished with them.
+ *
+ * If an error occurs, the function will set @error and return %FALSE.
+ *
+ * Returns: %TRUE on success, %FALSE on failure
+ *
+ * Since: 3.10
+ **/
+gboolean
+e_cal_backend_create_objects_sync (ECalBackend *backend,
+ const gchar * const *calobjs,
+ GQueue *out_uids,
+ GCancellable *cancellable,
+ GError **error)
+{
+ EAsyncClosure *closure;
+ GAsyncResult *result;
+ gboolean success;
+
+ g_return_val_if_fail (E_IS_CAL_BACKEND (backend), FALSE);
+ g_return_val_if_fail (calobjs != NULL, FALSE);
+
+ closure = e_async_closure_new ();
+
+ e_cal_backend_create_objects (
+ backend, calobjs, cancellable,
+ e_async_closure_callback, closure);
+
+ result = e_async_closure_wait (closure);
+
+ success = e_cal_backend_create_objects_finish (
+ backend, result, out_uids, error);
+
+ e_async_closure_free (closure);
+
+ return success;
+}
+
+/* Helper for e_cal_backend_create_objects() */
+static void
+cal_backend_create_objects_thread (GSimpleAsyncResult *simple,
+ GObject *source_object,
+ GCancellable *cancellable)
+{
+ ECalBackend *backend;
+ ECalBackendClass *class;
+ EDataCal *data_cal;
+ AsyncContext *async_context;
+
+ backend = E_CAL_BACKEND (source_object);
+
+ class = E_CAL_BACKEND_GET_CLASS (backend);
+
+ data_cal = e_cal_backend_ref_data_cal (backend);
+ g_return_if_fail (data_cal != NULL);
+
+ async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+ if (class->create_objects == NULL) {
+ g_simple_async_result_set_error (
+ simple, E_DATA_CAL_ERROR,
+ UnsupportedMethod,
+ "%s", e_data_cal_status_to_string (
+ UnsupportedMethod));
+ g_simple_async_result_complete_in_idle (simple);
+
+ } else if (!e_cal_backend_is_opened (backend)) {
+ g_simple_async_result_set_error (
+ simple, E_DATA_CAL_ERROR,
+ NotOpened,
+ "%s", e_data_cal_status_to_string (
+ NotOpened));
+ g_simple_async_result_complete_in_idle (simple);
+
+ } else {
+ guint32 opid;
+
+ opid = cal_backend_stash_operation (backend, simple);
+
+ class->create_objects (
+ backend, data_cal, opid, cancellable,
+ async_context->string_list);
+ }
+
+ g_object_unref (data_cal);
+}
+
+/**
+ * e_cal_backend_create_objects:
+ * @backend: an #ECalBackend
+ * @calobjs: a %NULL-terminated array of iCalendar strings
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @callback: a #GAsyncReadyCallback to call when the request is satisifed
+ * @user_data: data to pass to the callback function
+ *
+ * Asynchronously creates one or more new iCalendar objects from @calobjs.
+ *
+ * When the operation is finished, @callback will be called. You can then
+ * call e_cal_backend_create_objects_finish() to get the result of the
+ * operation.
+ *
+ * Since: 3.10
+ **/
+void
+e_cal_backend_create_objects (ECalBackend *backend,
+ const gchar * const *calobjs,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *simple;
+ AsyncContext *async_context;
+ GSList *list = NULL;
+ gint ii;
+
+ g_return_if_fail (E_IS_CAL_BACKEND (backend));
+ g_return_if_fail (calobjs != NULL);
+
+ for (ii = 0; calobjs[ii] != NULL; ii++)
+ list = g_slist_prepend (list, g_strdup (calobjs[ii]));
+
+ async_context = g_slice_new0 (AsyncContext);
+ async_context->string_list = g_slist_reverse (list);
+
+ simple = g_simple_async_result_new (
+ G_OBJECT (backend), callback, user_data,
+ e_cal_backend_create_objects);
+
+ g_simple_async_result_set_check_cancellable (simple, cancellable);
+
+ g_simple_async_result_set_op_res_gpointer (
+ simple, async_context, (GDestroyNotify) async_context_free);
+
+ cal_backend_push_operation (
+ backend, simple, cancellable, FALSE,
+ cal_backend_create_objects_thread);
+
+ cal_backend_dispatch_next_operation (backend);
+
+ g_object_unref (simple);
+}
+
+/**
+ * e_cal_backend_create_objects_finish:
+ * @backend: an #ECalBackend
+ * @result: a #GAsyncResult
+ * @out_uids: a #GQueue in which to deposit results
+ * @error: return location for a #GError, or %NULL
+ *
+ * Finishes the operation started with e_cal_backend_create_objects().
+ *
+ * A unique ID string for each newly-created object is deposited in @out_uids.
+ * Free the returned ID strings with g_free() when finished with them.
+ *
+ * If an error occurred, the function will set @error and return %FALSE.
+ *
+ * Returns: %TRUE on success, %FALSE on failure
+ *
+ * Since: 3.10
+ **/
+gboolean
+e_cal_backend_create_objects_finish (ECalBackend *backend,
+ GAsyncResult *result,
+ GQueue *out_uids,
+ GError **error)
+{
+ GSimpleAsyncResult *simple;
+ AsyncContext *async_context;
+ GQueue *string_queue;
+ GQueue *component_queue;
+
+ g_return_val_if_fail (
+ g_simple_async_result_is_valid (
+ result, G_OBJECT (backend),
+ e_cal_backend_create_objects), FALSE);
+ g_return_val_if_fail (out_uids != NULL, FALSE);
+
+ simple = G_SIMPLE_ASYNC_RESULT (result);
+ async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+ if (g_simple_async_result_propagate_error (simple, error))
+ return FALSE;
+
+ /* XXX Packing GQueues in a GQueue is pretty awkward, but until
+ * the backend methods can be updated I'm trying to make do
+ * with a single data container for all kinds of results. */
+
+ string_queue = g_queue_pop_head (&async_context->result_queue);
+ component_queue = g_queue_pop_head (&async_context->result_queue);
+
+ g_warn_if_fail (g_queue_is_empty (&async_context->result_queue));
+
+ g_return_val_if_fail (string_queue != NULL, FALSE);
+ g_return_val_if_fail (component_queue != NULL, FALSE);
+
+ e_queue_transfer (string_queue, out_uids);
+
+ while (!g_queue_is_empty (component_queue)) {
+ ECalComponent *component;
+
+ component = g_queue_pop_head (component_queue);
+ e_cal_backend_notify_component_created (backend, component);
+ g_object_unref (component);
+ }
+
+ g_queue_free (string_queue);
+ g_queue_free (component_queue);
+
+ return TRUE;
+}
+
+/**
+ * e_cal_backend_modify_objects:
+ * @backend: an #ECalBackend
+ * @calobjs: a %NULL-terminated array of iCalendar strings
+ * @mod: modification type for recurrences
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Modifies one or more iCalendar objects according to @calobjs and @mod.
+ *
+ * If an error occurs, the function will set @error and return %FALSE.
+ *
+ * Returns: %TRUE on success, %FALSE on failure
+ *
+ * Since: 3.10
+ **/
+gboolean
+e_cal_backend_modify_objects_sync (ECalBackend *backend,
+ const gchar * const *calobjs,
+ ECalObjModType mod,
+ GCancellable *cancellable,
+ GError **error)
+{
+ EAsyncClosure *closure;
+ GAsyncResult *result;
+ gboolean success;
+
+ g_return_val_if_fail (E_IS_CAL_BACKEND (backend), FALSE);
+ g_return_val_if_fail (calobjs != NULL, FALSE);
+
+ closure = e_async_closure_new ();
+
+ e_cal_backend_modify_objects (
+ backend, calobjs, mod, cancellable,
+ e_async_closure_callback, closure);
+
+ result = e_async_closure_wait (closure);
+
+ success = e_cal_backend_modify_objects_finish (
+ backend, result, error);
+
+ e_async_closure_free (closure);
+
+ return success;
+}
+
+/* Helper for e_cal_backend_modify_objects() */
+static void
+cal_backend_modify_objects_thread (GSimpleAsyncResult *simple,
+ GObject *source_object,
+ GCancellable *cancellable)
+{
+ ECalBackend *backend;
+ ECalBackendClass *class;
+ EDataCal *data_cal;
+ AsyncContext *async_context;
+
+ backend = E_CAL_BACKEND (source_object);
+
+ class = E_CAL_BACKEND_GET_CLASS (backend);
+
+ data_cal = e_cal_backend_ref_data_cal (backend);
+ g_return_if_fail (data_cal != NULL);
+
+ async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+ if (class->modify_objects == NULL) {
+ g_simple_async_result_set_error (
+ simple, E_DATA_CAL_ERROR,
+ UnsupportedMethod,
+ "%s", e_data_cal_status_to_string (
+ UnsupportedMethod));
+ g_simple_async_result_complete_in_idle (simple);
+
+ } else if (!e_cal_backend_is_opened (backend)) {
+ g_simple_async_result_set_error (
+ simple, E_DATA_CAL_ERROR,
+ NotOpened,
+ "%s", e_data_cal_status_to_string (
+ NotOpened));
+ g_simple_async_result_complete_in_idle (simple);
+
+ } else {
+ guint32 opid;
+
+ opid = cal_backend_stash_operation (backend, simple);
+
+ class->modify_objects (
+ backend, data_cal, opid, cancellable,
+ async_context->string_list,
+ async_context->mod);
+ }
+
+ g_object_unref (data_cal);
+}
+
+/**
+ * e_cal_backend_modify_objects:
+ * @backend: an #ECalBackend
+ * @calobjs: a %NULL-terminated array of iCalendar strings
+ * @mod: modification type for recurrences
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied
+ * @user_data: data to pass to the callback function
+ *
+ * Asynchronously modifies one or more iCalendar objects according to
+ * @calobjs and @mod.
+ *
+ * When the operation is finished, @callback will be called. You can then
+ * call e_cal_backend_modify_objects_finish() to get the result of the
+ * operation.
+ *
+ * Since: 3.10
+ **/
+void
+e_cal_backend_modify_objects (ECalBackend *backend,
+ const gchar * const *calobjs,
+ ECalObjModType mod,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *simple;
+ AsyncContext *async_context;
+ GSList *list = NULL;
+ gint ii;
+
+ g_return_if_fail (E_IS_CAL_BACKEND (backend));
+ g_return_if_fail (calobjs != NULL);
+
+ for (ii = 0; calobjs[ii] != NULL; ii++)
+ list = g_slist_prepend (list, g_strdup (calobjs[ii]));
+
+ async_context = g_slice_new0 (AsyncContext);
+ async_context->string_list = g_slist_reverse (list);
+ async_context->mod = mod;
+
+ simple = g_simple_async_result_new (
+ G_OBJECT (backend), callback, user_data,
+ e_cal_backend_modify_objects);
+
+ g_simple_async_result_set_check_cancellable (simple, cancellable);
+
+ g_simple_async_result_set_op_res_gpointer (
+ simple, async_context, (GDestroyNotify) async_context_free);
+
+ cal_backend_push_operation (
+ backend, simple, cancellable, FALSE,
+ cal_backend_modify_objects_thread);
+
+ cal_backend_dispatch_next_operation (backend);
+
+ g_object_unref (simple);
+}
+
+/**
+ * e_cal_backend_modify_objects_finish:
+ * @backend: an #ECalBackend
+ * @result: a #GAsyncResult
+ * @error: return location for a #GError, or %NULL
+ *
+ * Finishes the operation started with e_cal_backend_modify_objects().
+ *
+ * If an error occurred, the function will set @error and return %FALSE.
+ *
+ * Returns: %TRUE on success, %FALSE on failure
+ *
+ * Since: 3.10
+ **/
+gboolean
+e_cal_backend_modify_objects_finish (ECalBackend *backend,
+ GAsyncResult *result,
+ GError **error)
+{
+ GSimpleAsyncResult *simple;
+ AsyncContext *async_context;
+ GQueue *old_component_queue;
+ GQueue *new_component_queue;
+ guint length, ii;
+
+ g_return_val_if_fail (
+ g_simple_async_result_is_valid (
+ result, G_OBJECT (backend),
+ e_cal_backend_modify_objects), FALSE);
+
+ simple = G_SIMPLE_ASYNC_RESULT (result);
+ async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+ if (g_simple_async_result_propagate_error (simple, error))
+ return FALSE;
+
+ /* XXX Packing GQueues in a GQueue is pretty awkward, but until
+ * the backend methods can be updated I'm trying to make do
+ * with a single data container for all kinds of results. */
+
+ old_component_queue = g_queue_pop_head (&async_context->result_queue);
+ new_component_queue = g_queue_pop_head (&async_context->result_queue);
+
+ g_warn_if_fail (g_queue_is_empty (&async_context->result_queue));
+
+ g_return_val_if_fail (old_component_queue != NULL, FALSE);
+ g_return_val_if_fail (new_component_queue != NULL, FALSE);
+
+ length = MIN (
+ g_queue_get_length (old_component_queue),
+ g_queue_get_length (new_component_queue));
+
+ for (ii = 0; ii < length; ii++) {
+ ECalComponent *old_component;
+ ECalComponent *new_component;
+
+ old_component = g_queue_pop_head (old_component_queue);
+ new_component = g_queue_pop_head (new_component_queue);
+
+ e_cal_backend_notify_component_modified (
+ backend, old_component, new_component);
+
+ g_object_unref (old_component);
+ g_object_unref (new_component);
+ }
+
+ g_warn_if_fail (g_queue_is_empty (old_component_queue));
+ g_queue_free (old_component_queue);
+
+ g_warn_if_fail (g_queue_is_empty (new_component_queue));
+ g_queue_free (new_component_queue);
+
+ return TRUE;
+}
+
+/**
+ * e_cal_backend_remove_objects_sync:
+ * @backend: an #ECalBackend
+ * @component_ids: a #GList of #ECalComponentId structs
+ * @mod: modification type for recurrences
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Removes one or more iCalendar objects according to @component_ids and @mod.
+ *
+ * If an error occurs, the function will set @error and return %FALSE.
+ *
+ * Returns: %TRUE on success, %FALSE on failure
+ *
+ * Since: 3.10
+ **/
+gboolean
+e_cal_backend_remove_objects_sync (ECalBackend *backend,
+ GList *component_ids,
+ ECalObjModType mod,
+ GCancellable *cancellable,
+ GError **error)
+{
+ EAsyncClosure *closure;
+ GAsyncResult *result;
+ gboolean success;
+
+ g_return_val_if_fail (E_IS_CAL_BACKEND (backend), FALSE);
+ g_return_val_if_fail (component_ids != NULL, FALSE);
+
+ closure = e_async_closure_new ();
+
+ e_cal_backend_remove_objects (
+ backend, component_ids, mod, cancellable,
+ e_async_closure_callback, closure);
+
+ result = e_async_closure_wait (closure);
+
+ success = e_cal_backend_remove_objects_finish (
+ backend, result, error);
+
+ e_async_closure_free (closure);
+
+ return success;
+}
+
+/* Helper for e_cal_backend_remove_objects() */
+static void
+cal_backend_remove_objects_thread (GSimpleAsyncResult *simple,
+ GObject *source_object,
+ GCancellable *cancellable)
+{
+ ECalBackend *backend;
+ ECalBackendClass *class;
+ EDataCal *data_cal;
+ AsyncContext *async_context;
+
+ backend = E_CAL_BACKEND (source_object);
+
+ class = E_CAL_BACKEND_GET_CLASS (backend);
+ g_return_if_fail (class->remove_objects != NULL);
+
+ data_cal = e_cal_backend_ref_data_cal (backend);
+ g_return_if_fail (data_cal != NULL);
+
+ async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+ if (!e_cal_backend_is_opened (backend)) {
+ g_simple_async_result_set_error (
+ simple, E_DATA_CAL_ERROR,
+ NotOpened,
+ "%s", e_data_cal_status_to_string (
+ NotOpened));
+ g_simple_async_result_complete_in_idle (simple);
+
+ } else {
+ guint32 opid;
+
+ opid = cal_backend_stash_operation (backend, simple);
+
+ class->remove_objects (
+ backend, data_cal, opid, cancellable,
+ async_context->compid_list,
+ async_context->mod);
+ }
+
+ g_object_unref (data_cal);
+}
+
+/**
+ * e_cal_backend_remove_objects:
+ * @backend: an #ECalBackend
+ * @component_ids: a #GList of #ECalComponentId structs
+ * @mod: modification type for recurrences
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied
+ * @user_data: data to pass to the callback function
+ *
+ * Asynchronously removes one or more iCalendar objects according to
+ * @component_ids and @mod.
+ *
+ * When the operation is finished, @callback will be called. You can then
+ * call e_cal_backend_remove_objects_finish() to get the result of the
+ * operation.
+ *
+ * Since: 3.10
+ **/
+void
+e_cal_backend_remove_objects (ECalBackend *backend,
+ GList *component_ids,
+ ECalObjModType mod,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *simple;
+ AsyncContext *async_context;
+ GSList *list = NULL;
+
+ g_return_if_fail (E_IS_CAL_BACKEND (backend));
+ g_return_if_fail (component_ids != NULL);
+
+ while (component_ids != NULL) {
+ ECalComponentId *id = component_ids->data;
+ list = g_slist_prepend (list, e_cal_component_id_copy (id));
+ component_ids = g_list_next (component_ids);
+ }
+
+ async_context = g_slice_new0 (AsyncContext);
+ async_context->compid_list = g_slist_reverse (list);
+ async_context->mod = mod;
+
+ simple = g_simple_async_result_new (
+ G_OBJECT (backend), callback, user_data,
+ e_cal_backend_remove_objects);
+
+ g_simple_async_result_set_check_cancellable (simple, cancellable);
+
+ g_simple_async_result_set_op_res_gpointer (
+ simple, async_context, (GDestroyNotify) async_context_free);
+
+ cal_backend_push_operation (
+ backend, simple, cancellable, FALSE,
+ cal_backend_remove_objects_thread);
+
+ cal_backend_dispatch_next_operation (backend);
+
+ g_object_unref (simple);
+}
+
+/**
+ * e_cal_backend_remove_objects_finish:
+ * @backend: an #ECalBackend
+ * @result: a #GAsyncResult
+ * @error: return location for a #GError, or %NULL
+ *
+ * Finishes the operation started with e_cal_backend_remove_objects().
+ *
+ * If an error occurred, the function will set @error and return %FALSE.
+ *
+ * Returns: %TRUE on success, %FALSE on failure
+ *
+ * Since: 3.10
+ **/
+gboolean
+e_cal_backend_remove_objects_finish (ECalBackend *backend,
+ GAsyncResult *result,
+ GError **error)
+{
+ GSimpleAsyncResult *simple;
+ AsyncContext *async_context;
+ GQueue *component_id_queue;
+ GQueue *old_component_queue;
+ GQueue *new_component_queue;
+ guint length, ii;
+
+ g_return_val_if_fail (
+ g_simple_async_result_is_valid (
+ result, G_OBJECT (backend),
+ e_cal_backend_remove_objects), FALSE);
+
+ simple = G_SIMPLE_ASYNC_RESULT (result);
+ async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+ if (g_simple_async_result_propagate_error (simple, error))
+ return FALSE;
+
+ /* XXX Packing GQueues in a GQueue is pretty awkward, but until
+ * the backend methods can be updated I'm trying to make do
+ * with a single data container for all kinds of results. */
+
+ component_id_queue = g_queue_pop_head (&async_context->result_queue);
+ old_component_queue = g_queue_pop_head (&async_context->result_queue);
+ new_component_queue = g_queue_pop_head (&async_context->result_queue);
+
+ g_warn_if_fail (g_queue_is_empty (&async_context->result_queue));
+
+ g_return_val_if_fail (component_id_queue != NULL, FALSE);
+ g_return_val_if_fail (old_component_queue != NULL, FALSE);
+ /* new_component_queue may be NULL */
+
+ length = MIN (
+ g_queue_get_length (component_id_queue),
+ g_queue_get_length (old_component_queue));
+
+ for (ii = 0; ii < length; ii++) {
+ ECalComponentId *component_id;
+ ECalComponent *old_component;
+ ECalComponent *new_component = NULL;
+
+ component_id = g_queue_pop_head (component_id_queue);
+ old_component = g_queue_pop_head (old_component_queue);
+ if (new_component_queue != NULL)
+ new_component = g_queue_pop_head (new_component_queue);
+
+ e_cal_backend_notify_component_removed (
+ backend, component_id, old_component, new_component);
+
+ e_cal_component_free_id (component_id);
+ g_clear_object (&old_component);
+ g_clear_object (&new_component);
+ }
+
+ g_warn_if_fail (g_queue_is_empty (component_id_queue));
+ g_queue_free (component_id_queue);
+
+ g_warn_if_fail (g_queue_is_empty (old_component_queue));
+ g_queue_free (old_component_queue);
+
+ if (new_component_queue != NULL) {
+ g_warn_if_fail (g_queue_is_empty (new_component_queue));
+ g_queue_free (new_component_queue);
+ }
+
+ return TRUE;
+}
+
+/**
+ * e_cal_backend_receive_objects_sync:
+ * @backend: an #ECalBackend
+ * @calobj: an iCalendar string
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Receives the set of iCalendar objects specified by @calobj. This is used
+ * for iTIP confirmation and cancellation messages for scheduled meetings.
+ *
+ * If an error occurs, the function will set @error and return %FALSE.
+ *
+ * Returns: %TRUE on success, %FALSE on failure
+ *
+ * Since: 3.10
+ **/
+gboolean
+e_cal_backend_receive_objects_sync (ECalBackend *backend,
+ const gchar *calobj,
+ GCancellable *cancellable,
+ GError **error)
+{
+ EAsyncClosure *closure;
+ GAsyncResult *result;
+ gboolean success;
+
+ g_return_val_if_fail (E_IS_CAL_BACKEND (backend), FALSE);
+ g_return_val_if_fail (calobj != NULL, FALSE);
+
+ closure = e_async_closure_new ();
+
+ e_cal_backend_receive_objects (
+ backend, calobj, cancellable,
+ e_async_closure_callback, closure);
+
+ result = e_async_closure_wait (closure);
+
+ success = e_cal_backend_receive_objects_finish (
+ backend, result, error);
+
+ e_async_closure_free (closure);
+
+ return success;
+}
+
+/* Helper for e_cal_backend_receive_objects() */
+static void
+cal_backend_receive_objects_thread (GSimpleAsyncResult *simple,
+ GObject *source_object,
+ GCancellable *cancellable)
+{
+ ECalBackend *backend;
+ ECalBackendClass *class;
+ EDataCal *data_cal;
+ AsyncContext *async_context;
+
+ backend = E_CAL_BACKEND (source_object);
+
+ class = E_CAL_BACKEND_GET_CLASS (backend);
+ g_return_if_fail (class->receive_objects != NULL);
+
+ data_cal = e_cal_backend_ref_data_cal (backend);
+ g_return_if_fail (data_cal != NULL);
+
+ async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+ if (!e_cal_backend_is_opened (backend)) {
+ g_simple_async_result_set_error (
+ simple, E_DATA_CAL_ERROR,
+ NotOpened,
+ "%s", e_data_cal_status_to_string (
+ NotOpened));
+ g_simple_async_result_complete_in_idle (simple);
+
+ } else {
+ guint32 opid;
+
+ opid = cal_backend_stash_operation (backend, simple);
+
+ class->receive_objects (
+ backend, data_cal, opid, cancellable,
+ async_context->calobj);
+ }
+
+ g_object_unref (data_cal);
+}
+
+/**
+ * e_cal_backend_receive_objects:
+ * @backend: an #ECalBackend
+ * @calobj: an iCalendar string
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied
+ * @user_data: data to pass to the callback function
+ *
+ * Asynchronously receives the set of iCalendar objects specified by
+ * @calobj. This is used for iTIP confirmation and cancellation messages
+ * for scheduled meetings.
+ *
+ * When the operation is finished, @callback will be called. You can then
+ * call e_cal_backend_receive_objects_finish() to get the result of the
+ * operation.
+ *
+ * Since: 3.10
+ **/
+void
+e_cal_backend_receive_objects (ECalBackend *backend,
+ const gchar *calobj,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *simple;
+ AsyncContext *async_context;
+
+ g_return_if_fail (E_IS_CAL_BACKEND (backend));
+ g_return_if_fail (calobj != NULL);
+
+ async_context = g_slice_new0 (AsyncContext);
+ async_context->calobj = g_strdup (calobj);
+
+ simple = g_simple_async_result_new (
+ G_OBJECT (backend), callback, user_data,
+ e_cal_backend_receive_objects);
+
+ g_simple_async_result_set_check_cancellable (simple, cancellable);
+
+ g_simple_async_result_set_op_res_gpointer (
+ simple, async_context, (GDestroyNotify) async_context_free);
+
+ cal_backend_push_operation (
+ backend, simple, cancellable, FALSE,
+ cal_backend_receive_objects_thread);
+
+ cal_backend_dispatch_next_operation (backend);
+
+ g_object_unref (simple);
+}
+
+/**
+ * e_cal_backend_receive_objects_finish:
+ * @backend: an #ECalBackend
+ * @result: a #GAsyncResult
+ * @error: return location for a #GError, or %NULL
+ *
+ * Finishes the operation started with e_cal_backend_receive_objects().
+ *
+ * If an error occurred, the function will set @error and erturn %FALSE.
+ *
+ * Returns: %TRUE on success, %FALSE on failure
+ *
+ * Since: 3.10
+ **/
+gboolean
+e_cal_backend_receive_objects_finish (ECalBackend *backend,
+ GAsyncResult *result,
+ GError **error)
+{
+ GSimpleAsyncResult *simple;
+
+ g_return_val_if_fail (
+ g_simple_async_result_is_valid (
+ result, G_OBJECT (backend),
+ e_cal_backend_receive_objects), FALSE);
+
+ simple = G_SIMPLE_ASYNC_RESULT (result);
+
+ /* Assume success unless a GError is set. */
+ return !g_simple_async_result_propagate_error (simple, error);
+}
+
+/**
+ * e_cal_backend_send_objects_sync:
+ * @backend: an #ECalBackend
+ * @calobj: an iCalendar string
+ * @out_users: a #GQueue in which to deposit results
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Sends meeting information in @calobj. The @backend may modify @calobj
+ * and send meeting information only to particular users. The function
+ * returns the sent #ECalComponent and deposits the list of users the
+ * meeting information was sent to in @out_users.
+ *
+ * The returned #ECalComponent is referenced for thread-safety and must
+ * be unrefenced with g_object_unref() when finished with it.
+ *
+ * If an error occurs, the function will set @error and return %NULL.
+ *
+ * Returns: an #ECalComponent, or %NULL
+ *
+ * Since: 3.10
+ **/
+ECalComponent *
+e_cal_backend_send_objects_sync (ECalBackend *backend,
+ const gchar *calobj,
+ GQueue *out_users,
+ GCancellable *cancellable,
+ GError **error)
+{
+ EAsyncClosure *closure;
+ GAsyncResult *result;
+ ECalComponent *component;
+
+ g_return_val_if_fail (E_IS_CAL_BACKEND (backend), NULL);
+ g_return_val_if_fail (calobj != NULL, NULL);
+
+ closure = e_async_closure_new ();
+
+ e_cal_backend_send_objects (
+ backend, calobj, cancellable,
+ e_async_closure_callback, closure);
+
+ result = e_async_closure_wait (closure);
+
+ component = e_cal_backend_send_objects_finish (
+ backend, result, out_users, error);
+
+ e_async_closure_free (closure);
+
+ return component;
+}
+
+/* Helper for e_cal_backend_send_objects() */
+static void
+cal_backend_send_objects_thread (GSimpleAsyncResult *simple,
+ GObject *source_object,
+ GCancellable *cancellable)
+{
+ ECalBackend *backend;
+ ECalBackendClass *class;
+ EDataCal *data_cal;
+ AsyncContext *async_context;
+
+ backend = E_CAL_BACKEND (source_object);
+
+ class = E_CAL_BACKEND_GET_CLASS (backend);
+ g_return_if_fail (class->send_objects != NULL);
+
+ data_cal = e_cal_backend_ref_data_cal (backend);
+ g_return_if_fail (data_cal != NULL);
+
+ async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+ if (!e_cal_backend_is_opened (backend)) {
+ g_simple_async_result_set_error (
+ simple, E_DATA_CAL_ERROR,
+ NotOpened,
+ "%s", e_data_cal_status_to_string (
+ NotOpened));
+ g_simple_async_result_complete_in_idle (simple);
+
+ } else {
+ guint32 opid;
+
+ opid = cal_backend_stash_operation (backend, simple);
+
+ class->send_objects (
+ backend, data_cal, opid, cancellable,
+ async_context->calobj);
+ }
+
+ g_object_unref (data_cal);
+}
+
+/**
+ * e_cal_backend_send_objects:
+ * @backend: an #ECalBackend
+ * @calobj: an iCalendar string
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied
+ * @user_data: data to pass to the callback function
+ *
+ * Asynchronously sends meeting information in @calobj. The @backend may
+ * modify @calobj and send meeting information only to particular users.
+ *
+ * When the operation is finished, @callback will be called. You can then
+ * call e_cal_backend_send_objects_finish() to get the result of the operation.
+ *
+ * Since: 3.10
+ **/
+void
+e_cal_backend_send_objects (ECalBackend *backend,
+ const gchar *calobj,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *simple;
+ AsyncContext *async_context;
+
+ g_return_if_fail (E_IS_CAL_BACKEND (backend));
+ g_return_if_fail (calobj != NULL);
+
+ async_context = g_slice_new0 (AsyncContext);
+ async_context->calobj = g_strdup (calobj);
+
+ simple = g_simple_async_result_new (
+ G_OBJECT (backend), callback, user_data,
+ e_cal_backend_send_objects);
+
+ g_simple_async_result_set_check_cancellable (simple, cancellable);
+
+ g_simple_async_result_set_op_res_gpointer (
+ simple, async_context, (GDestroyNotify) async_context_free);
+
+ cal_backend_push_operation (
+ backend, simple, cancellable, FALSE,
+ cal_backend_send_objects_thread);
+
+ cal_backend_dispatch_next_operation (backend);
+
+ g_object_unref (simple);
+}
+
+/**
+ * e_cal_backend_send_objects_finish:
+ * @backend: an #ECalBackend
+ * @result: a #GAsyncResult
+ * @out_users: a #GQueue in which to deposit results
+ * @error: return location for a #GError, or %NULL
+ *
+ * Finishes the operation started with e_cal_backend_send_objects().
+ *
+ * The function returns the sent #ECalComponent and deposits the list of
+ * users the meeting information was sent to in @out_users.
+ *
+ * The returned #ECalComponent is referenced for thread-safety and must
+ * be unreferenced with g_object_unref() when finished with it.
+ *
+ * If an error occurs, the function will set @error and return %NULL.
+ *
+ * Returns: an #ECalComponent, or %NULL
+ *
+ * Since: 3.10
+ **/
+ECalComponent *
+e_cal_backend_send_objects_finish (ECalBackend *backend,
+ GAsyncResult *result,
+ GQueue *out_users,
+ GError **error)
+{
+ GSimpleAsyncResult *simple;
+ AsyncContext *async_context;
+ ECalComponent *component;
+
+ g_return_val_if_fail (
+ g_simple_async_result_is_valid (
+ result, G_OBJECT (backend),
+ e_cal_backend_send_objects), NULL);
+ g_return_val_if_fail (out_users != NULL, NULL);
+
+ simple = G_SIMPLE_ASYNC_RESULT (result);
+ async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+ if (g_simple_async_result_propagate_error (simple, error))
+ return NULL;
+
+ component = g_queue_pop_head (&async_context->result_queue);
+ g_return_val_if_fail (E_IS_CAL_COMPONENT (component), NULL);
+
+ e_queue_transfer (&async_context->result_queue, out_users);
+
+ return component;
+}
+
+/**
+ * e_cal_backend_get_attachment_uris_sync:
+ * @backend: an #ECalBackend
+ * @uid: a unique ID for an iCalendar object
+ * @rid: a recurrence ID, or %NULL
+ * @out_attachment_uris: a #GQueue in which to deposit results
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Inspects the iCalendar object specified by @uid and, optionally, @rid
+ * for attachments and deposits a URI string for each attachment in
+ * @out_attachment_uris. Free the returned strings with g_free() when
+ * finished with them.
+ *
+ * If an error occurs, the function will set @error and return %FALSE.
+ * Note that an empty result set does not necessarily imply an error.
+ *
+ * Returns: %TRUE on success, %FALSE on failure
+ *
+ * Since: 3.10
+ **/
+gboolean
+e_cal_backend_get_attachment_uris_sync (ECalBackend *backend,
+ const gchar *uid,
+ const gchar *rid,
+ GQueue *out_attachment_uris,
+ GCancellable *cancellable,
+ GError **error)
+{
+ EAsyncClosure *closure;
+ GAsyncResult *result;
+ gboolean success;
+
+ g_return_val_if_fail (E_IS_CAL_BACKEND (backend), FALSE);
+ g_return_val_if_fail (uid != NULL, FALSE);
+ /* rid can be NULL */
+
+ closure = e_async_closure_new ();
+
+ e_cal_backend_get_attachment_uris (
+ backend, uid, rid, cancellable,
+ e_async_closure_callback, closure);
+
+ result = e_async_closure_wait (closure);
+
+ success = e_cal_backend_get_attachment_uris_finish (
+ backend, result, out_attachment_uris, error);
+
+ e_async_closure_free (closure);
+
+ return success;
+}
+
+/* Helper for e_cal_backend_get_attachment_uris() */
+static void
+cal_backend_get_attachment_uris_thread (GSimpleAsyncResult *simple,
+ GObject *source_object,
+ GCancellable *cancellable)
+{
+ ECalBackend *backend;
+ ECalBackendClass *class;
+ EDataCal *data_cal;
+ AsyncContext *async_context;
+
+ backend = E_CAL_BACKEND (source_object);
+
+ class = E_CAL_BACKEND_GET_CLASS (backend);
+ g_return_if_fail (class->get_attachment_uris != NULL);
+
+ data_cal = e_cal_backend_ref_data_cal (backend);
+ g_return_if_fail (data_cal != NULL);
+
+ async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+ if (!e_cal_backend_is_opened (backend)) {
+ g_simple_async_result_set_error (
+ simple, E_DATA_CAL_ERROR,
+ NotOpened,
+ "%s", e_data_cal_status_to_string (
+ NotOpened));
+ g_simple_async_result_complete_in_idle (simple);
+
+ } else {
+ guint32 opid;
+
+ opid = cal_backend_stash_operation (backend, simple);
+
+ class->get_attachment_uris (
+ backend, data_cal, opid, cancellable,
+ async_context->uid,
+ async_context->rid);
+ }
+
+ g_object_unref (data_cal);
+}
+
+/**
+ * e_cal_backend_get_attachment_uris:
+ * @backend: an #ECalBackend
+ * @uid: a unique ID for an iCalendar object
+ * @rid: a recurrence ID, or %NULL
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied
+ * @user_data: data to pass to the callback function
+ *
+ * Asynchronously inspects the iCalendar object specified by @uid and,
+ * optionally, @rid for attachments.
+ *
+ * When the operation is finished, @callback will be called. You can then
+ * call e_cal_backend_get_attachment_uris_finish() to get the result of the
+ * operation.
+ *
+ * Since: 3.10
+ **/
+void
+e_cal_backend_get_attachment_uris (ECalBackend *backend,
+ const gchar *uid,
+ const gchar *rid,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *simple;
+ AsyncContext *async_context;
+
+ g_return_if_fail (E_IS_CAL_BACKEND (backend));
+ g_return_if_fail (uid != NULL);
+ /* rid is optional */
+
+ async_context = g_slice_new0 (AsyncContext);
+ async_context->uid = g_strdup (uid);
+ async_context->rid = g_strdup (rid);
+
+ simple = g_simple_async_result_new (
+ G_OBJECT (backend), callback, user_data,
+ e_cal_backend_get_attachment_uris);
+
+ g_simple_async_result_set_check_cancellable (simple, cancellable);
+
+ g_simple_async_result_set_op_res_gpointer (
+ simple, async_context, (GDestroyNotify) async_context_free);
+
+ cal_backend_push_operation (
+ backend, simple, cancellable, FALSE,
+ cal_backend_get_attachment_uris_thread);
+
+ cal_backend_dispatch_next_operation (backend);
- if (!e_cal_backend_is_opened (backend))
- e_data_cal_respond_get_free_busy (cal, opid, EDC_NOT_OPENED_ERROR);
- else
- (* E_CAL_BACKEND_GET_CLASS (backend)->get_free_busy) (backend, cal, opid, cancellable, users,
start, end);
+ g_object_unref (simple);
}
/**
- * e_cal_backend_create_objects:
+ * e_cal_backend_get_attachment_uris_finish:
* @backend: an #ECalBackend
- * @cal: an #EDataCal
- * @opid: the ID to use for this operation
- * @cancellable: a #GCancellable for the operation
- * @calobjs: The objects to create (list of gchar *).
+ * @result: a #GAsyncResult
+ * @out_attachment_uris: a #GQueue in which to deposit results
+ * @error: return location for a #GError, or %NULL
*
- * Calls the create_object method on the given backend.
- * This might be finished with e_data_cal_respond_create_objects().
+ * Finishes the operation started with e_cal_backend_get_attachment_uris().
*
- * Since: 3.6
+ * The requested attachment URI strings are deposited in @out_attachment_uris.
+ * Free the returned strings with g_free() when finished with them.
+ *
+ * If an error occurred, the function will set @error and return %FALSE.
+ * Note that an empty result set does not necessarily imply an error.
+ *
+ * Returns: %TRUE on success, %FALSE on failure
+ *
+ * Since: 3.10
**/
-void
-e_cal_backend_create_objects (ECalBackend *backend,
- EDataCal *cal,
- guint32 opid,
- GCancellable *cancellable,
- const GSList *calobjs)
+gboolean
+e_cal_backend_get_attachment_uris_finish (ECalBackend *backend,
+ GAsyncResult *result,
+ GQueue *out_attachment_uris,
+ GError **error)
{
- g_return_if_fail (backend != NULL);
- g_return_if_fail (E_IS_CAL_BACKEND (backend));
- g_return_if_fail (calobjs != NULL);
+ GSimpleAsyncResult *simple;
+ AsyncContext *async_context;
+
+ g_return_val_if_fail (
+ g_simple_async_result_is_valid (
+ result, G_OBJECT (backend),
+ e_cal_backend_get_attachment_uris), FALSE);
+ g_return_val_if_fail (out_attachment_uris != NULL, FALSE);
+
+ simple = G_SIMPLE_ASYNC_RESULT (result);
+ async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+ if (g_simple_async_result_propagate_error (simple, error))
+ return FALSE;
- if (!E_CAL_BACKEND_GET_CLASS (backend)->create_objects)
- e_data_cal_respond_create_objects (cal, opid, EDC_ERROR (UnsupportedMethod), NULL, NULL);
- else if (!e_cal_backend_is_opened (backend))
- e_data_cal_respond_create_objects (cal, opid, EDC_NOT_OPENED_ERROR, NULL, NULL);
- else
- (* E_CAL_BACKEND_GET_CLASS (backend)->create_objects) (backend, cal, opid, cancellable,
calobjs);
+ e_queue_transfer (&async_context->result_queue, out_attachment_uris);
+
+ return TRUE;
}
/**
- * e_cal_backend_modify_objects:
+ * e_cal_backend_discard_alarm_sync:
* @backend: an #ECalBackend
- * @cal: an #EDataCal
- * @opid: the ID to use for this operation
- * @cancellable: a #GCancellable for the operation
- * @calobjs: Objects to be modified (list of gchar *).
- * @mod: Type of modification.
+ * @uid: a unique ID for an iCalendar object
+ * @rid: a recurrence ID, or %NULL
+ * @alarm_uid: a unique ID for an iCalendar VALARM object
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
*
- * Calls the modify_objects method on the given backend.
- * This might be finished with e_data_cal_respond_modify_objects().
+ * Discards the VALARM object with a unique ID of @alarm_uid from the
+ * iCalendar object identified by @uid and, optionally, @rid.
*
- * Since: 3.6
+ * If an error occurs, the function will set @error and return %FALSE.
+ *
+ * Returns: %TRUE on success, %FALSE on failure
+ *
+ * Since: 3.10
**/
-void
-e_cal_backend_modify_objects (ECalBackend *backend,
- EDataCal *cal,
- guint32 opid,
- GCancellable *cancellable,
- const GSList *calobjs,
- ECalObjModType mod)
+gboolean
+e_cal_backend_discard_alarm_sync (ECalBackend *backend,
+ const gchar *uid,
+ const gchar *rid,
+ const gchar *alarm_uid,
+ GCancellable *cancellable,
+ GError **error)
{
- g_return_if_fail (backend != NULL);
- g_return_if_fail (E_IS_CAL_BACKEND (backend));
- g_return_if_fail (calobjs != NULL);
+ EAsyncClosure *closure;
+ GAsyncResult *result;
+ gboolean success;
+
+ g_return_val_if_fail (E_IS_CAL_BACKEND (backend), FALSE);
+ g_return_val_if_fail (uid != NULL, FALSE);
+ /* rid can be NULL */
+ g_return_val_if_fail (alarm_uid != NULL, FALSE);
+
+ closure = e_async_closure_new ();
+
+ e_cal_backend_discard_alarm (
+ backend, uid, rid, alarm_uid, cancellable,
+ e_async_closure_callback, closure);
+
+ result = e_async_closure_wait (closure);
+
+ success = e_cal_backend_discard_alarm_finish (
+ backend, result, error);
+
+ e_async_closure_free (closure);
+
+ return success;
+}
+
+/* Helper for e_cal_backend_discard_alarm() */
+static void
+cal_backend_discard_alarm_thread (GSimpleAsyncResult *simple,
+ GObject *source_object,
+ GCancellable *cancellable)
+{
+ ECalBackend *backend;
+ ECalBackendClass *class;
+ EDataCal *data_cal;
+ AsyncContext *async_context;
+
+ backend = E_CAL_BACKEND (source_object);
+
+ class = E_CAL_BACKEND_GET_CLASS (backend);
+
+ data_cal = e_cal_backend_ref_data_cal (backend);
+ g_return_if_fail (data_cal != NULL);
+
+ async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+ if (class->discard_alarm == NULL) {
+ g_simple_async_result_set_error (
+ simple, E_DATA_CAL_ERROR,
+ NotSupported,
+ "%s", e_data_cal_status_to_string (
+ NotSupported));
+ g_simple_async_result_complete_in_idle (simple);
+
+ } else if (!e_cal_backend_is_opened (backend)) {
+ g_simple_async_result_set_error (
+ simple, E_DATA_CAL_ERROR,
+ NotOpened,
+ "%s", e_data_cal_status_to_string (
+ NotOpened));
+ g_simple_async_result_complete_in_idle (simple);
+
+ } else {
+ guint32 opid;
+
+ opid = cal_backend_stash_operation (backend, simple);
+
+ class->discard_alarm (
+ backend, data_cal, opid, cancellable,
+ async_context->uid,
+ async_context->rid,
+ async_context->alarm_uid);
+ }
- if (!E_CAL_BACKEND_GET_CLASS (backend)->modify_objects)
- e_data_cal_respond_modify_objects (cal, opid, EDC_ERROR (UnsupportedMethod), NULL, NULL);
- else if (!e_cal_backend_is_opened (backend))
- e_data_cal_respond_modify_objects (cal, opid, EDC_NOT_OPENED_ERROR, NULL, NULL);
- else
- (* E_CAL_BACKEND_GET_CLASS (backend)->modify_objects) (backend, cal, opid, cancellable,
calobjs, mod);
+ g_object_unref (data_cal);
}
/**
- * e_cal_backend_remove_objects:
+ * e_cal_backend_discard_alarm:
* @backend: an #ECalBackend
- * @cal: an #EDataCal
- * @opid: the ID to use for this operation
- * @cancellable: a #GCancellable for the operation
- * @ids: List of #ECalComponentId objects identifying the objects to remove
- * @mod: Type of removal.
+ * @uid: a unique ID for an iCalendar object
+ * @rid: a recurrence ID, or %NULL
+ * @alarm_uid: a unique ID for an iCalendar VALARM object
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied
+ * @user_data: data to pass to the callback function
*
- * Removes objects in a calendar backend. The backend will notify all of its
- * clients about the change.
- * This might be finished with e_data_cal_respond_remove_objects().
+ * Asynchronously discards the VALARM object with a unique ID of @alarm_uid
+ * from the iCalendar object identified by @uid and, optionally, @rid.
*
- * Since: 3.6
+ * When the operation is finished, @callback will be called. You can
+ * then call e_cal_backend_discard_alarm_finish() to get the result of
+ * the operation.
+ *
+ * Since: 3.10
**/
void
-e_cal_backend_remove_objects (ECalBackend *backend,
- EDataCal *cal,
- guint32 opid,
- GCancellable *cancellable,
- const GSList *ids,
- ECalObjModType mod)
+e_cal_backend_discard_alarm (ECalBackend *backend,
+ const gchar *uid,
+ const gchar *rid,
+ const gchar *alarm_uid,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
{
- g_return_if_fail (backend != NULL);
+ GSimpleAsyncResult *simple;
+ AsyncContext *async_context;
+
g_return_if_fail (E_IS_CAL_BACKEND (backend));
- g_return_if_fail (ids != NULL);
- g_return_if_fail (E_CAL_BACKEND_GET_CLASS (backend)->remove_objects != NULL);
+ g_return_if_fail (uid != NULL);
+ /* rid can be NULL */
+ g_return_if_fail (alarm_uid != NULL);
+
+ async_context = g_slice_new0 (AsyncContext);
+ async_context->uid = g_strdup (uid);
+ async_context->rid = g_strdup (rid);
+ async_context->alarm_uid = g_strdup (alarm_uid);
+
+ simple = g_simple_async_result_new (
+ G_OBJECT (backend), callback, user_data,
+ e_cal_backend_discard_alarm);
- if (!e_cal_backend_is_opened (backend))
- e_data_cal_respond_remove_objects (cal, opid, EDC_NOT_OPENED_ERROR, NULL, NULL, NULL);
- else
- (* E_CAL_BACKEND_GET_CLASS (backend)->remove_objects) (backend, cal, opid, cancellable, ids,
mod);
+ g_simple_async_result_set_check_cancellable (simple, cancellable);
+
+ g_simple_async_result_set_op_res_gpointer (
+ simple, async_context, (GDestroyNotify) async_context_free);
+
+ cal_backend_push_operation (
+ backend, simple, cancellable, FALSE,
+ cal_backend_discard_alarm_thread);
+
+ cal_backend_dispatch_next_operation (backend);
+
+ g_object_unref (simple);
}
/**
- * e_cal_backend_receive_objects:
+ * e_cal_backend_discard_alarm_finish:
* @backend: an #ECalBackend
- * @cal: an #EDataCal
- * @opid: the ID to use for this operation
- * @cancellable: a #GCancellable for the operation
- * @calobj: iCalendar object.
+ * @result: a #GAsyncResult
+ * @error: return location for a #GError, or %NULL
+ *
+ * Finishes the operation started with e_cal_backend_discard_alarm().
+ *
+ * If an error occurred, the function will set @error and return %FALSE.
+ *
+ * Returns: %TRUE on success, %FALSE on failure
*
- * Calls the receive_objects method on the given backend.
- * This might be finished with e_data_cal_respond_receive_objects().
+ * Since: 3.10
**/
-void
-e_cal_backend_receive_objects (ECalBackend *backend,
- EDataCal *cal,
- guint32 opid,
- GCancellable *cancellable,
- const gchar *calobj)
+gboolean
+e_cal_backend_discard_alarm_finish (ECalBackend *backend,
+ GAsyncResult *result,
+ GError **error)
{
- g_return_if_fail (backend != NULL);
- g_return_if_fail (E_IS_CAL_BACKEND (backend));
- g_return_if_fail (calobj != NULL);
- g_return_if_fail (E_CAL_BACKEND_GET_CLASS (backend)->receive_objects != NULL);
+ GSimpleAsyncResult *simple;
- if (!e_cal_backend_is_opened (backend))
- e_data_cal_respond_receive_objects (cal, opid, EDC_NOT_OPENED_ERROR);
- else
- (* E_CAL_BACKEND_GET_CLASS (backend)->receive_objects) (backend, cal, opid, cancellable,
calobj);
+ g_return_val_if_fail (
+ g_simple_async_result_is_valid (
+ result, G_OBJECT (backend),
+ e_cal_backend_discard_alarm), FALSE);
+
+ simple = G_SIMPLE_ASYNC_RESULT (result);
+
+ /* Assume success unless a GError is set. */
+ return !g_simple_async_result_propagate_error (simple, error);
}
/**
- * e_cal_backend_send_objects:
+ * e_cal_backend_get_timezone_sync:
* @backend: an #ECalBackend
- * @cal: an #EDataCal
- * @opid: the ID to use for this operation
- * @cancellable: a #GCancellable for the operation
- * @calobj: iCalendar object to be sent.
+ * @tzid: a unique ID for an iCalendar VTIMEZONE object
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Obtains the VTIMEZONE object identified by @tzid. Free the returned
+ * string with g_free() when finished with it.
*
- * Calls the send_objects method on the given backend.
- * This might be finished with e_data_cal_respond_send_objects().
+ * If an error occurs, the function will set @error and return %NULL.
+ *
+ * Returns: an iCalendar string, or %NULL
+ *
+ * Since: 3.10
**/
-void
-e_cal_backend_send_objects (ECalBackend *backend,
- EDataCal *cal,
- guint32 opid,
- GCancellable *cancellable,
- const gchar *calobj)
+gchar *
+e_cal_backend_get_timezone_sync (ECalBackend *backend,
+ const gchar *tzid,
+ GCancellable *cancellable,
+ GError **error)
{
- g_return_if_fail (backend != NULL);
- g_return_if_fail (E_IS_CAL_BACKEND (backend));
- g_return_if_fail (calobj != NULL);
- g_return_if_fail (E_CAL_BACKEND_GET_CLASS (backend)->send_objects != NULL);
+ EAsyncClosure *closure;
+ GAsyncResult *result;
+ gchar *tzobject;
+
+ g_return_val_if_fail (E_IS_CAL_BACKEND (backend), NULL);
+ g_return_val_if_fail (tzid != NULL, NULL);
+
+ closure = e_async_closure_new ();
+
+ e_cal_backend_get_timezone (
+ backend, tzid, cancellable,
+ e_async_closure_callback, closure);
+
+ result = e_async_closure_wait (closure);
+
+ tzobject = e_cal_backend_get_timezone_finish (
+ backend, result, error);
+
+ e_async_closure_free (closure);
+
+ return tzobject;
+}
+
+/* Helper for e_cal_backend_get_timezone() */
+static void
+cal_backend_get_timezone_thread (GSimpleAsyncResult *simple,
+ GObject *source_object,
+ GCancellable *cancellable)
+{
+ ECalBackend *backend;
+ ECalBackendClass *class;
+ EDataCal *data_cal;
+ AsyncContext *async_context;
+
+ backend = E_CAL_BACKEND (source_object);
+
+ class = E_CAL_BACKEND_GET_CLASS (backend);
+ g_return_if_fail (class->get_timezone != NULL);
+
+ data_cal = e_cal_backend_ref_data_cal (backend);
+ g_return_if_fail (data_cal != NULL);
- if (!e_cal_backend_is_opened (backend))
- e_data_cal_respond_send_objects (cal, opid, EDC_NOT_OPENED_ERROR, NULL, NULL);
- else
- (* E_CAL_BACKEND_GET_CLASS (backend)->send_objects) (backend, cal, opid, cancellable, calobj);
+ async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+ if (!e_cal_backend_is_opened (backend)) {
+ g_simple_async_result_set_error (
+ simple, E_DATA_CAL_ERROR,
+ NotOpened,
+ "%s", e_data_cal_status_to_string (
+ NotOpened));
+ g_simple_async_result_complete_in_idle (simple);
+
+ } else {
+ guint32 opid;
+
+ opid = cal_backend_stash_operation (backend, simple);
+
+ class->get_timezone (
+ backend, data_cal, opid, cancellable,
+ async_context->tzid);
+ }
+
+ g_object_unref (data_cal);
}
/**
- * e_cal_backend_get_attachment_uris:
+ * e_cal_backend_get_timezone:
* @backend: an #ECalBackend
- * @cal: an #EDataCal
- * @opid: the ID to use for this operation
- * @cancellable: a #GCancellable for the operation
- * @uid: Unique identifier for a calendar object.
- * @rid: ID for the object's recurrence to get.
+ * @tzid: a unique ID for an iCalendar VTIMEZONE object
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied
+ * @user_data: data to pass to the callback function
*
- * Queries a calendar backend for attachments present in a calendar object based
- * on its unique identifier and its recurrence ID (if a recurrent appointment).
- * This might be finished with e_data_cal_respond_get_attachment_uris().
+ * Asynchronously obtains the VTIMEZONE object identified by @tzid.
*
- * Since: 3.2
+ * When the operation is finished, @callback will be called. You can
+ * then call e_cal_backend_get_timezone_finish() to get the result of
+ * the operation.
+ *
+ * Since: 3.10
**/
void
-e_cal_backend_get_attachment_uris (ECalBackend *backend,
- EDataCal *cal,
- guint32 opid,
- GCancellable *cancellable,
- const gchar *uid,
- const gchar *rid)
+e_cal_backend_get_timezone (ECalBackend *backend,
+ const gchar *tzid,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
{
- g_return_if_fail (backend != NULL);
+ GSimpleAsyncResult *simple;
+ AsyncContext *async_context;
+
g_return_if_fail (E_IS_CAL_BACKEND (backend));
- g_return_if_fail (uid != NULL);
- g_return_if_fail (E_CAL_BACKEND_GET_CLASS (backend)->get_attachment_uris != NULL);
+ g_return_if_fail (tzid != NULL);
+
+ async_context = g_slice_new0 (AsyncContext);
+ async_context->tzid = g_strdup (tzid);
+
+ simple = g_simple_async_result_new (
+ G_OBJECT (backend), callback, user_data,
+ e_cal_backend_get_timezone);
+
+ g_simple_async_result_set_check_cancellable (simple, cancellable);
- if (!e_cal_backend_is_opened (backend))
- e_data_cal_respond_get_attachment_uris (cal, opid, EDC_NOT_OPENED_ERROR, NULL);
- else
- (* E_CAL_BACKEND_GET_CLASS (backend)->get_attachment_uris) (backend, cal, opid, cancellable,
uid, rid);
+ g_simple_async_result_set_op_res_gpointer (
+ simple, async_context, (GDestroyNotify) async_context_free);
+
+ cal_backend_push_operation (
+ backend, simple, cancellable, FALSE,
+ cal_backend_get_timezone_thread);
+
+ cal_backend_dispatch_next_operation (backend);
+
+ g_object_unref (simple);
}
/**
- * e_cal_backend_discard_alarm:
+ * e_cal_backend_get_timezone_finish:
* @backend: an #ECalBackend
- * @cal: an #EDataCal
- * @opid: the ID to use for this operation
- * @cancellable: a #GCancellable for the operation
- * @uid: Unique identifier for a calendar object.
- * @rid: ID for the object's recurrence to discard alarm in.
- * @auid: Unique identifier of the alarm itself.
+ * @result: a #GAsyncResult
+ * @error: return location for a #GError, or %NULL
+ *
+ * Finishes the operation started with e_cal_backend_get_timezone().
+ *
+ * Free the returned string with g_free() when finished with it.
+ *
+ * If an error occurred, the function will set @error and return %NULL.
+ *
+ * Returns: an iCalendar string, or %NULL
*
- * Discards alarm @auid from the object identified by @uid and @rid.
- * This might be finished with e_data_cal_respond_discard_alarm().
- * Default implementation of this method returns Not Supported error.
+ * Since: 3.10
**/
-void
-e_cal_backend_discard_alarm (ECalBackend *backend,
- EDataCal *cal,
- guint32 opid,
- GCancellable *cancellable,
- const gchar *uid,
- const gchar *rid,
- const gchar *auid)
+gchar *
+e_cal_backend_get_timezone_finish (ECalBackend *backend,
+ GAsyncResult *result,
+ GError **error)
{
- g_return_if_fail (backend != NULL);
- g_return_if_fail (E_IS_CAL_BACKEND (backend));
- g_return_if_fail (uid != NULL);
- g_return_if_fail (auid != NULL);
+ GSimpleAsyncResult *simple;
+ AsyncContext *async_context;
+ gchar *tzobject;
+
+ g_return_val_if_fail (
+ g_simple_async_result_is_valid (
+ result, G_OBJECT (backend),
+ e_cal_backend_get_timezone), FALSE);
+
+ simple = G_SIMPLE_ASYNC_RESULT (result);
+ async_context = g_simple_async_result_get_op_res_gpointer (simple);
- if (!E_CAL_BACKEND_GET_CLASS (backend)->discard_alarm)
- e_data_cal_respond_discard_alarm (cal, opid, e_data_cal_create_error (NotSupported, NULL));
- else if (!e_cal_backend_is_opened (backend))
- e_data_cal_respond_discard_alarm (cal, opid, EDC_NOT_OPENED_ERROR);
- else
- (* E_CAL_BACKEND_GET_CLASS (backend)->discard_alarm) (backend, cal, opid, cancellable, uid,
rid, auid);
+ if (g_simple_async_result_propagate_error (simple, error))
+ return FALSE;
+
+ tzobject = g_queue_pop_head (&async_context->result_queue);
+ g_return_val_if_fail (tzobject != NULL, NULL);
+
+ g_warn_if_fail (g_queue_is_empty (&async_context->result_queue));
+
+ return tzobject;
}
/**
- * e_cal_backend_get_timezone:
+ * e_cal_backend_add_timezone_sync:
* @backend: an #ECalBackend
- * @cal: an #EDataCal
- * @opid: the ID to use for this operation
- * @cancellable: a #GCancellable for the operation
- * @tzid: Unique identifier of a VTIMEZONE object. Note that this must not be
- * NULL.
+ * @tzobject: an iCalendar VTIMEZONE string
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
*
- * Returns the icaltimezone* corresponding to the TZID, or NULL if the TZID
- * can't be found.
- * This might be finished with e_data_cal_respond_get_timezone().
+ * Adds the timezone described by @tzobject to @backend.
+ *
+ * If an error occurs, the function will set @error and return %FALSE.
+ *
+ * Returns: %TRUE on success, %FALSE on failure
+ *
+ * Since: 3.10
**/
-void
-e_cal_backend_get_timezone (ECalBackend *backend,
- EDataCal *cal,
- guint32 opid,
- GCancellable *cancellable,
- const gchar *tzid)
+gboolean
+e_cal_backend_add_timezone_sync (ECalBackend *backend,
+ const gchar *tzobject,
+ GCancellable *cancellable,
+ GError **error)
{
- g_return_if_fail (backend != NULL);
- g_return_if_fail (E_IS_CAL_BACKEND (backend));
- g_return_if_fail (tzid != NULL);
- g_return_if_fail (E_CAL_BACKEND_GET_CLASS (backend)->get_timezone != NULL);
+ EAsyncClosure *closure;
+ GAsyncResult *result;
+ gboolean success;
+
+ g_return_val_if_fail (E_IS_CAL_BACKEND (backend), FALSE);
+ g_return_val_if_fail (tzobject != NULL, FALSE);
+
+ closure = e_async_closure_new ();
+
+ e_cal_backend_add_timezone (
+ backend, tzobject, cancellable,
+ e_async_closure_callback, closure);
+
+ result = e_async_closure_wait (closure);
- if (!e_cal_backend_is_opened (backend))
- e_data_cal_respond_get_timezone (cal, opid, EDC_NOT_OPENED_ERROR, NULL);
- else
- (* E_CAL_BACKEND_GET_CLASS (backend)->get_timezone) (backend, cal, opid, cancellable, tzid);
+ success = e_cal_backend_add_timezone_finish (
+ backend, result, error);
+
+ e_async_closure_free (closure);
+
+ return success;
+}
+
+/* Helper for e_cal_backend_add_timezone() */
+static void
+cal_backend_add_timezone_thread (GSimpleAsyncResult *simple,
+ GObject *source_object,
+ GCancellable *cancellable)
+{
+ ECalBackend *backend;
+ ECalBackendClass *class;
+ EDataCal *data_cal;
+ AsyncContext *async_context;
+
+ backend = E_CAL_BACKEND (source_object);
+
+ class = E_CAL_BACKEND_GET_CLASS (backend);
+ g_return_if_fail (class->add_timezone != NULL);
+
+ data_cal = e_cal_backend_ref_data_cal (backend);
+ g_return_if_fail (data_cal != NULL);
+
+ async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+ if (!e_cal_backend_is_opened (backend)) {
+ g_simple_async_result_set_error (
+ simple, E_DATA_CAL_ERROR,
+ NotOpened,
+ "%s", e_data_cal_status_to_string (
+ NotOpened));
+ g_simple_async_result_complete_in_idle (simple);
+
+ } else {
+ guint32 opid;
+
+ opid = cal_backend_stash_operation (backend, simple);
+
+ class->add_timezone (
+ backend, data_cal, opid, cancellable,
+ async_context->tzobject);
+ }
+
+ g_object_unref (data_cal);
}
/**
* e_cal_backend_add_timezone
* @backend: an #ECalBackend
- * @cal: an #EDataCal
- * @opid: the ID to use for this operation
- * @cancellable: a #GCancellable for the operation
- * @tzobject: The timezone object, in a string.
+ * @tzobject: an iCalendar VTIMEZONE string
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied
+ * @user_data: data to pass to the callback function
*
- * Add a timezone object to the given backend.
- * This might be finished with e_data_cal_respond_add_timezone().
+ * Asynchronously adds the timezone described by @tzobject to @backend.
+ *
+ * When the operation is finished, @callback will be called. You can
+ * then call e_cal_backend_add_timezone_finish() to get the result of
+ * the operation.
+ *
+ * Since: 3.10
**/
void
e_cal_backend_add_timezone (ECalBackend *backend,
- EDataCal *cal,
- guint32 opid,
+ const gchar *tzobject,
GCancellable *cancellable,
- const gchar *tzobject)
+ GAsyncReadyCallback callback,
+ gpointer user_data)
{
+ GSimpleAsyncResult *simple;
+ AsyncContext *async_context;
+
g_return_if_fail (E_IS_CAL_BACKEND (backend));
g_return_if_fail (tzobject != NULL);
- g_return_if_fail (E_CAL_BACKEND_GET_CLASS (backend)->add_timezone != NULL);
- if (!e_cal_backend_is_opened (backend))
- e_data_cal_respond_add_timezone (cal, opid, EDC_NOT_OPENED_ERROR);
- else
- (* E_CAL_BACKEND_GET_CLASS (backend)->add_timezone) (backend, cal, opid, cancellable,
tzobject);
+ async_context = g_slice_new0 (AsyncContext);
+ async_context->tzobject = g_strdup (tzobject);
+
+ simple = g_simple_async_result_new (
+ G_OBJECT (backend), callback, user_data,
+ e_cal_backend_add_timezone);
+
+ g_simple_async_result_set_check_cancellable (simple, cancellable);
+
+ g_simple_async_result_set_op_res_gpointer (
+ simple, async_context, (GDestroyNotify) async_context_free);
+
+ cal_backend_push_operation (
+ backend, simple, cancellable, FALSE,
+ cal_backend_add_timezone_thread);
+
+ cal_backend_dispatch_next_operation (backend);
+
+ g_object_unref (simple);
+}
+
+/**
+ * e_cal_backend_add_timezone_finish:
+ * @backend: an #ECalBackend
+ * @result: a #GAsyncResult
+ * @error: return location for a #GError, or %NULL
+ *
+ * Finishes the operation started with e_cal_backend_add_timezone().
+ *
+ * If an error occurred, the function will set @error and return %FALSE.
+ *
+ * Returns: %TRUE on success, %FALSE on failure
+ *
+ * Since: 3.10
+ **/
+gboolean
+e_cal_backend_add_timezone_finish (ECalBackend *backend,
+ GAsyncResult *result,
+ GError **error)
+{
+ GSimpleAsyncResult *simple;
+
+ g_return_val_if_fail (
+ g_simple_async_result_is_valid (
+ result, G_OBJECT (backend),
+ e_cal_backend_add_timezone), FALSE);
+
+ simple = G_SIMPLE_ASYNC_RESULT (result);
+
+ /* Assume success unless a GError is set. */
+ return !g_simple_async_result_propagate_error (simple, error);
}
/**
@@ -1852,3 +4433,51 @@ e_cal_backend_empty_cache (ECalBackend *backend,
e_file_cache_thaw_changes (E_FILE_CACHE (cache));
}
+
+/**
+ * e_cal_backend_prepare_for_completion:
+ * @backend: an #ECalBackend
+ * @opid: an operation ID given to #EDataCal
+ * @result_queue: return location for a #GQueue, or %NULL
+ *
+ * Obtains the #GSimpleAsyncResult for @opid and sets @result_queue as a
+ * place to deposit results prior to completing the #GSimpleAsyncResult.
+ *
+ * <note>
+ * <para>
+ * This is a temporary function to serve #EDataCal's "respond"
+ * functions until they can be removed. Nothing else should be
+ * calling this function.
+ * </para>
+ * </note>
+ *
+ * Returns: (transfer full): a #GSimpleAsyncResult
+ *
+ * Since: 3.10
+ **/
+GSimpleAsyncResult *
+e_cal_backend_prepare_for_completion (ECalBackend *backend,
+ guint32 opid,
+ GQueue **result_queue)
+{
+ GSimpleAsyncResult *simple;
+ AsyncContext *async_context;
+
+ g_return_val_if_fail (E_IS_CAL_BACKEND (backend), NULL);
+ g_return_val_if_fail (opid > 0, NULL);
+
+ simple = cal_backend_claim_operation (backend, opid);
+ g_return_val_if_fail (simple != NULL, NULL);
+
+ async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+ if (result_queue != NULL) {
+ if (async_context != NULL)
+ *result_queue = &async_context->result_queue;
+ else
+ *result_queue = NULL;
+ }
+
+ return simple;
+}
+
diff --git a/calendar/libedata-cal/e-cal-backend.h b/calendar/libedata-cal/e-cal-backend.h
index 358b4c2..7779f58 100644
--- a/calendar/libedata-cal/e-cal-backend.h
+++ b/calendar/libedata-cal/e-cal-backend.h
@@ -1,23 +1,19 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/* Evolution calendar - generic backend class
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- * Authors: Federico Mena-Quintero <federico ximian com>
- * Rodrigo Moya <rodrigo ximian com>
+/*
+ * e-cal-backend.h
*
* This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
- * License as published by the Free Software Foundation.
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
*
* 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 Lesser General Public License for more details.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
*
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#if !defined (__LIBEDATA_CAL_H_INSIDE__) && !defined (LIBEDATA_CAL_COMPILATION)
@@ -275,91 +271,229 @@ void e_cal_backend_remove_view (ECalBackend *backend,
EDataCalView *view);
GList * e_cal_backend_list_views (ECalBackend *backend);
+gchar * e_cal_backend_get_backend_property_sync
+ (ECalBackend *backend,
+ const gchar *prop_name,
+ GCancellable *cancellable,
+ GError **error);
void e_cal_backend_get_backend_property
(ECalBackend *backend,
- EDataCal *cal,
- guint32 opid,
+ const gchar *prop_name,
GCancellable *cancellable,
- const gchar *prop_name);
-
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gchar * e_cal_backend_get_backend_property_finish
+ (ECalBackend *backend,
+ GAsyncResult *result,
+ GError **error);
+gboolean e_cal_backend_open_sync (ECalBackend *backend,
+ GCancellable *cancellable,
+ GError **error);
void e_cal_backend_open (ECalBackend *backend,
- EDataCal *cal,
- guint32 opid,
GCancellable *cancellable,
- gboolean only_if_exists);
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean e_cal_backend_open_finish (ECalBackend *backend,
+ GAsyncResult *result,
+ GError **error);
+gboolean e_cal_backend_refresh_sync (ECalBackend *backend,
+ GCancellable *cancellable,
+ GError **error);
void e_cal_backend_refresh (ECalBackend *backend,
- EDataCal *cal,
- guint32 opid,
- GCancellable *cancellable);
-void e_cal_backend_get_object (ECalBackend *backend,
- EDataCal *cal,
- guint32 opid,
GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean e_cal_backend_refresh_finish (ECalBackend *backend,
+ GAsyncResult *result,
+ GError **error);
+ECalComponent * e_cal_backend_get_object_sync (ECalBackend *backend,
const gchar *uid,
- const gchar *rid);
+ const gchar *rid,
+ GCancellable *cancellable,
+ GError **error);
+void e_cal_backend_get_object (ECalBackend *backend,
+ const gchar *uid,
+ const gchar *rid,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+ECalComponent * e_cal_backend_get_object_finish (ECalBackend *backend,
+ GAsyncResult *result,
+ GError **error);
+gboolean e_cal_backend_get_object_list_sync
+ (ECalBackend *backend,
+ const gchar *query,
+ GQueue *out_objects,
+ GCancellable *cancellable,
+ GError **error);
void e_cal_backend_get_object_list (ECalBackend *backend,
- EDataCal *cal,
- guint32 opid,
+ const gchar *query,
GCancellable *cancellable,
- const gchar *sexp);
-void e_cal_backend_get_free_busy (ECalBackend *backend,
- EDataCal *cal,
- guint32 opid,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean e_cal_backend_get_object_list_finish
+ (ECalBackend *backend,
+ GAsyncResult *result,
+ GQueue *out_objects,
+ GError **error);
+gboolean e_cal_backend_get_free_busy_sync
+ (ECalBackend *backend,
+ time_t start,
+ time_t end,
+ const gchar * const *users,
GCancellable *cancellable,
- const GSList *users,
+ GError **error);
+void e_cal_backend_get_free_busy (ECalBackend *backend,
time_t start,
- time_t end);
+ time_t end,
+ const gchar * const *users,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean e_cal_backend_get_free_busy_finish
+ (ECalBackend *backend,
+ GAsyncResult *result,
+ GError **error);
+gboolean e_cal_backend_create_objects_sync
+ (ECalBackend *backend,
+ const gchar * const *calobjs,
+ GQueue *out_uids,
+ GCancellable *cancellable,
+ GError **error);
void e_cal_backend_create_objects (ECalBackend *backend,
- EDataCal *cal,
- guint32 opid,
+ const gchar * const *calobjs,
GCancellable *cancellable,
- const GSList *calobjs);
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean e_cal_backend_create_objects_finish
+ (ECalBackend *backend,
+ GAsyncResult *result,
+ GQueue *out_uids,
+ GError **error);
+gboolean e_cal_backend_modify_objects_sync
+ (ECalBackend *backend,
+ const gchar * const *calobjs,
+ ECalObjModType mod,
+ GCancellable *cancellable,
+ GError **error);
void e_cal_backend_modify_objects (ECalBackend *backend,
- EDataCal *cal,
- guint32 opid,
+ const gchar * const *calobjs,
+ ECalObjModType mod,
GCancellable *cancellable,
- const GSList *calobjs,
- ECalObjModType mod);
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean e_cal_backend_modify_objects_finish
+ (ECalBackend *backend,
+ GAsyncResult *result,
+ GError **error);
+gboolean e_cal_backend_remove_objects_sync
+ (ECalBackend *backend,
+ GList *component_ids,
+ ECalObjModType mod,
+ GCancellable *cancellable,
+ GError **error);
void e_cal_backend_remove_objects (ECalBackend *backend,
- EDataCal *cal,
- guint32 opid,
+ GList *component_ids,
+ ECalObjModType mod,
GCancellable *cancellable,
- const GSList *ids,
- ECalObjModType mod);
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean e_cal_backend_remove_objects_finish
+ (ECalBackend *backend,
+ GAsyncResult *result,
+ GError **error);
+gboolean e_cal_backend_receive_objects_sync
+ (ECalBackend *backend,
+ const gchar *calobj,
+ GCancellable *cancellable,
+ GError **error);
void e_cal_backend_receive_objects (ECalBackend *backend,
- EDataCal *cal,
- guint32 opid,
+ const gchar *calobj,
GCancellable *cancellable,
- const gchar *calobj);
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean e_cal_backend_receive_objects_finish
+ (ECalBackend *backend,
+ GAsyncResult *result,
+ GError **error);
+ECalComponent * e_cal_backend_send_objects_sync (ECalBackend *backend,
+ const gchar *calobj,
+ GQueue *out_users,
+ GCancellable *cancellable,
+ GError **error);
void e_cal_backend_send_objects (ECalBackend *backend,
- EDataCal *cal,
- guint32 opid,
+ const gchar *calobj,
GCancellable *cancellable,
- const gchar *calobj);
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+ECalComponent * e_cal_backend_send_objects_finish
+ (ECalBackend *backend,
+ GAsyncResult *result,
+ GQueue *out_users,
+ GError **error);
+gboolean e_cal_backend_get_attachment_uris_sync
+ (ECalBackend *backend,
+ const gchar *uid,
+ const gchar *rid,
+ GQueue *out_attachment_uris,
+ GCancellable *cancellable,
+ GError **error);
void e_cal_backend_get_attachment_uris
(ECalBackend *backend,
- EDataCal *cal,
- guint32 opid,
+ const gchar *uid,
+ const gchar *rid,
GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean e_cal_backend_get_attachment_uris_finish
+ (ECalBackend *backend,
+ GAsyncResult *result,
+ GQueue *out_attachment_uris,
+ GError **error);
+gboolean e_cal_backend_discard_alarm_sync
+ (ECalBackend *backend,
const gchar *uid,
- const gchar *rid);
-void e_cal_backend_discard_alarm (ECalBackend *backend,
- EDataCal *cal,
- guint32 opid,
+ const gchar *rid,
+ const gchar *alarm_uid,
GCancellable *cancellable,
+ GError **error);
+void e_cal_backend_discard_alarm (ECalBackend *backend,
const gchar *uid,
const gchar *rid,
- const gchar *auid);
+ const gchar *alarm_uid,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean e_cal_backend_discard_alarm_finish
+ (ECalBackend *backend,
+ GAsyncResult *result,
+ GError **error);
+gchar * e_cal_backend_get_timezone_sync (ECalBackend *backend,
+ const gchar *tzid,
+ GCancellable *cancellable,
+ GError **error);
void e_cal_backend_get_timezone (ECalBackend *backend,
- EDataCal *cal,
- guint32 opid,
+ const gchar *tzid,
GCancellable *cancellable,
- const gchar *tzid);
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gchar * e_cal_backend_get_timezone_finish
+ (ECalBackend *backend,
+ GAsyncResult *result,
+ GError **error);
+gboolean e_cal_backend_add_timezone_sync (ECalBackend *backend,
+ const gchar *tzobject,
+ GCancellable *cancellable,
+ GError **error);
void e_cal_backend_add_timezone (ECalBackend *backend,
- EDataCal *cal,
- guint32 opid,
+ const gchar *tzobject,
GCancellable *cancellable,
- const gchar *tzobject);
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean e_cal_backend_add_timezone_finish
+ (ECalBackend *backend,
+ GAsyncResult *result,
+ GError **error);
void e_cal_backend_start_view (ECalBackend *backend,
EDataCalView *view);
void e_cal_backend_stop_view (ECalBackend *backend,
@@ -392,6 +526,12 @@ void e_cal_backend_empty_cache (ECalBackend *backend,
void e_cal_backend_set_is_removed (ECalBackend *backend,
gboolean is_removed);
+GSimpleAsyncResult *
+ e_cal_backend_prepare_for_completion
+ (ECalBackend *backend,
+ guint opid,
+ GQueue **result_queue);
+
G_END_DECLS
#endif /* E_CAL_BACKEND_H */
diff --git a/calendar/libedata-cal/e-data-cal.c b/calendar/libedata-cal/e-data-cal.c
index 7b79e7a..a570c7f 100644
--- a/calendar/libedata-cal/e-data-cal.c
+++ b/calendar/libedata-cal/e-data-cal.c
@@ -1,25 +1,19 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/* Evolution calendar client interface object
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- * Copyright (C) 2009 Intel Corporation
- *
- * Authors: Federico Mena-Quintero <federico ximian com>
- * Rodrigo Moya <rodrigo ximian com>
- * Ross Burton <ross linux intel com>
+/*
+ * e-data-cal.c
*
* This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
- * License as published by the Free Software Foundation.
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
*
* 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 Lesser General Public License for more details.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
*
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
@@ -46,6 +40,8 @@
#define EDC_ERROR(_code) e_data_cal_create_error (_code, NULL)
#define EDC_ERROR_EX(_code, _msg) e_data_cal_create_error (_code, _msg)
+typedef struct _AsyncContext AsyncContext;
+
struct _EDataCalPrivate {
GDBusConnection *connection;
EDBusCalendar *dbus_interface;
@@ -54,14 +50,16 @@ struct _EDataCalPrivate {
gboolean opened;
- GRecMutex pending_ops_lock;
- GHashTable *pending_ops; /* opid -> OperationData */
+ GMutex sender_lock;
+ GHashTable *sender_table;
+};
- /* Operations are queued while an
- * open operation is in progress. */
- GMutex open_lock;
- guint32 open_opid;
- GQueue open_queue;
+struct _AsyncContext {
+ EDataCal *data_cal;
+ EDBusCalendar *interface;
+ GDBusMethodInvocation *invocation;
+ GCancellable *cancellable;
+ guint watcher_id;
};
enum {
@@ -71,90 +69,6 @@ enum {
PROP_OBJECT_PATH
};
-static EOperationPool *ops_pool = NULL;
-
-typedef enum {
- OP_OPEN,
- OP_REFRESH,
- OP_GET_BACKEND_PROPERTY,
- OP_GET_OBJECT,
- OP_GET_OBJECT_LIST,
- OP_GET_FREE_BUSY,
- OP_CREATE_OBJECTS,
- OP_MODIFY_OBJECTS,
- OP_REMOVE_OBJECTS,
- OP_RECEIVE_OBJECTS,
- OP_SEND_OBJECTS,
- OP_GET_ATTACHMENT_URIS,
- OP_DISCARD_ALARM,
- OP_GET_VIEW,
- OP_GET_TIMEZONE,
- OP_ADD_TIMEZONE,
- OP_CLOSE
-} OperationID;
-
-typedef struct {
- volatile gint ref_count;
-
- OperationID op;
- guint32 id; /* operation id */
- EDataCal *cal;
- ECalBackend *backend;
- GCancellable *cancellable;
- GDBusMethodInvocation *invocation;
- const gchar *sender; /* owned by invocation */
- guint watcher_id;
-
- union {
- /* OP_GET_OBJECT */
- /* OP_GET_ATTACHMENT_URIS */
- struct _ur {
- gchar *uid;
- gchar *rid;
- } ur;
- /* OP_DISCARD_ALARM */
- struct _ura {
- gchar *uid;
- gchar *rid;
- gchar *auid;
- } ura;
- /* OP_GET_OBJECT_LIST */
- /* OP_GET_VIEW */
- gchar *sexp;
- /* OP_GET_FREE_BUSY */
- struct _free_busy {
- time_t start, end;
- GSList *users;
- } fb;
- /* OP_CREATE_OBJECTS */
- GSList *calobjs;
- /* OP_RECEIVE_OBJECTS */
- /* OP_SEND_OBJECTS */
- struct _co {
- gchar *calobj;
- } co;
- /* OP_MODIFY_OBJECTS */
- struct _mo {
- GSList *calobjs;
- ECalObjModType mod;
- } mo;
- /* OP_REMOVE_OBJECTS */
- struct _ro {
- GSList *ids;
- ECalObjModType mod;
- } ro;
- /* OP_GET_TIMEZONE */
- gchar *tzid;
- /* OP_ADD_TIMEZONE */
- gchar *tzobject;
- /* OP_GET_BACKEND_PROPERTY */
- const gchar *prop_name;
-
- /* OP_REFRESH */
- /* OP_CLOSE */
- } d;
-} OperationData;
-
/* Forward Declarations */
static void e_data_cal_initable_init (GInitableIface *interface);
@@ -166,205 +80,131 @@ G_DEFINE_TYPE_WITH_CODE (
G_TYPE_INITABLE,
e_data_cal_initable_init))
-/* Function to get a new EDataCalView path, used by get_view below */
-static gchar *
-construct_calview_path (void)
-{
- static guint counter = 1;
- return g_strdup_printf ("/org/gnome/evolution/dataserver/CalendarView/%d/%d", getpid (), counter++);
-}
-
-static OperationData *
-op_ref (OperationData *data)
-{
- g_return_val_if_fail (data != NULL, data);
- g_return_val_if_fail (data->ref_count > 0, data);
-
- g_atomic_int_inc (&data->ref_count);
-
- return data;
-}
-
static void
-op_sender_vanished_cb (GDBusConnection *connection,
- const gchar *sender,
- GCancellable *cancellable)
+sender_vanished_cb (GDBusConnection *connection,
+ const gchar *sender,
+ GCancellable *cancellable)
{
g_cancellable_cancel (cancellable);
}
-static OperationData *
-op_new (OperationID op,
- EDataCal *cal,
- ECalBackend *backend,
- GDBusMethodInvocation *invocation)
+static void
+sender_table_insert (EDataCal *data_cal,
+ const gchar *sender,
+ GCancellable *cancellable)
{
- OperationData *data;
-
- data = g_slice_new0 (OperationData);
- data->ref_count = 1;
- data->op = op;
- data->id = e_operation_pool_reserve_opid (ops_pool);
- data->cal = g_object_ref (cal);
- data->backend = g_object_ref (backend);
- data->cancellable = g_cancellable_new ();
+ GHashTable *sender_table;
+ GPtrArray *array;
- /* This is optional so we can fake client requests. */
- if (invocation != NULL) {
- GDBusConnection *connection;
+ g_return_if_fail (sender != NULL);
- data->invocation = g_object_ref (invocation);
- data->sender = g_dbus_method_invocation_get_sender (invocation);
+ g_mutex_lock (&data_cal->priv->sender_lock);
- connection = e_data_cal_get_connection (cal);
+ sender_table = data_cal->priv->sender_table;
+ array = g_hash_table_lookup (sender_table, sender);
- data->watcher_id = g_bus_watch_name_on_connection (
- connection, data->sender,
- G_BUS_NAME_WATCHER_FLAGS_NONE,
- (GBusNameAppearedCallback) NULL,
- (GBusNameVanishedCallback) op_sender_vanished_cb,
- g_object_ref (data->cancellable),
+ if (array == NULL) {
+ array = g_ptr_array_new_with_free_func (
(GDestroyNotify) g_object_unref);
+ g_hash_table_insert (
+ sender_table, g_strdup (sender), array);
}
- g_rec_mutex_lock (&cal->priv->pending_ops_lock);
- g_hash_table_insert (
- cal->priv->pending_ops,
- GUINT_TO_POINTER (data->id),
- op_ref (data));
- g_rec_mutex_unlock (&cal->priv->pending_ops_lock);
+ g_ptr_array_add (array, g_object_ref (cancellable));
- return data;
+ g_mutex_unlock (&data_cal->priv->sender_lock);
}
-static void
-op_unref (OperationData *data)
-{
- g_return_if_fail (data != NULL);
- g_return_if_fail (data->ref_count > 0);
-
- if (g_atomic_int_dec_and_test (&data->ref_count)) {
-
- switch (data->op) {
- case OP_GET_OBJECT:
- case OP_GET_ATTACHMENT_URIS:
- g_free (data->d.ur.uid);
- g_free (data->d.ur.rid);
- break;
- case OP_DISCARD_ALARM:
- g_free (data->d.ura.uid);
- g_free (data->d.ura.rid);
- g_free (data->d.ura.auid);
- break;
- case OP_GET_OBJECT_LIST:
- case OP_GET_VIEW:
- g_free (data->d.sexp);
- break;
- case OP_GET_FREE_BUSY:
- g_slist_free_full (
- data->d.fb.users,
- (GDestroyNotify) g_free);
- break;
- case OP_CREATE_OBJECTS:
- g_slist_free_full (
- data->d.calobjs,
- (GDestroyNotify) g_free);
- break;
- case OP_RECEIVE_OBJECTS:
- case OP_SEND_OBJECTS:
- g_free (data->d.co.calobj);
- break;
- case OP_MODIFY_OBJECTS:
- g_slist_free_full (
- data->d.mo.calobjs,
- (GDestroyNotify) g_free);
- break;
- case OP_REMOVE_OBJECTS:
- g_slist_free_full (
- data->d.ro.ids, (GDestroyNotify)
- e_cal_component_free_id);
- break;
- case OP_GET_TIMEZONE:
- g_free (data->d.tzid);
- break;
- case OP_ADD_TIMEZONE:
- g_free (data->d.tzobject);
- break;
- default:
- break;
- }
+static gboolean
+sender_table_remove (EDataCal *data_cal,
+ const gchar *sender,
+ GCancellable *cancellable)
+{
+ GHashTable *sender_table;
+ GPtrArray *array;
+ gboolean removed = FALSE;
- g_object_unref (data->cal);
- g_object_unref (data->backend);
- g_object_unref (data->cancellable);
+ g_return_val_if_fail (sender != NULL, FALSE);
- if (data->invocation != NULL)
- g_object_unref (data->invocation);
+ g_mutex_lock (&data_cal->priv->sender_lock);
- if (data->watcher_id > 0)
- g_bus_unwatch_name (data->watcher_id);
+ sender_table = data_cal->priv->sender_table;
+ array = g_hash_table_lookup (sender_table, sender);
- g_slice_free (OperationData, data);
+ if (array != NULL) {
+ removed = g_ptr_array_remove_fast (array, cancellable);
+
+ if (array->len == 0)
+ g_hash_table_remove (sender_table, sender);
}
+
+ g_mutex_unlock (&data_cal->priv->sender_lock);
+
+ return removed;
}
-static void
-op_dispatch (EDataCal *cal,
- OperationData *data)
+static AsyncContext *
+async_context_new (EDataCal *data_cal,
+ GDBusMethodInvocation *invocation)
{
- g_mutex_lock (&cal->priv->open_lock);
+ AsyncContext *async_context;
+ EDBusCalendar *interface;
- /* If an open operation is currently in progress, queue this
- * operation to be dispatched when the open operation finishes. */
- if (cal->priv->open_opid > 0) {
- g_queue_push_tail (&cal->priv->open_queue, data);
- } else {
- if (data->op == OP_OPEN)
- cal->priv->open_opid = data->id;
- e_operation_pool_push (ops_pool, data);
- }
+ interface = data_cal->priv->dbus_interface;
+
+ async_context = g_slice_new0 (AsyncContext);
+ async_context->data_cal = g_object_ref (data_cal);
+ async_context->interface = g_object_ref (interface);
+ async_context->invocation = g_object_ref (invocation);
+ async_context->cancellable = g_cancellable_new ();
+
+ async_context->watcher_id = g_bus_watch_name_on_connection (
+ g_dbus_method_invocation_get_connection (invocation),
+ g_dbus_method_invocation_get_sender (invocation),
+ G_BUS_NAME_WATCHER_FLAGS_NONE,
+ (GBusNameAppearedCallback) NULL,
+ (GBusNameVanishedCallback) sender_vanished_cb,
+ g_object_ref (async_context->cancellable),
+ (GDestroyNotify) g_object_ref);
+
+ sender_table_insert (
+ async_context->data_cal,
+ g_dbus_method_invocation_get_sender (invocation),
+ async_context->cancellable);
- g_mutex_unlock (&cal->priv->open_lock);
+ return async_context;
}
-static OperationData *
-op_claim (EDataCal *cal,
- guint32 opid)
+static void
+async_context_free (AsyncContext *async_context)
{
- OperationData *data;
+ sender_table_remove (
+ async_context->data_cal,
+ g_dbus_method_invocation_get_sender (
+ async_context->invocation),
+ async_context->cancellable);
- g_return_val_if_fail (E_IS_DATA_CAL (cal), NULL);
+ g_clear_object (&async_context->data_cal);
+ g_clear_object (&async_context->interface);
+ g_clear_object (&async_context->invocation);
+ g_clear_object (&async_context->cancellable);
- e_operation_pool_release_opid (ops_pool, opid);
-
- g_rec_mutex_lock (&cal->priv->pending_ops_lock);
- data = g_hash_table_lookup (
- cal->priv->pending_ops,
- GUINT_TO_POINTER (opid));
- if (data != NULL) {
- /* Steal the hash table's reference. */
- g_hash_table_steal (
- cal->priv->pending_ops,
- GUINT_TO_POINTER (opid));
- }
- g_rec_mutex_unlock (&cal->priv->pending_ops_lock);
+ if (async_context->watcher_id > 0)
+ g_bus_unwatch_name (async_context->watcher_id);
- return data;
+ g_slice_free (AsyncContext, async_context);
}
-static void
-op_complete (EDataCal *cal,
- guint32 opid)
+static gchar *
+construct_calview_path (void)
{
- g_return_if_fail (E_IS_DATA_CAL (cal));
+ static volatile gint counter = 1;
- e_operation_pool_release_opid (ops_pool, opid);
+ g_atomic_int_inc (&counter);
- g_rec_mutex_lock (&cal->priv->pending_ops_lock);
- g_hash_table_remove (
- cal->priv->pending_ops,
- GUINT_TO_POINTER (opid));
- g_rec_mutex_unlock (&cal->priv->pending_ops_lock);
+ return g_strdup_printf (
+ "/org/gnome/evolution/dataserver/CalendarView/%d/%d",
+ getpid (), counter);
}
static void
@@ -494,218 +334,6 @@ data_cal_convert_to_client_error (GError *error)
}
}
-static void
-cancel_operations_for_sender (EDataCal *cal,
- const gchar *sender)
-{
- GHashTableIter iter;
- gpointer value;
-
- g_return_if_fail (sender != NULL);
-
- g_rec_mutex_lock (&cal->priv->pending_ops_lock);
-
- g_hash_table_iter_init (&iter, cal->priv->pending_ops);
- while (g_hash_table_iter_next (&iter, NULL, &value)) {
- OperationData *op = value;
-
- if (op->sender != NULL && g_str_equal (sender, op->sender))
- g_cancellable_cancel (op->cancellable);
- }
-
- g_rec_mutex_unlock (&cal->priv->pending_ops_lock);
-}
-
-static void
-operation_thread (gpointer data,
- gpointer user_data)
-{
- OperationData *op = data;
-
- switch (op->op) {
- case OP_OPEN:
- e_cal_backend_open (
- op->backend, op->cal, op->id,
- op->cancellable, FALSE);
- break;
-
- case OP_REFRESH:
- e_cal_backend_refresh (
- op->backend, op->cal, op->id, op->cancellable);
- break;
-
- case OP_GET_BACKEND_PROPERTY:
- e_cal_backend_get_backend_property (
- op->backend, op->cal, op->id,
- op->cancellable, op->d.prop_name);
- break;
-
- case OP_GET_OBJECT:
- e_cal_backend_get_object (
- op->backend, op->cal, op->id,
- op->cancellable,
- op->d.ur.uid,
- op->d.ur.rid && *op->d.ur.rid ? op->d.ur.rid : NULL);
- break;
-
- case OP_GET_OBJECT_LIST:
- e_cal_backend_get_object_list (
- op->backend, op->cal, op->id,
- op->cancellable, op->d.sexp);
- break;
-
- case OP_GET_FREE_BUSY:
- e_cal_backend_get_free_busy (
- op->backend, op->cal, op->id,
- op->cancellable,
- op->d.fb.users,
- op->d.fb.start,
- op->d.fb.end);
- break;
-
- case OP_CREATE_OBJECTS:
- e_cal_backend_create_objects (
- op->backend, op->cal, op->id,
- op->cancellable, op->d.calobjs);
- break;
-
- case OP_MODIFY_OBJECTS:
- e_cal_backend_modify_objects (
- op->backend, op->cal, op->id,
- op->cancellable,
- op->d.mo.calobjs,
- op->d.mo.mod);
- break;
-
- case OP_REMOVE_OBJECTS:
- e_cal_backend_remove_objects (
- op->backend, op->cal, op->id,
- op->cancellable,
- op->d.ro.ids,
- op->d.ro.mod);
- break;
-
- case OP_RECEIVE_OBJECTS:
- e_cal_backend_receive_objects (
- op->backend, op->cal, op->id,
- op->cancellable, op->d.co.calobj);
- break;
-
- case OP_SEND_OBJECTS:
- e_cal_backend_send_objects (
- op->backend, op->cal, op->id,
- op->cancellable, op->d.co.calobj);
- break;
-
- case OP_GET_ATTACHMENT_URIS:
- e_cal_backend_get_attachment_uris (
- op->backend, op->cal, op->id,
- op->cancellable,
- op->d.ur.uid,
- op->d.ur.rid && *op->d.ur.rid ? op->d.ur.rid : NULL);
- break;
-
- case OP_DISCARD_ALARM:
- e_cal_backend_discard_alarm (
- op->backend, op->cal, op->id,
- op->cancellable,
- op->d.ura.uid,
- op->d.ura.rid && *op->d.ura.rid ? op->d.ura.rid : NULL,
- op->d.ura.auid);
- break;
-
- case OP_GET_VIEW:
- if (op->d.sexp) {
- EDataCalView *view;
- ECalBackendSExp *obj_sexp;
- GDBusConnection *connection;
- gchar *object_path;
- GError *error = NULL;
-
- /* we handle this entirely here, since it doesn't require any
- * backend involvement now that we have e_cal_view_start to
- * actually kick off the search. */
-
- obj_sexp = e_cal_backend_sexp_new (op->d.sexp);
- if (!obj_sexp) {
- g_dbus_method_invocation_return_error_literal (
- op->invocation,
- E_CLIENT_ERROR,
- E_CLIENT_ERROR_INVALID_QUERY,
- _("Invalid query"));
-
- op_complete (op->cal, op->id);
- break;
- }
-
- object_path = construct_calview_path ();
- connection = e_data_cal_get_connection (op->cal);
-
- view = e_data_cal_view_new (
- op->backend, obj_sexp,
- connection, object_path, &error);
-
- g_object_unref (obj_sexp);
-
- /* Sanity check. */
- g_return_if_fail (
- ((view != NULL) && (error == NULL)) ||
- ((view == NULL) && (error != NULL)));
-
- if (error != NULL) {
- /* Translators: This is a prefix to a detailed error message *
- */
- g_prefix_error (&error, "%s", _("Invalid query: "));
- data_cal_convert_to_client_error (error);
- g_dbus_method_invocation_take_error (
- op->invocation, error);
-
- op_complete (op->cal, op->id);
- g_free (object_path);
- break;
- }
-
- e_cal_backend_add_view (op->backend, view);
-
- e_dbus_calendar_complete_get_view (
- op->cal->priv->dbus_interface,
- op->invocation,
- object_path);
-
- op_complete (op->cal, op->id);
-
- g_object_unref (view);
- g_free (object_path);
- }
- break;
-
- case OP_GET_TIMEZONE:
- e_cal_backend_get_timezone (
- op->backend, op->cal, op->id,
- op->cancellable, op->d.tzid);
- break;
-
- case OP_ADD_TIMEZONE:
- e_cal_backend_add_timezone (
- op->backend, op->cal, op->id,
- op->cancellable, op->d.tzobject);
- break;
-
- case OP_CLOSE:
- if (op->sender != NULL)
- cancel_operations_for_sender (op->cal, op->sender);
-
- e_dbus_calendar_complete_close (
- op->cal->priv->dbus_interface,
- op->invocation);
-
- op_complete (op->cal, op->id);
- break;
- }
-
- op_unref (op);
-}
-
/* Create the EDataCal error quark */
GQuark
e_data_cal_error_quark (void)
@@ -855,171 +483,399 @@ e_data_cal_create_error_fmt (EDataCalCallStatus status,
return error;
}
+static void
+data_cal_complete_open_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ AsyncContext *async_context = user_data;
+ GError *error = NULL;
+
+ e_cal_backend_open_finish (
+ E_CAL_BACKEND (source_object), result, &error);
+
+ if (error == NULL) {
+ e_dbus_calendar_complete_open (
+ async_context->interface,
+ async_context->invocation);
+ } else {
+ g_dbus_method_invocation_take_error (
+ async_context->invocation, error);
+ }
+
+ async_context_free (async_context);
+}
+
static gboolean
data_cal_handle_open_cb (EDBusCalendar *interface,
GDBusMethodInvocation *invocation,
- EDataCal *cal)
+ EDataCal *data_cal)
{
- OperationData *op;
ECalBackend *backend;
+ AsyncContext *async_context;
- backend = e_data_cal_ref_backend (cal);
+ backend = e_data_cal_ref_backend (data_cal);
g_return_val_if_fail (backend != NULL, FALSE);
- op = op_new (OP_OPEN, cal, backend, invocation);
+ async_context = async_context_new (data_cal, invocation);
- op_dispatch (cal, op);
+ e_cal_backend_open (
+ backend,
+ async_context->cancellable,
+ data_cal_complete_open_cb,
+ async_context);
g_object_unref (backend);
return TRUE;
}
+static void
+data_cal_complete_refresh_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ AsyncContext *async_context = user_data;
+ GError *error = NULL;
+
+ e_cal_backend_refresh_finish (
+ E_CAL_BACKEND (source_object), result, &error);
+
+ if (error == NULL) {
+ e_dbus_calendar_complete_refresh (
+ async_context->interface,
+ async_context->invocation);
+ } else {
+ g_dbus_method_invocation_take_error (
+ async_context->invocation, error);
+ }
+
+ async_context_free (async_context);
+}
+
static gboolean
data_cal_handle_refresh_cb (EDBusCalendar *interface,
GDBusMethodInvocation *invocation,
- EDataCal *cal)
+ EDataCal *data_cal)
{
- OperationData *op;
ECalBackend *backend;
+ AsyncContext *async_context;
- backend = e_data_cal_ref_backend (cal);
+ backend = e_data_cal_ref_backend (data_cal);
g_return_val_if_fail (backend != NULL, FALSE);
- op = op_new (OP_REFRESH, cal, backend, invocation);
+ async_context = async_context_new (data_cal, invocation);
- op_dispatch (cal, op);
+ e_cal_backend_refresh (
+ backend,
+ async_context->cancellable,
+ data_cal_complete_refresh_cb,
+ async_context);
g_object_unref (backend);
return TRUE;
}
+static void
+data_cal_complete_get_object_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ AsyncContext *async_context = user_data;
+ ECalComponent *component;
+ GError *error = NULL;
+
+ component = e_cal_backend_get_object_finish (
+ E_CAL_BACKEND (source_object), result, &error);
+
+ /* Sanity check. */
+ g_return_if_fail (
+ ((component != NULL) && (error == NULL)) ||
+ ((component == NULL) && (error != NULL)));
+
+ if (error == NULL) {
+ gchar *string;
+ gchar *utf8_string;
+
+ string = e_cal_component_get_as_string (component);
+ utf8_string = e_util_utf8_make_valid (string);
+
+ e_dbus_calendar_complete_get_object (
+ async_context->interface,
+ async_context->invocation,
+ utf8_string);
+
+ g_free (utf8_string);
+ g_free (string);
+ } else {
+ g_dbus_method_invocation_take_error (
+ async_context->invocation, error);
+ }
+
+ async_context_free (async_context);
+}
+
static gboolean
data_cal_handle_get_object_cb (EDBusCalendar *interface,
GDBusMethodInvocation *invocation,
const gchar *in_uid,
const gchar *in_rid,
- EDataCal *cal)
+ EDataCal *data_cal)
{
- OperationData *op;
ECalBackend *backend;
-
- backend = e_data_cal_ref_backend (cal);
- g_return_val_if_fail (backend != NULL, FALSE);
+ AsyncContext *async_context;
/* Recurrence ID is optional. Its omission is denoted
* via D-Bus by an emptry string. Convert it to NULL. */
if (in_rid != NULL && *in_rid == '\0')
in_rid = NULL;
- op = op_new (OP_GET_OBJECT, cal, backend, invocation);
- op->d.ur.uid = g_strdup (in_uid);
- op->d.ur.rid = g_strdup (in_rid);
+ backend = e_data_cal_ref_backend (data_cal);
+ g_return_val_if_fail (backend != NULL, FALSE);
+
+ async_context = async_context_new (data_cal, invocation);
- op_dispatch (cal, op);
+ e_cal_backend_get_object (
+ backend,
+ in_uid, in_rid,
+ async_context->cancellable,
+ data_cal_complete_get_object_cb,
+ async_context);
g_object_unref (backend);
return TRUE;
}
+static void
+data_cal_complete_get_object_list_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ AsyncContext *async_context = user_data;
+ GQueue queue = G_QUEUE_INIT;
+ GError *error = NULL;
+
+ e_cal_backend_get_object_list_finish (
+ E_CAL_BACKEND (source_object), result, &queue, &error);
+
+ if (error == NULL) {
+ gchar **strv;
+ gint ii = 0;
+
+ strv = g_new0 (gchar *, queue.length + 1);
+
+ while (!g_queue_is_empty (&queue)) {
+ ECalComponent *component;
+ gchar *string;
+
+ component = g_queue_pop_head (&queue);
+
+ string = e_cal_component_get_as_string (component);
+ strv[ii++] = e_util_utf8_make_valid (string);
+ g_free (string);
+
+ g_object_unref (component);
+ }
+
+ e_dbus_calendar_complete_get_object_list (
+ async_context->interface,
+ async_context->invocation,
+ (const gchar * const *) strv);
+
+ g_strfreev (strv);
+ } else {
+ g_dbus_method_invocation_take_error (
+ async_context->invocation, error);
+ }
+
+ async_context_free (async_context);
+}
+
static gboolean
data_cal_handle_get_object_list_cb (EDBusCalendar *interface,
GDBusMethodInvocation *invocation,
- const gchar *in_sexp,
- EDataCal *cal)
+ const gchar *in_query,
+ EDataCal *data_cal)
{
- OperationData *op;
ECalBackend *backend;
+ AsyncContext *async_context;
- backend = e_data_cal_ref_backend (cal);
+ backend = e_data_cal_ref_backend (data_cal);
g_return_val_if_fail (backend != NULL, FALSE);
- op = op_new (OP_GET_OBJECT_LIST, cal, backend, invocation);
- op->d.sexp = g_strdup (in_sexp);
+ async_context = async_context_new (data_cal, invocation);
- op_dispatch (cal, op);
+ e_cal_backend_get_object_list (
+ backend,
+ in_query,
+ async_context->cancellable,
+ data_cal_complete_get_object_list_cb,
+ async_context);
g_object_unref (backend);
return TRUE;
}
+static void
+data_cal_complete_get_free_busy_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ AsyncContext *async_context = user_data;
+ GError *error = NULL;
+
+ e_cal_backend_get_free_busy_finish (
+ E_CAL_BACKEND (source_object), result, &error);
+
+ if (error == NULL) {
+ e_dbus_calendar_complete_get_free_busy (
+ async_context->interface,
+ async_context->invocation);
+ } else {
+ g_dbus_method_invocation_take_error (
+ async_context->invocation, error);
+ }
+
+ async_context_free (async_context);
+}
+
static gboolean
data_cal_handle_get_free_busy_cb (EDBusCalendar *interface,
GDBusMethodInvocation *invocation,
gint64 in_start,
gint64 in_end,
- const gchar **in_users,
- EDataCal *cal)
+ const gchar * const *in_users,
+ EDataCal *data_cal)
{
- OperationData *op;
ECalBackend *backend;
- GSList *tmp = NULL;
- gint ii;
+ AsyncContext *async_context;
- backend = e_data_cal_ref_backend (cal);
+ backend = e_data_cal_ref_backend (data_cal);
g_return_val_if_fail (backend != NULL, FALSE);
- for (ii = 0; in_users[ii] != NULL; ii++)
- tmp = g_slist_prepend (tmp, g_strdup (in_users[ii]));
+ async_context = async_context_new (data_cal, invocation);
- op = op_new (OP_GET_FREE_BUSY, cal, backend, invocation);
- op->d.fb.start = (time_t) in_start;
- op->d.fb.end = (time_t) in_end;
- op->d.fb.users = g_slist_reverse (tmp);
-
- op_dispatch (cal, op);
+ e_cal_backend_get_free_busy (
+ backend,
+ (time_t) in_start,
+ (time_t) in_end,
+ in_users,
+ async_context->cancellable,
+ data_cal_complete_get_free_busy_cb,
+ async_context);
g_object_unref (backend);
return TRUE;
}
+static void
+data_cal_complete_create_objects_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ AsyncContext *async_context = user_data;
+ GQueue queue = G_QUEUE_INIT;
+ GError *error = NULL;
+
+ e_cal_backend_create_objects_finish (
+ E_CAL_BACKEND (source_object), result, &queue, &error);
+
+ if (error == NULL) {
+ gchar **strv;
+ gint ii = 0;
+
+ strv = g_new0 (gchar *, queue.length + 1);
+
+ while (!g_queue_is_empty (&queue)) {
+ gchar *uid;
+
+ uid = g_queue_pop_head (&queue);
+ strv[ii++] = e_util_utf8_make_valid (uid);
+ g_free (uid);
+ }
+
+ e_dbus_calendar_complete_create_objects (
+ async_context->interface,
+ async_context->invocation,
+ (const gchar * const *) strv);
+
+ g_strfreev (strv);
+ } else {
+ g_dbus_method_invocation_take_error (
+ async_context->invocation, error);
+ }
+
+ async_context_free (async_context);
+}
+
static gboolean
data_cal_handle_create_objects_cb (EDBusCalendar *interface,
GDBusMethodInvocation *invocation,
- const gchar **in_calobjs,
- EDataCal *cal)
+ const gchar * const *in_calobjs,
+ EDataCal *data_cal)
{
- OperationData *op;
ECalBackend *backend;
- GSList *tmp = NULL;
- gint ii;
+ AsyncContext *async_context;
- backend = e_data_cal_ref_backend (cal);
+ backend = e_data_cal_ref_backend (data_cal);
g_return_val_if_fail (backend != NULL, FALSE);
- for (ii = 0; in_calobjs[ii] != NULL; ii++)
- tmp = g_slist_prepend (tmp, g_strdup (in_calobjs[ii]));
+ async_context = async_context_new (data_cal, invocation);
- op = op_new (OP_CREATE_OBJECTS, cal, backend, invocation);
- op->d.calobjs = g_slist_reverse (tmp);
-
- op_dispatch (cal, op);
+ e_cal_backend_create_objects (
+ backend,
+ in_calobjs,
+ async_context->cancellable,
+ data_cal_complete_create_objects_cb,
+ async_context);
g_object_unref (backend);
return TRUE;
}
+static void
+data_cal_complete_modify_objects_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ AsyncContext *async_context = user_data;
+ GError *error = NULL;
+
+ e_cal_backend_modify_objects_finish (
+ E_CAL_BACKEND (source_object), result, &error);
+
+ if (error == NULL) {
+ e_dbus_calendar_complete_modify_objects (
+ async_context->interface,
+ async_context->invocation);
+ } else {
+ g_dbus_method_invocation_take_error (
+ async_context->invocation, error);
+ }
+
+ async_context_free (async_context);
+}
+
static gboolean
data_cal_handle_modify_objects_cb (EDBusCalendar *interface,
GDBusMethodInvocation *invocation,
- const gchar **in_ics_objects,
+ const gchar * const *in_ics_objects,
const gchar *in_mod_type,
- EDataCal *cal)
+ EDataCal *data_cal)
{
+ ECalBackend *backend;
+ AsyncContext *async_context;
GFlagsClass *flags_class;
ECalObjModType mod = 0;
- OperationData *op;
- ECalBackend *backend;
- GSList *tmp = NULL;
gchar **flags_strv;
gint ii;
- backend = e_data_cal_ref_backend (cal);
+ backend = e_data_cal_ref_backend (data_cal);
g_return_val_if_fail (backend != NULL, FALSE);
flags_class = g_type_class_ref (E_TYPE_CAL_OBJ_MOD_TYPE);
@@ -1040,36 +896,59 @@ data_cal_handle_modify_objects_cb (EDBusCalendar *interface,
g_strfreev (flags_strv);
g_type_class_unref (flags_class);
- for (ii = 0; in_ics_objects[ii] != NULL; ii++)
- tmp = g_slist_prepend (tmp, g_strdup (in_ics_objects[ii]));
+ async_context = async_context_new (data_cal, invocation);
- op = op_new (OP_MODIFY_OBJECTS, cal, backend, invocation);
- op->d.mo.calobjs = g_slist_reverse (tmp);
- op->d.mo.mod = mod;
-
- op_dispatch (cal, op);
+ e_cal_backend_modify_objects (
+ backend,
+ in_ics_objects, mod,
+ async_context->cancellable,
+ data_cal_complete_modify_objects_cb,
+ async_context);
g_object_unref (backend);
return TRUE;
}
+static void
+data_cal_complete_remove_objects_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ AsyncContext *async_context = user_data;
+ GError *error = NULL;
+
+ e_cal_backend_remove_objects_finish (
+ E_CAL_BACKEND (source_object), result, &error);
+
+ if (error == NULL) {
+ e_dbus_calendar_complete_remove_objects (
+ async_context->interface,
+ async_context->invocation);
+ } else {
+ g_dbus_method_invocation_take_error (
+ async_context->invocation, error);
+ }
+
+ async_context_free (async_context);
+}
+
static gboolean
data_cal_handle_remove_objects_cb (EDBusCalendar *interface,
GDBusMethodInvocation *invocation,
GVariant *in_uid_rid_array,
const gchar *in_mod_type,
- EDataCal *cal)
+ EDataCal *data_cal)
{
+ ECalBackend *backend;
+ AsyncContext *async_context;
GFlagsClass *flags_class;
ECalObjModType mod = 0;
- OperationData *op;
- ECalBackend *backend;
- GSList *tmp = NULL;
+ GQueue component_ids = G_QUEUE_INIT;
gchar **flags_strv;
gsize n_children, ii;
- backend = e_data_cal_ref_backend (cal);
+ backend = e_data_cal_ref_backend (data_cal);
g_return_val_if_fail (backend != NULL, FALSE);
flags_class = g_type_class_ref (E_TYPE_CAL_OBJ_MOD_TYPE);
@@ -1114,91 +993,249 @@ data_cal_handle_remove_objects_cb (EDBusCalendar *interface,
id->rid = NULL;
}
- tmp = g_slist_prepend (tmp, id);
+ g_queue_push_tail (&component_ids, id);
}
- op = op_new (OP_REMOVE_OBJECTS, cal, backend, invocation);
- op->d.ro.ids = g_slist_reverse (tmp);
- op->d.ro.mod = mod;
+ async_context = async_context_new (data_cal, invocation);
+
+ e_cal_backend_remove_objects (
+ backend,
+ component_ids.head, mod,
+ async_context->cancellable,
+ data_cal_complete_remove_objects_cb,
+ async_context);
- op_dispatch (cal, op);
+ while (!g_queue_is_empty (&component_ids))
+ e_cal_component_free_id (g_queue_pop_head (&component_ids));
g_object_unref (backend);
return TRUE;
}
+static void
+data_cal_complete_receive_objects_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ AsyncContext *async_context = user_data;
+ GError *error = NULL;
+
+ e_cal_backend_receive_objects_finish (
+ E_CAL_BACKEND (source_object), result, &error);
+
+ if (error == NULL) {
+ e_dbus_calendar_complete_receive_objects (
+ async_context->interface,
+ async_context->invocation);
+ } else {
+ g_dbus_method_invocation_take_error (
+ async_context->invocation, error);
+ }
+
+ async_context_free (async_context);
+}
+
static gboolean
data_cal_handle_receive_objects_cb (EDBusCalendar *interface,
GDBusMethodInvocation *invocation,
const gchar *in_calobj,
- EDataCal *cal)
+ EDataCal *data_cal)
{
- OperationData *op;
ECalBackend *backend;
+ AsyncContext *async_context;
- backend = e_data_cal_ref_backend (cal);
+ backend = e_data_cal_ref_backend (data_cal);
g_return_val_if_fail (backend != NULL, FALSE);
- op = op_new (OP_RECEIVE_OBJECTS, cal, backend, invocation);
- op->d.co.calobj = g_strdup (in_calobj);
+ async_context = async_context_new (data_cal, invocation);
- op_dispatch (cal, op);
+ e_cal_backend_receive_objects (
+ backend,
+ in_calobj,
+ async_context->cancellable,
+ data_cal_complete_receive_objects_cb,
+ async_context);
g_object_unref (backend);
return TRUE;
}
+static void
+data_cal_complete_send_objects_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ AsyncContext *async_context = user_data;
+ ECalComponent *component;
+ GQueue queue = G_QUEUE_INIT;
+ GError *error = NULL;
+
+ component = e_cal_backend_send_objects_finish (
+ E_CAL_BACKEND (source_object), result, &queue, &error);
+
+ /* Sanity check. */
+ g_return_if_fail (
+ ((component != NULL) && (error == NULL)) ||
+ ((component == NULL) && (error != NULL)));
+
+ if (component != NULL) {
+ gchar **strv;
+ gchar *string;
+ gchar *utf8_string;
+ gint ii = 0;
+
+ strv = g_new0 (gchar *, queue.length + 1);
+
+ while (!g_queue_is_empty (&queue)) {
+ gchar *user;
+
+ user = g_queue_pop_head (&queue);
+ strv[ii++] = e_util_utf8_make_valid (user);
+ g_free (user);
+ }
+
+ string = e_cal_component_get_as_string (component);
+ utf8_string = e_util_utf8_make_valid (string);
+
+ e_dbus_calendar_complete_send_objects (
+ async_context->interface,
+ async_context->invocation,
+ (const gchar * const *) strv,
+ utf8_string);
+
+ g_free (utf8_string);
+ g_free (string);
+
+ g_strfreev (strv);
+ } else {
+ g_dbus_method_invocation_take_error (
+ async_context->invocation, error);
+ }
+
+ async_context_free (async_context);
+}
+
static gboolean
data_cal_handle_send_objects_cb (EDBusCalendar *interface,
GDBusMethodInvocation *invocation,
const gchar *in_calobj,
- EDataCal *cal)
+ EDataCal *data_cal)
{
- OperationData *op;
ECalBackend *backend;
+ AsyncContext *async_context;
- backend = e_data_cal_ref_backend (cal);
+ backend = e_data_cal_ref_backend (data_cal);
g_return_val_if_fail (backend != NULL, FALSE);
- op = op_new (OP_SEND_OBJECTS, cal, backend, invocation);
- op->d.co.calobj = g_strdup (in_calobj);
+ async_context = async_context_new (data_cal, invocation);
- op_dispatch (cal, op);
+ e_cal_backend_send_objects (
+ backend,
+ in_calobj,
+ async_context->cancellable,
+ data_cal_complete_send_objects_cb,
+ async_context);
g_object_unref (backend);
return TRUE;
}
+static void
+data_cal_complete_get_attachment_uris_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ AsyncContext *async_context = user_data;
+ GQueue queue = G_QUEUE_INIT;
+ GError *error = NULL;
+
+ e_cal_backend_get_attachment_uris_finish (
+ E_CAL_BACKEND (source_object), result, &queue, &error);
+
+ if (error == NULL) {
+ gchar **strv;
+ gint ii = 0;
+
+ strv = g_new0 (gchar *, queue.length + 1);
+
+ while (!g_queue_is_empty (&queue)) {
+ gchar *uri;
+
+ uri = g_queue_pop_head (&queue);
+ strv[ii++] = e_util_utf8_make_valid (uri);
+ g_free (uri);
+ }
+
+ e_dbus_calendar_complete_get_attachment_uris (
+ async_context->interface,
+ async_context->invocation,
+ (const gchar * const *) strv);
+
+ g_strfreev (strv);
+ } else {
+ g_dbus_method_invocation_take_error (
+ async_context->invocation, error);
+ }
+
+ async_context_free (async_context);
+}
+
static gboolean
data_cal_handle_get_attachment_uris_cb (EDBusCalendar *interface,
GDBusMethodInvocation *invocation,
const gchar *in_uid,
const gchar *in_rid,
- EDataCal *cal)
+ EDataCal *data_cal)
{
- OperationData *op;
ECalBackend *backend;
-
- backend = e_data_cal_ref_backend (cal);
- g_return_val_if_fail (backend != NULL, FALSE);
+ AsyncContext *async_context;
/* Recurrence ID is optional. Its omission is denoted
* via D-Bus by an empty string. Convert it to NULL. */
if (in_rid != NULL && *in_rid == '\0')
in_rid = NULL;
- op = op_new (OP_GET_ATTACHMENT_URIS, cal, backend, invocation);
- op->d.ur.uid = g_strdup (in_uid);
- op->d.ur.rid = g_strdup (in_rid);
+ backend = e_data_cal_ref_backend (data_cal);
+ g_return_val_if_fail (backend != NULL, FALSE);
+
+ async_context = async_context_new (data_cal, invocation);
- op_dispatch (cal, op);
+ e_cal_backend_get_attachment_uris (
+ backend,
+ in_uid, in_rid,
+ async_context->cancellable,
+ data_cal_complete_get_attachment_uris_cb,
+ async_context);
g_object_unref (backend);
- return TRUE;
+ return TRUE;
+}
+
+static void
+data_cal_complete_discard_alarm_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ AsyncContext *async_context = user_data;
+ GError *error = NULL;
+
+ e_cal_backend_discard_alarm_finish (
+ E_CAL_BACKEND (source_object), result, &error);
+
+ if (error == NULL) {
+ e_dbus_calendar_complete_discard_alarm (
+ async_context->interface,
+ async_context->invocation);
+ } else {
+ g_dbus_method_invocation_take_error (
+ async_context->invocation, error);
+ }
+
+ async_context_free (async_context);
}
static gboolean
@@ -1207,25 +1244,27 @@ data_cal_handle_discard_alarm_cb (EDBusCalendar *interface,
const gchar *in_uid,
const gchar *in_rid,
const gchar *in_alarm_uid,
- EDataCal *cal)
+ EDataCal *data_cal)
{
- OperationData *op;
ECalBackend *backend;
-
- backend = e_data_cal_ref_backend (cal);
- g_return_val_if_fail (backend != NULL, FALSE);
+ AsyncContext *async_context;
/* Recurrence ID is optional. Its omission is denoted
* via D-Bus by an empty string. Convert it to NULL. */
if (in_rid != NULL && *in_rid == '\0')
in_rid = NULL;
- op = op_new (OP_DISCARD_ALARM, cal, backend, invocation);
- op->d.ura.uid = g_strdup (in_uid);
- op->d.ura.rid = g_strdup (in_rid);
- op->d.ura.auid = g_strdup (in_alarm_uid);
+ backend = e_data_cal_ref_backend (data_cal);
+ g_return_val_if_fail (backend != NULL, FALSE);
+
+ async_context = async_context_new (data_cal, invocation);
- op_dispatch (cal, op);
+ e_cal_backend_discard_alarm (
+ backend,
+ in_uid, in_rid, in_alarm_uid,
+ async_context->cancellable,
+ data_cal_complete_discard_alarm_cb,
+ async_context);
g_object_unref (backend);
@@ -1235,64 +1274,163 @@ data_cal_handle_discard_alarm_cb (EDBusCalendar *interface,
static gboolean
data_cal_handle_get_view_cb (EDBusCalendar *interface,
GDBusMethodInvocation *invocation,
- const gchar *in_sexp,
- EDataCal *cal)
+ const gchar *in_query,
+ EDataCal *data_cal)
{
- OperationData *op;
ECalBackend *backend;
+ EDataCalView *view;
+ ECalBackendSExp *sexp;
+ GDBusConnection *connection;
+ gchar *object_path;
+ GError *error = NULL;
- backend = e_data_cal_ref_backend (cal);
+ backend = e_data_cal_ref_backend (data_cal);
g_return_val_if_fail (backend != NULL, FALSE);
- op = op_new (OP_GET_VIEW, cal, backend, invocation);
- op->d.sexp = g_strdup (in_sexp);
+ sexp = e_cal_backend_sexp_new (in_query);
+ if (sexp == NULL) {
+ g_dbus_method_invocation_return_error_literal (
+ invocation,
+ E_CLIENT_ERROR,
+ E_CLIENT_ERROR_INVALID_QUERY,
+ _("Invalid query"));
+ g_object_unref (backend);
+ return TRUE;
+ }
+
+ object_path = construct_calview_path ();
+ connection = g_dbus_method_invocation_get_connection (invocation);
+
+ view = e_data_cal_view_new (
+ backend, sexp, connection, object_path, &error);
+
+ g_object_unref (sexp);
+
+ /* Sanity check. */
+ g_return_val_if_fail (
+ ((view != NULL) && (error == NULL)) ||
+ ((view == NULL) && (error != NULL)), FALSE);
+
+ if (view != NULL) {
+ e_dbus_calendar_complete_get_view (
+ interface, invocation, object_path);
+ e_cal_backend_add_view (backend, view);
+ g_object_unref (view);
+ } else {
+ data_cal_convert_to_client_error (error);
+ g_prefix_error (&error, "%s", _("Invalid query: "));
+ g_dbus_method_invocation_take_error (invocation, error);
+ }
- /* This operation is never queued. */
- e_operation_pool_push (ops_pool, op);
+ g_free (object_path);
g_object_unref (backend);
return TRUE;
}
+static void
+data_cal_complete_get_timezone_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ AsyncContext *async_context = user_data;
+ gchar *tzobject;
+ GError *error = NULL;
+
+ /* XXX Should this return an ECalComponent instead? */
+ tzobject = e_cal_backend_get_timezone_finish (
+ E_CAL_BACKEND (source_object), result, &error);
+
+ /* Sanity check. */
+ g_return_if_fail (
+ ((tzobject != NULL) && (error == NULL)) ||
+ ((tzobject == NULL) && (error != NULL)));
+
+ if (tzobject != NULL) {
+ e_dbus_calendar_complete_get_timezone (
+ async_context->interface,
+ async_context->invocation,
+ tzobject);
+
+ g_free (tzobject);
+ } else {
+ g_dbus_method_invocation_take_error (
+ async_context->invocation, error);
+ }
+
+ async_context_free (async_context);
+}
+
static gboolean
data_cal_handle_get_timezone_cb (EDBusCalendar *interface,
GDBusMethodInvocation *invocation,
const gchar *in_tzid,
- EDataCal *cal)
+ EDataCal *data_cal)
{
- OperationData *op;
ECalBackend *backend;
+ AsyncContext *async_context;
- backend = e_data_cal_ref_backend (cal);
+ backend = e_data_cal_ref_backend (data_cal);
g_return_val_if_fail (backend != NULL, FALSE);
- op = op_new (OP_GET_TIMEZONE, cal, backend, invocation);
- op->d.tzid = g_strdup (in_tzid);
+ async_context = async_context_new (data_cal, invocation);
- op_dispatch (cal, op);
+ e_cal_backend_get_timezone (
+ backend,
+ in_tzid,
+ async_context->cancellable,
+ data_cal_complete_get_timezone_cb,
+ async_context);
g_object_unref (backend);
return TRUE;
}
+static void
+data_cal_complete_add_timezone_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ AsyncContext *async_context = user_data;
+ GError *error = NULL;
+
+ e_cal_backend_add_timezone_finish (
+ E_CAL_BACKEND (source_object), result, &error);
+
+ if (error == NULL) {
+ e_dbus_calendar_complete_add_timezone (
+ async_context->interface,
+ async_context->invocation);
+ } else {
+ g_dbus_method_invocation_take_error (
+ async_context->invocation, error);
+ }
+
+ async_context_free (async_context);
+}
+
static gboolean
data_cal_handle_add_timezone_cb (EDBusCalendar *interface,
GDBusMethodInvocation *invocation,
const gchar *in_tzobject,
- EDataCal *cal)
+ EDataCal *data_cal)
{
- OperationData *op;
ECalBackend *backend;
+ AsyncContext *async_context;
- backend = e_data_cal_ref_backend (cal);
+ backend = e_data_cal_ref_backend (data_cal);
g_return_val_if_fail (backend != NULL, FALSE);
- op = op_new (OP_ADD_TIMEZONE, cal, backend, invocation);
- op->d.tzobject = g_strdup (in_tzobject);
+ async_context = async_context_new (data_cal, invocation);
- op_dispatch (cal, op);
+ e_cal_backend_add_timezone (
+ backend,
+ in_tzobject,
+ async_context->cancellable,
+ data_cal_complete_add_timezone_cb,
+ async_context);
g_object_unref (backend);
@@ -1302,20 +1440,14 @@ data_cal_handle_add_timezone_cb (EDBusCalendar *interface,
static gboolean
data_cal_handle_close_cb (EDBusCalendar *interface,
GDBusMethodInvocation *invocation,
- EDataCal *cal)
+ EDataCal *data_cal)
{
- OperationData *op;
ECalBackend *backend;
const gchar *sender;
- backend = e_data_cal_ref_backend (cal);
+ backend = e_data_cal_ref_backend (data_cal);
g_return_val_if_fail (backend != NULL, FALSE);
- op = op_new (OP_CLOSE, cal, backend, invocation);
-
- /* This operation is never queued. */
- e_operation_pool_push (ops_pool, op);
-
sender = g_dbus_method_invocation_get_sender (invocation);
g_signal_emit_by_name (backend, "closed", sender);
@@ -1338,46 +1470,31 @@ e_data_cal_respond_open (EDataCal *cal,
guint32 opid,
GError *error)
{
- OperationData *data;
+ ECalBackend *backend;
+ GSimpleAsyncResult *simple;
g_return_if_fail (E_IS_DATA_CAL (cal));
- data = op_claim (cal, opid);
- g_return_if_fail (data != NULL);
+ backend = e_data_cal_ref_backend (cal);
+ g_return_if_fail (backend != NULL);
+
+ simple = e_cal_backend_prepare_for_completion (backend, opid, NULL);
+ g_return_if_fail (simple != NULL);
/* Translators: This is prefix to a detailed error message */
g_prefix_error (&error, "%s", _("Cannot open calendar: "));
cal->priv->opened = (error == NULL);
- if (error == NULL) {
- e_dbus_calendar_complete_open (
- cal->priv->dbus_interface,
- data->invocation);
- } else {
+ if (error != NULL) {
data_cal_convert_to_client_error (error);
- g_dbus_method_invocation_take_error (
- data->invocation, error);
+ g_simple_async_result_take_error (simple, error);
}
- op_unref (data);
+ g_simple_async_result_complete_in_idle (simple);
- /* Dispatch any pending operations. */
-
- g_mutex_lock (&cal->priv->open_lock);
-
- if (opid == cal->priv->open_opid) {
- OperationData *op;
-
- cal->priv->open_opid = 0;
-
- while (!g_queue_is_empty (&cal->priv->open_queue)) {
- op = g_queue_pop_head (&cal->priv->open_queue);
- e_operation_pool_push (ops_pool, op);
- }
- }
-
- g_mutex_unlock (&cal->priv->open_lock);
+ g_object_unref (simple);
+ g_object_unref (backend);
}
/**
@@ -1394,27 +1511,29 @@ e_data_cal_respond_refresh (EDataCal *cal,
guint32 opid,
GError *error)
{
- OperationData *data;
+ ECalBackend *backend;
+ GSimpleAsyncResult *simple;
g_return_if_fail (E_IS_DATA_CAL (cal));
- data = op_claim (cal, opid);
- g_return_if_fail (data != NULL);
+ backend = e_data_cal_ref_backend (cal);
+ g_return_if_fail (backend != NULL);
+
+ simple = e_cal_backend_prepare_for_completion (backend, opid, NULL);
+ g_return_if_fail (simple != NULL);
/* Translators: This is prefix to a detailed error message */
g_prefix_error (&error, "%s", _("Cannot refresh calendar: "));
- if (error == NULL) {
- e_dbus_calendar_complete_refresh (
- cal->priv->dbus_interface,
- data->invocation);
- } else {
+ if (error != NULL) {
data_cal_convert_to_client_error (error);
- g_dbus_method_invocation_take_error (
- data->invocation, error);
+ g_simple_async_result_take_error (simple, error);
}
- op_unref (data);
+ g_simple_async_result_complete (simple);
+
+ g_object_unref (simple);
+ g_object_unref (backend);
}
/**
@@ -1433,27 +1552,32 @@ e_data_cal_respond_get_backend_property (EDataCal *cal,
GError *error,
const gchar *prop_value)
{
- OperationData *data;
+ ECalBackend *backend;
+ GSimpleAsyncResult *simple;
+ GQueue *queue = NULL;
g_return_if_fail (E_IS_DATA_CAL (cal));
- data = op_claim (cal, opid);
- g_return_if_fail (data != NULL);
+ backend = e_data_cal_ref_backend (cal);
+ g_return_if_fail (backend != NULL);
- /* Translators: This is prefix to a detailed error message */
- g_prefix_error (&error, "%s", _("Cannot retrieve backend property: "));
+ simple = e_cal_backend_prepare_for_completion (backend, opid, &queue);
+ g_return_if_fail (simple != NULL);
+ g_return_if_fail (queue != NULL);
if (error == NULL) {
- e_data_cal_report_backend_property_changed (
- cal, data->d.prop_name, prop_value);
+ /* Convert NULL to an empty string. */
+ if (prop_value == NULL)
+ prop_value = "";
+ g_queue_push_tail (queue, g_strdup (prop_value));
} else {
- /* This should never happen, since all backend property
- * requests now originate from our constructed() method. */
- g_warning ("%s: %s", G_STRFUNC, error->message);
- g_error_free (error);
+ g_simple_async_result_take_error (simple, error);
}
- op_unref (data);
+ g_simple_async_result_complete_in_idle (simple);
+
+ g_object_unref (simple);
+ g_object_unref (backend);
}
/**
@@ -1472,34 +1596,44 @@ e_data_cal_respond_get_object (EDataCal *cal,
GError *error,
const gchar *object)
{
- OperationData *data;
+ ECalBackend *backend;
+ GSimpleAsyncResult *simple;
+ GQueue *queue = NULL;
g_return_if_fail (E_IS_DATA_CAL (cal));
- data = op_claim (cal, opid);
- g_return_if_fail (data != NULL);
+ backend = e_data_cal_ref_backend (cal);
+ g_return_if_fail (backend != NULL);
+
+ simple = e_cal_backend_prepare_for_completion (backend, opid, &queue);
+ g_return_if_fail (simple != NULL);
+ g_return_if_fail (queue != NULL);
/* Translators: This is prefix to a detailed error message */
g_prefix_error (&error, "%s", _("Cannot retrieve calendar object path: "));
if (error == NULL) {
- gchar *utf8_object;
-
- utf8_object = e_util_utf8_make_valid (object);
-
- e_dbus_calendar_complete_get_object (
- cal->priv->dbus_interface,
- data->invocation,
- utf8_object);
+ ECalComponent *component;
- g_free (utf8_object);
+ component = e_cal_component_new_from_string (object);
+ if (component != NULL) {
+ g_queue_push_tail (queue, component);
+ } else {
+ g_simple_async_result_set_error (
+ simple, E_CAL_CLIENT_ERROR,
+ E_CAL_CLIENT_ERROR_INVALID_OBJECT,
+ "%s", e_cal_client_error_to_string (
+ E_CAL_CLIENT_ERROR_INVALID_OBJECT));
+ }
} else {
data_cal_convert_to_client_error (error);
- g_dbus_method_invocation_take_error (
- data->invocation, error);
+ g_simple_async_result_take_error (simple, error);
}
- op_unref (data);
+ g_simple_async_result_complete_in_idle (simple);
+
+ g_object_unref (simple);
+ g_object_unref (backend);
}
/**
@@ -1518,42 +1652,48 @@ e_data_cal_respond_get_object_list (EDataCal *cal,
GError *error,
const GSList *objects)
{
- OperationData *data;
+ ECalBackend *backend;
+ GSimpleAsyncResult *simple;
+ GQueue *queue = NULL;
g_return_if_fail (E_IS_DATA_CAL (cal));
- data = op_claim (cal, opid);
- g_return_if_fail (data != NULL);
+ backend = e_data_cal_ref_backend (cal);
+ g_return_if_fail (backend != NULL);
+
+ simple = e_cal_backend_prepare_for_completion (backend, opid, &queue);
+ g_return_if_fail (simple != NULL);
+ g_return_if_fail (queue != NULL);
/* Translators: This is prefix to a detailed error message */
g_prefix_error (&error, "%s", _("Cannot retrieve calendar object list: "));
if (error == NULL) {
- gchar **strv;
- guint length;
- gint ii = 0;
+ GSList *list, *link;
- length = g_slist_length ((GSList *) objects);
- strv = g_new0 (gchar *, length + 1);
+ list = (GSList *) objects;
- while (objects != NULL) {
- strv[ii++] = e_util_utf8_make_valid (objects->data);
- objects = g_slist_next (objects);
- }
+ for (link = list; link != NULL; link = g_slist_next (link)) {
+ ECalComponent *component;
+ gchar *string = link->data;
- e_dbus_calendar_complete_get_object_list (
- cal->priv->dbus_interface,
- data->invocation,
- (const gchar * const *) strv);
+ component = e_cal_component_new_from_string (string);
+ if (component != NULL) {
+ g_queue_push_tail (
+ queue, g_object_ref (component));
+ g_object_unref (component);
+ }
+ }
- g_strfreev (strv);
} else {
data_cal_convert_to_client_error (error);
- g_dbus_method_invocation_take_error (
- data->invocation, error);
+ g_simple_async_result_take_error (simple, error);
}
- op_unref (data);
+ g_simple_async_result_complete_in_idle (simple);
+
+ g_object_unref (simple);
+ g_object_unref (backend);
}
/**
@@ -1571,27 +1711,29 @@ e_data_cal_respond_get_free_busy (EDataCal *cal,
guint32 opid,
GError *error)
{
- OperationData *data;
+ ECalBackend *backend;
+ GSimpleAsyncResult *simple;
g_return_if_fail (E_IS_DATA_CAL (cal));
- data = op_claim (cal, opid);
- g_return_if_fail (data != NULL);
+ backend = e_data_cal_ref_backend (cal);
+ g_return_if_fail (backend != NULL);
+
+ simple = e_cal_backend_prepare_for_completion (backend, opid, NULL);
+ g_return_if_fail (simple != NULL);
/* Translators: This is prefix to a detailed error message */
g_prefix_error (&error, "%s", _("Cannot retrieve calendar free/busy list: "));
- if (error == NULL) {
- e_dbus_calendar_complete_get_free_busy (
- cal->priv->dbus_interface,
- data->invocation);
- } else {
+ if (error != NULL) {
data_cal_convert_to_client_error (error);
- g_dbus_method_invocation_take_error (
- data->invocation, error);
+ g_simple_async_result_take_error (simple, error);
}
- op_unref (data);
+ g_simple_async_result_complete_in_idle (simple);
+
+ g_object_unref (simple);
+ g_object_unref (backend);
}
/**
@@ -1612,52 +1754,55 @@ e_data_cal_respond_create_objects (EDataCal *cal,
const GSList *uids,
GSList *new_components)
{
- OperationData *data;
+ ECalBackend *backend;
+ GSimpleAsyncResult *simple;
+ GQueue *queue = NULL;
g_return_if_fail (E_IS_DATA_CAL (cal));
- data = op_claim (cal, opid);
- g_return_if_fail (data != NULL);
+ backend = e_data_cal_ref_backend (cal);
+ g_return_if_fail (backend != NULL);
+
+ simple = e_cal_backend_prepare_for_completion (backend, opid, &queue);
+ g_return_if_fail (simple != NULL);
+ g_return_if_fail (queue != NULL);
/* Translators: This is prefix to a detailed error message */
g_prefix_error (&error, "%s", _("Cannot create calendar object: "));
if (error == NULL) {
- gchar **strv;
- guint length;
- gint ii = 0;
+ GQueue *inner_queue;
+ GSList *list, *link;
- length = g_slist_length ((GSList *) uids);
- strv = g_new0 (gchar *, length + 1);
+ inner_queue = g_queue_new ();
- while (uids != NULL) {
- strv[ii++] = e_util_utf8_make_valid (uids->data);
- uids = g_slist_next ((GSList *) uids);
- }
+ list = (GSList *) uids;
- e_dbus_calendar_complete_create_objects (
- cal->priv->dbus_interface,
- data->invocation,
- (const gchar * const *) strv);
+ for (link = list; link != NULL; link = g_slist_next (link))
+ g_queue_push_tail (inner_queue, g_strdup (link->data));
- g_strfreev (strv);
+ g_queue_push_tail (queue, inner_queue);
- while (new_components != NULL) {
- ECalComponent *component;
+ inner_queue = g_queue_new ();
- component = E_CAL_COMPONENT (new_components->data);
- e_cal_backend_notify_component_created (
- data->backend, component);
+ list = (GSList *) new_components;
+
+ for (link = list; link != NULL; link = g_slist_next (link))
+ g_queue_push_tail (
+ inner_queue,
+ g_object_ref (link->data));
+
+ g_queue_push_tail (queue, inner_queue);
- new_components = g_slist_next (new_components);
- }
} else {
data_cal_convert_to_client_error (error);
- g_dbus_method_invocation_take_error (
- data->invocation, error);
+ g_simple_async_result_take_error (simple, error);
}
- op_unref (data);
+ g_simple_async_result_complete_in_idle (simple);
+
+ g_object_unref (simple);
+ g_object_unref (backend);
}
/**
@@ -1678,41 +1823,59 @@ e_data_cal_respond_modify_objects (EDataCal *cal,
GSList *old_components,
GSList *new_components)
{
- OperationData *data;
+ ECalBackend *backend;
+ GSimpleAsyncResult *simple;
+ GQueue *queue = NULL;
g_return_if_fail (E_IS_DATA_CAL (cal));
- data = op_claim (cal, opid);
- g_return_if_fail (data != NULL);
+ backend = e_data_cal_ref_backend (cal);
+ g_return_if_fail (backend != NULL);
+
+ simple = e_cal_backend_prepare_for_completion (backend, opid, &queue);
+ g_return_if_fail (simple != NULL);
+ g_return_if_fail (queue != NULL);
/* Translators: This is prefix to a detailed error message */
g_prefix_error (&error, "%s", _("Cannot modify calendar object: "));
if (error == NULL) {
- e_dbus_calendar_complete_modify_objects (
- cal->priv->dbus_interface,
- data->invocation);
+ GQueue *inner_queue;
+ GSList *list, *link;
- while (old_components != NULL && new_components != NULL) {
- ECalComponent *old_component;
- ECalComponent *new_component;
+ /* FIXME Ugh, this is awkward... */
- old_component = E_CAL_COMPONENT (old_components->data);
- new_component = E_CAL_COMPONENT (new_components->data);
+ inner_queue = g_queue_new ();
- e_cal_backend_notify_component_modified (
- data->backend, old_component, new_component);
+ list = (GSList *) old_components;
+
+ for (link = list; link != NULL; link = g_slist_next (link))
+ g_queue_push_tail (
+ inner_queue,
+ g_object_ref (link->data));
+
+ g_queue_push_tail (queue, inner_queue);
+
+ inner_queue = g_queue_new ();
+
+ list = (GSList *) new_components;
+
+ for (link = list; link != NULL; link = g_slist_next (link))
+ g_queue_push_tail (
+ inner_queue,
+ g_object_ref (link->data));
+
+ g_queue_push_tail (queue, inner_queue);
- old_components = g_slist_next (old_components);
- new_components = g_slist_next (new_components);
- }
} else {
data_cal_convert_to_client_error (error);
- g_dbus_method_invocation_take_error (
- data->invocation, error);
+ g_simple_async_result_take_error (simple, error);
}
- op_unref (data);
+ g_simple_async_result_complete_in_idle (simple);
+
+ g_object_unref (simple);
+ g_object_unref (backend);
}
/**
@@ -1736,47 +1899,76 @@ e_data_cal_respond_remove_objects (EDataCal *cal,
GSList *old_components,
GSList *new_components)
{
- OperationData *data;
+ ECalBackend *backend;
+ GSimpleAsyncResult *simple;
+ GQueue *queue = NULL;
g_return_if_fail (E_IS_DATA_CAL (cal));
- data = op_claim (cal, opid);
- g_return_if_fail (data != NULL);
+ backend = e_data_cal_ref_backend (cal);
+ g_return_if_fail (backend != NULL);
+
+ simple = e_cal_backend_prepare_for_completion (backend, opid, &queue);
+ g_return_if_fail (simple != NULL);
+ g_return_if_fail (queue != NULL);
/* Translators: This is prefix to a detailed error message */
g_prefix_error (&error, "%s", _("Cannot remove calendar object: "));
if (error == NULL) {
- e_dbus_calendar_complete_remove_objects (
- cal->priv->dbus_interface,
- data->invocation);
+ GQueue *inner_queue;
+ GSList *list, *link;
+
+ /* FIXME Ugh, this is awkward... */
+
+ inner_queue = g_queue_new ();
+
+ list = (GSList *) ids;
+
+ for (link = list; link != NULL; link = g_slist_next (link))
+ g_queue_push_tail (
+ inner_queue,
+ e_cal_component_id_copy (link->data));
+
+ g_queue_push_tail (queue, inner_queue);
- while (ids != NULL && old_components != NULL) {
- ECalComponentId *id;
- ECalComponent *old_component;
- ECalComponent *new_component = NULL;
+ inner_queue = g_queue_new ();
- id = ids->data;
- old_component = E_CAL_COMPONENT (old_components->data);
- new_component = (new_components != NULL) ?
- E_CAL_COMPONENT (new_components->data) : NULL;
+ list = (GSList *) old_components;
- e_cal_backend_notify_component_removed (
- data->backend, id, old_component, new_component);
+ for (link = list; link != NULL; link = g_slist_next (link))
+ g_queue_push_tail (
+ inner_queue,
+ g_object_ref (link->data));
- ids = g_slist_next ((GSList *) ids);
- old_components = g_slist_next (old_components);
+ g_queue_push_tail (queue, inner_queue);
- if (new_components != NULL)
- new_components = g_slist_next (new_components);
+ if (new_components != NULL) {
+ inner_queue = g_queue_new ();
+
+ list = (GSList *) new_components;
+
+ /* XXX Careful here. Apparently list elements
+ * can be NULL. What a horrible API design. */
+ for (link = list; link != NULL; link = g_slist_next (link)) {
+ if (link->data != NULL)
+ g_object_ref (link->data);
+ g_queue_push_tail (
+ inner_queue, link->data);
+ }
+
+ g_queue_push_tail (queue, inner_queue);
}
+
} else {
data_cal_convert_to_client_error (error);
- g_dbus_method_invocation_take_error (
- data->invocation, error);
+ g_simple_async_result_take_error (simple, error);
}
- op_unref (data);
+ g_simple_async_result_complete_in_idle (simple);
+
+ g_object_unref (simple);
+ g_object_unref (backend);
}
/**
@@ -1793,27 +1985,29 @@ e_data_cal_respond_receive_objects (EDataCal *cal,
guint32 opid,
GError *error)
{
- OperationData *data;
+ ECalBackend *backend;
+ GSimpleAsyncResult *simple;
g_return_if_fail (E_IS_DATA_CAL (cal));
- data = op_claim (cal, opid);
- g_return_if_fail (data != NULL);
+ backend = e_data_cal_ref_backend (cal);
+ g_return_if_fail (backend != NULL);
+
+ simple = e_cal_backend_prepare_for_completion (backend, opid, NULL);
+ g_return_if_fail (simple != NULL);
/* Translators: This is prefix to a detailed error message */
g_prefix_error (&error, "%s", _("Cannot receive calendar objects: "));
- if (error == NULL) {
- e_dbus_calendar_complete_receive_objects (
- cal->priv->dbus_interface,
- data->invocation);
- } else {
+ if (error != NULL) {
data_cal_convert_to_client_error (error);
- g_dbus_method_invocation_take_error (
- data->invocation, error);
+ g_simple_async_result_take_error (simple, error);
}
- op_unref (data);
+ g_simple_async_result_complete_in_idle (simple);
+
+ g_object_unref (simple);
+ g_object_unref (backend);
}
/**
@@ -1834,48 +2028,45 @@ e_data_cal_respond_send_objects (EDataCal *cal,
const GSList *users,
const gchar *calobj)
{
- OperationData *data;
+ ECalBackend *backend;
+ GSimpleAsyncResult *simple;
+ GQueue *queue = NULL;
g_return_if_fail (E_IS_DATA_CAL (cal));
- data = op_claim (cal, opid);
- g_return_if_fail (data != NULL);
+ backend = e_data_cal_ref_backend (cal);
+ g_return_if_fail (backend != NULL);
+
+ simple = e_cal_backend_prepare_for_completion (backend, opid, &queue);
+ g_return_if_fail (simple != NULL);
+ g_return_if_fail (queue != NULL);
/* Translators: This is prefix to a detailed error message */
g_prefix_error (&error, "%s", _("Cannot send calendar objects: "));
if (error == NULL) {
- gchar *utf8_calobj;
- gchar **strv;
- guint length;
- gint ii = 0;
-
- length = g_slist_length ((GSList *) users);
- strv = g_new0 (gchar *, length + 1);
-
- while (users != NULL) {
- strv[ii++] = e_util_utf8_make_valid (users->data);
- users = g_slist_next ((GSList *) users);
- }
+ ECalComponent *component;
+ GSList *list, *link;
- utf8_calobj = e_util_utf8_make_valid (calobj);
+ component = e_cal_component_new_from_string (calobj);
+ g_return_if_fail (component != NULL);
+ g_queue_push_tail (queue, g_object_ref (component));
+ g_object_unref (component);
- e_dbus_calendar_complete_send_objects (
- cal->priv->dbus_interface,
- data->invocation,
- (const gchar *const *) strv,
- utf8_calobj);
+ list = (GSList *) users;
- g_free (utf8_calobj);
+ for (link = list; link != NULL; link = g_slist_next (link))
+ g_queue_push_tail (queue, g_strdup (link->data));
- g_strfreev (strv);
} else {
data_cal_convert_to_client_error (error);
- g_dbus_method_invocation_take_error (
- data->invocation, error);
+ g_simple_async_result_take_error (simple, error);
}
- op_unref (data);
+ g_simple_async_result_complete_in_idle (simple);
+
+ g_object_unref (simple);
+ g_object_unref (backend);
}
/**
@@ -1894,40 +2085,38 @@ e_data_cal_respond_get_attachment_uris (EDataCal *cal,
GError *error,
const GSList *attachment_uris)
{
- OperationData *data;
+ ECalBackend *backend;
+ GSimpleAsyncResult *simple;
+ GQueue *queue = NULL;
g_return_if_fail (E_IS_DATA_CAL (cal));
- data = op_claim (cal, opid);
- g_return_if_fail (data != NULL);
+ backend = e_data_cal_ref_backend (cal);
+ g_return_if_fail (backend != NULL);
+
+ simple = e_cal_backend_prepare_for_completion (backend, opid, &queue);
+ g_return_if_fail (simple != NULL);
+ g_return_if_fail (queue != NULL);
/* Translators: This is prefix to a detailed error message */
g_prefix_error (&error, "%s", _("Could not retrieve attachment uris: "));
if (error == NULL) {
- gchar **strv;
- guint length;
- gint ii = 0;
-
- length = g_slist_length ((GSList *) attachment_uris);
- strv = g_new0 (gchar *, length + 1);
+ GSList *list, *link;
- while (attachment_uris != NULL) {
- strv[ii++] = e_util_utf8_make_valid (attachment_uris->data);
- attachment_uris = g_slist_next ((GSList *) attachment_uris);
- }
-
- e_dbus_calendar_complete_get_attachment_uris (
- cal->priv->dbus_interface,
- data->invocation,
- (const gchar * const *) strv);
+ list = (GSList *) attachment_uris;
- g_strfreev (strv);
+ for (link = list; link != NULL; link = g_slist_next (link))
+ g_queue_push_tail (queue, g_strdup (link->data));
} else {
data_cal_convert_to_client_error (error);
- g_dbus_method_invocation_take_error (
- data->invocation, error);
+ g_simple_async_result_take_error (simple, error);
}
+
+ g_simple_async_result_complete_in_idle (simple);
+
+ g_object_unref (simple);
+ g_object_unref (backend);
}
/**
@@ -1944,73 +2133,29 @@ e_data_cal_respond_discard_alarm (EDataCal *cal,
guint32 opid,
GError *error)
{
- OperationData *data;
+ ECalBackend *backend;
+ GSimpleAsyncResult *simple;
g_return_if_fail (E_IS_DATA_CAL (cal));
- data = op_claim (cal, opid);
- g_return_if_fail (data != NULL);
+ backend = e_data_cal_ref_backend (cal);
+ g_return_if_fail (backend != NULL);
+
+ simple = e_cal_backend_prepare_for_completion (backend, opid, NULL);
+ g_return_if_fail (simple != NULL);
/* Translators: This is prefix to a detailed error message */
g_prefix_error (&error, "%s", _("Could not discard reminder: "));
- if (error == NULL) {
- e_dbus_calendar_complete_discard_alarm (
- cal->priv->dbus_interface,
- data->invocation);
- } else {
+ if (error != NULL) {
data_cal_convert_to_client_error (error);
- g_dbus_method_invocation_take_error (
- data->invocation, error);
+ g_simple_async_result_take_error (simple, error);
}
- op_unref (data);
-}
-
-/**
- * e_data_cal_respond_get_view:
- * @cal: A calendar client interface.
- * @error: Operation error, if any, automatically freed if passed it.
- * @view_path: The new live view path.
- *
- * Notifies listeners of the completion of the get_view method call.
- *
- * Since: 3.2
- */
-void
-e_data_cal_respond_get_view (EDataCal *cal,
- guint32 opid,
- GError *error,
- const gchar *view_path)
-{
- OperationData *data;
-
- g_return_if_fail (E_IS_DATA_CAL (cal));
-
- data = op_claim (cal, opid);
- g_return_if_fail (data != NULL);
-
- /* Translators: This is prefix to a detailed error message */
- g_prefix_error (&error, "%s", _("Could not get calendar view path: "));
-
- if (error == NULL) {
- gchar *utf8_view_path;
-
- utf8_view_path = e_util_utf8_make_valid (view_path);
-
- e_dbus_calendar_complete_get_view (
- cal->priv->dbus_interface,
- data->invocation,
- utf8_view_path);
-
- g_free (utf8_view_path);
- } else {
- data_cal_convert_to_client_error (error);
- g_dbus_method_invocation_take_error (
- data->invocation, error);
- }
+ g_simple_async_result_complete_in_idle (simple);
- op_unref (data);
+ g_object_unref (simple);
+ g_object_unref (backend);
}
/**
@@ -2029,34 +2174,33 @@ e_data_cal_respond_get_timezone (EDataCal *cal,
GError *error,
const gchar *tzobject)
{
- OperationData *data;
+ ECalBackend *backend;
+ GSimpleAsyncResult *simple;
+ GQueue *queue = NULL;
g_return_if_fail (E_IS_DATA_CAL (cal));
- data = op_claim (cal, opid);
- g_return_if_fail (data != NULL);
+ backend = e_data_cal_ref_backend (cal);
+ g_return_if_fail (backend != NULL);
+
+ simple = e_cal_backend_prepare_for_completion (backend, opid, &queue);
+ g_return_if_fail (simple != NULL);
+ g_return_if_fail (queue != NULL);
/* Translators: This is prefix to a detailed error message */
g_prefix_error (&error, "%s", _("Could not retrieve calendar time zone: "));
if (error == NULL) {
- gchar *utf8_tz_object;
-
- utf8_tz_object = e_util_utf8_make_valid (tzobject);
-
- e_dbus_calendar_complete_get_timezone (
- cal->priv->dbus_interface,
- data->invocation,
- utf8_tz_object);
-
- g_free (utf8_tz_object);
+ g_queue_push_tail (queue, g_strdup (tzobject));
} else {
data_cal_convert_to_client_error (error);
- g_dbus_method_invocation_take_error (
- data->invocation, error);
+ g_simple_async_result_take_error (simple, error);
}
- op_unref (data);
+ g_simple_async_result_complete_in_idle (simple);
+
+ g_object_unref (simple);
+ g_object_unref (backend);
}
/**
@@ -2073,27 +2217,29 @@ e_data_cal_respond_add_timezone (EDataCal *cal,
guint32 opid,
GError *error)
{
- OperationData *data;
+ ECalBackend *backend;
+ GSimpleAsyncResult *simple;
g_return_if_fail (E_IS_DATA_CAL (cal));
- data = op_claim (cal, opid);
- g_return_if_fail (data != NULL);
+ backend = e_data_cal_ref_backend (cal);
+ g_return_if_fail (backend != NULL);
+
+ simple = e_cal_backend_prepare_for_completion (backend, opid, NULL);
+ g_return_if_fail (simple != NULL);
/* Translators: This is prefix to a detailed error message */
g_prefix_error (&error, "%s", _("Could not add calendar time zone: "));
- if (error == NULL) {
- e_dbus_calendar_complete_add_timezone (
- cal->priv->dbus_interface,
- data->invocation);
- } else {
+ if (error != NULL) {
data_cal_convert_to_client_error (error);
- g_dbus_method_invocation_take_error (
- data->invocation, error);
+ g_simple_async_result_take_error (simple, error);
}
- op_unref (data);
+ g_simple_async_result_complete_in_idle (simple);
+
+ g_object_unref (simple);
+ g_object_unref (backend);
}
/**
@@ -2294,6 +2440,8 @@ data_cal_dispose (GObject *object)
priv->connection = NULL;
}
+ g_hash_table_remove_all (priv->sender_table);
+
/* Chain up to parent's dispose() method. */
G_OBJECT_CLASS (e_data_cal_parent_class)->dispose (object);
}
@@ -2307,23 +2455,14 @@ data_cal_finalize (GObject *object)
g_free (priv->object_path);
- if (priv->pending_ops) {
- g_hash_table_destroy (priv->pending_ops);
- priv->pending_ops = NULL;
- }
-
- g_rec_mutex_clear (&priv->pending_ops_lock);
+ g_mutex_clear (&priv->sender_lock);
+ g_hash_table_destroy (priv->sender_table);
if (priv->dbus_interface) {
g_object_unref (priv->dbus_interface);
priv->dbus_interface = NULL;
}
- g_mutex_clear (&priv->open_lock);
-
- /* This should be empty now, else we leak memory. */
- g_warn_if_fail (g_queue_is_empty (&priv->open_queue));
-
/* Chain up to parent's finalize() method. */
G_OBJECT_CLASS (e_data_cal_parent_class)->finalize (object);
}
@@ -2332,8 +2471,9 @@ static void
data_cal_constructed (GObject *object)
{
EDataCal *cal = E_DATA_CAL (object);
- OperationData *op;
ECalBackend *backend;
+ const gchar *prop_name;
+ gchar *prop_value;
/* Chain up to parent's constructed() method. */
G_OBJECT_CLASS (e_data_cal_parent_class)->constructed (object);
@@ -2359,44 +2499,42 @@ data_cal_constructed (GObject *object)
cal->priv->dbus_interface, "writable",
G_BINDING_SYNC_CREATE);
- /* XXX Initialize the rest of the properties by faking client
- * requests. At present it's the only way to fish values
- * from ECalBackend's antiquated API. */
-
- op = op_new (OP_GET_BACKEND_PROPERTY, cal, backend, NULL);
- op->d.prop_name = CLIENT_BACKEND_PROPERTY_CAPABILITIES;
- e_cal_backend_get_backend_property (
- backend, cal, op->id,
- op->cancellable, op->d.prop_name);
- op_unref (op);
-
- op = op_new (OP_GET_BACKEND_PROPERTY, cal, backend, NULL);
- op->d.prop_name = CLIENT_BACKEND_PROPERTY_REVISION;
- e_cal_backend_get_backend_property (
- backend, cal, op->id,
- op->cancellable, op->d.prop_name);
- op_unref (op);
-
- op = op_new (OP_GET_BACKEND_PROPERTY, cal, backend, NULL);
- op->d.prop_name = CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS;
- e_cal_backend_get_backend_property (
- backend, cal, op->id,
- op->cancellable, op->d.prop_name);
- op_unref (op);
-
- op = op_new (OP_GET_BACKEND_PROPERTY, cal, backend, NULL);
- op->d.prop_name = CAL_BACKEND_PROPERTY_ALARM_EMAIL_ADDRESS;
- e_cal_backend_get_backend_property (
- backend, cal, op->id,
- op->cancellable, op->d.prop_name);
- op_unref (op);
-
- op = op_new (OP_GET_BACKEND_PROPERTY, cal, backend, NULL);
- op->d.prop_name = CAL_BACKEND_PROPERTY_DEFAULT_OBJECT;
- e_cal_backend_get_backend_property (
- backend, cal, op->id,
- op->cancellable, op->d.prop_name);
- op_unref (op);
+ /* XXX Initialize the rest of the properties. */
+
+ prop_name = CLIENT_BACKEND_PROPERTY_CAPABILITIES;
+ prop_value = e_cal_backend_get_backend_property_sync (
+ backend, prop_name, NULL, NULL);
+ e_data_cal_report_backend_property_changed (
+ cal, prop_name, prop_value);
+ g_free (prop_value);
+
+ prop_name = CLIENT_BACKEND_PROPERTY_REVISION;
+ prop_value = e_cal_backend_get_backend_property_sync (
+ backend, prop_name, NULL, NULL);
+ e_data_cal_report_backend_property_changed (
+ cal, prop_name, prop_value);
+ g_free (prop_value);
+
+ prop_name = CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS;
+ prop_value = e_cal_backend_get_backend_property_sync (
+ backend, prop_name, NULL, NULL);
+ e_data_cal_report_backend_property_changed (
+ cal, prop_name, prop_value);
+ g_free (prop_value);
+
+ prop_name = CAL_BACKEND_PROPERTY_ALARM_EMAIL_ADDRESS;
+ prop_value = e_cal_backend_get_backend_property_sync (
+ backend, prop_name, NULL, NULL);
+ e_data_cal_report_backend_property_changed (
+ cal, prop_name, prop_value);
+ g_free (prop_value);
+
+ prop_name = CAL_BACKEND_PROPERTY_DEFAULT_OBJECT;
+ prop_value = e_cal_backend_get_backend_property_sync (
+ backend, prop_name, NULL, NULL);
+ e_data_cal_report_backend_property_changed (
+ cal, prop_name, prop_value);
+ g_free (prop_value);
g_object_unref (backend);
}
@@ -2468,9 +2606,6 @@ e_data_cal_class_init (EDataCalClass *class)
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS));
-
- if (!ops_pool)
- ops_pool = e_operation_pool_new (10, operation_thread, NULL);
}
static void
@@ -2480,72 +2615,71 @@ e_data_cal_initable_init (GInitableIface *interface)
}
static void
-e_data_cal_init (EDataCal *ecal)
+e_data_cal_init (EDataCal *data_cal)
{
EDBusCalendar *dbus_interface;
- ecal->priv = E_DATA_CAL_GET_PRIVATE (ecal);
+ data_cal->priv = E_DATA_CAL_GET_PRIVATE (data_cal);
dbus_interface = e_dbus_calendar_skeleton_new ();
- ecal->priv->dbus_interface = dbus_interface;
+ data_cal->priv->dbus_interface = dbus_interface;
- ecal->priv->pending_ops = g_hash_table_new_full (
- (GHashFunc) g_direct_hash,
- (GEqualFunc) g_direct_equal,
- (GDestroyNotify) NULL,
- (GDestroyNotify) op_unref);
- g_rec_mutex_init (&ecal->priv->pending_ops_lock);
+ g_mutex_init (&data_cal->priv->sender_lock);
- g_mutex_init (&ecal->priv->open_lock);
+ data_cal->priv->sender_table = g_hash_table_new_full (
+ (GHashFunc) g_str_hash,
+ (GEqualFunc) g_str_equal,
+ (GDestroyNotify) g_free,
+ (GDestroyNotify) g_ptr_array_unref);
g_signal_connect (
dbus_interface, "handle-open",
- G_CALLBACK (data_cal_handle_open_cb), ecal);
+ G_CALLBACK (data_cal_handle_open_cb), data_cal);
g_signal_connect (
dbus_interface, "handle-refresh",
- G_CALLBACK (data_cal_handle_refresh_cb), ecal);
+ G_CALLBACK (data_cal_handle_refresh_cb), data_cal);
g_signal_connect (
dbus_interface, "handle-get-object",
- G_CALLBACK (data_cal_handle_get_object_cb), ecal);
+ G_CALLBACK (data_cal_handle_get_object_cb), data_cal);
g_signal_connect (
dbus_interface, "handle-get-object-list",
- G_CALLBACK (data_cal_handle_get_object_list_cb), ecal);
+ G_CALLBACK (data_cal_handle_get_object_list_cb), data_cal);
g_signal_connect (
dbus_interface, "handle-get-free-busy",
- G_CALLBACK (data_cal_handle_get_free_busy_cb), ecal);
+ G_CALLBACK (data_cal_handle_get_free_busy_cb), data_cal);
g_signal_connect (
dbus_interface, "handle-create-objects",
- G_CALLBACK (data_cal_handle_create_objects_cb), ecal);
+ G_CALLBACK (data_cal_handle_create_objects_cb), data_cal);
g_signal_connect (
dbus_interface, "handle-modify-objects",
- G_CALLBACK (data_cal_handle_modify_objects_cb), ecal);
+ G_CALLBACK (data_cal_handle_modify_objects_cb), data_cal);
g_signal_connect (
dbus_interface, "handle-remove-objects",
- G_CALLBACK (data_cal_handle_remove_objects_cb), ecal);
+ G_CALLBACK (data_cal_handle_remove_objects_cb), data_cal);
g_signal_connect (
dbus_interface, "handle-receive-objects",
- G_CALLBACK (data_cal_handle_receive_objects_cb), ecal);
+ G_CALLBACK (data_cal_handle_receive_objects_cb), data_cal);
g_signal_connect (
dbus_interface, "handle-send-objects",
- G_CALLBACK (data_cal_handle_send_objects_cb), ecal);
+ G_CALLBACK (data_cal_handle_send_objects_cb), data_cal);
g_signal_connect (
dbus_interface, "handle-get-attachment-uris",
- G_CALLBACK (data_cal_handle_get_attachment_uris_cb), ecal);
+ G_CALLBACK (data_cal_handle_get_attachment_uris_cb), data_cal);
g_signal_connect (
dbus_interface, "handle-discard-alarm",
- G_CALLBACK (data_cal_handle_discard_alarm_cb), ecal);
+ G_CALLBACK (data_cal_handle_discard_alarm_cb), data_cal);
g_signal_connect (
dbus_interface, "handle-get-view",
- G_CALLBACK (data_cal_handle_get_view_cb), ecal);
+ G_CALLBACK (data_cal_handle_get_view_cb), data_cal);
g_signal_connect (
dbus_interface, "handle-get-timezone",
- G_CALLBACK (data_cal_handle_get_timezone_cb), ecal);
+ G_CALLBACK (data_cal_handle_get_timezone_cb), data_cal);
g_signal_connect (
dbus_interface, "handle-add-timezone",
- G_CALLBACK (data_cal_handle_add_timezone_cb), ecal);
+ G_CALLBACK (data_cal_handle_add_timezone_cb), data_cal);
g_signal_connect (
dbus_interface, "handle-close",
- G_CALLBACK (data_cal_handle_close_cb), ecal);
+ G_CALLBACK (data_cal_handle_close_cb), data_cal);
}
/**
diff --git a/calendar/libedata-cal/e-data-cal.h b/calendar/libedata-cal/e-data-cal.h
index 117b96f..b3bb673 100644
--- a/calendar/libedata-cal/e-data-cal.h
+++ b/calendar/libedata-cal/e-data-cal.h
@@ -1,23 +1,19 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/* Evolution calendar client interface object
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- * Authors: Federico Mena-Quintero <federico ximian com>
- * Rodrigo Moya <rodrigo ximian com>
+/*
+ * e-data-cal.h
*
* This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
- * License as published by the Free Software Foundation.
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
*
* 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 Lesser General Public License for more details.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
*
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#if !defined (__LIBEDATA_CAL_H_INSIDE__) && !defined (LIBEDATA_CAL_COMPILATION)
@@ -239,10 +235,6 @@ void e_data_cal_respond_discard_alarm
(EDataCal *cal,
guint32 opid,
GError *error);
-void e_data_cal_respond_get_view (EDataCal *cal,
- guint32 opid,
- GError *error,
- const gchar *view_path);
void e_data_cal_respond_get_timezone (EDataCal *cal,
guint32 opid,
GError *error,
diff --git a/configure.ac b/configure.ac
index 1e1ac78..21cfc57 100644
--- a/configure.ac
+++ b/configure.ac
@@ -114,7 +114,7 @@ LIBECAL_CURRENT=15
LIBECAL_REVISION=0
LIBECAL_AGE=0
-LIBEDATACAL_CURRENT=20
+LIBEDATACAL_CURRENT=21
LIBEDATACAL_REVISION=0
LIBEDATACAL_AGE=0
diff --git a/docs/reference/calendar/libedata-cal/libedata-cal-sections.txt
b/docs/reference/calendar/libedata-cal/libedata-cal-sections.txt
index 2b34cfd..be44d2e 100644
--- a/docs/reference/calendar/libedata-cal/libedata-cal-sections.txt
+++ b/docs/reference/calendar/libedata-cal/libedata-cal-sections.txt
@@ -25,21 +25,51 @@ e_cal_backend_create_cache_filename
e_cal_backend_add_view
e_cal_backend_remove_view
e_cal_backend_list_views
+e_cal_backend_get_backend_property_sync
e_cal_backend_get_backend_property
+e_cal_backend_get_backend_property_finish
+e_cal_backend_open_sync
e_cal_backend_open
+e_cal_backend_open_finish
+e_cal_backend_refresh_sync
e_cal_backend_refresh
+e_cal_backend_refresh_finish
+e_cal_backend_get_object_sync
e_cal_backend_get_object
+e_cal_backend_get_object_finish
+e_cal_backend_get_object_list_sync
e_cal_backend_get_object_list
+e_cal_backend_get_object_list_finish
+e_cal_backend_get_free_busy_sync
e_cal_backend_get_free_busy
+e_cal_backend_get_free_busy_finish
+e_cal_backend_create_objects_sync
e_cal_backend_create_objects
+e_cal_backend_create_objects_finish
+e_cal_backend_modify_objects_sync
e_cal_backend_modify_objects
+e_cal_backend_modify_objects_finish
+e_cal_backend_remove_objects_sync
e_cal_backend_remove_objects
+e_cal_backend_remove_objects_finish
+e_cal_backend_receive_objects_sync
e_cal_backend_receive_objects
+e_cal_backend_receive_objects_finish
+e_cal_backend_send_objects_sync
e_cal_backend_send_objects
+e_cal_backend_send_objects_finish
+e_cal_backend_get_attachment_uris_sync
e_cal_backend_get_attachment_uris
+e_cal_backend_get_attachment_uris_finish
+e_cal_backend_discard_alarm_sync
e_cal_backend_discard_alarm
+e_cal_backend_discard_alarm_finish
+e_cal_backend_get_timezone_sync
e_cal_backend_get_timezone
+e_cal_backend_get_timezone_finish
+e_cal_backend_add_timezone_sync
e_cal_backend_add_timezone
+e_cal_backend_add_timezone_finish
e_cal_backend_start_view
e_cal_backend_stop_view
e_cal_backend_notify_component_created
@@ -60,6 +90,7 @@ ECalBackendClass
e_cal_backend_get_type
<SUBSECTION Private>
ECalBackendPrivate
+e_cal_backend_prepare_for_completion
</SECTION>
<SECTION>
@@ -247,7 +278,6 @@ e_data_cal_respond_receive_objects
e_data_cal_respond_send_objects
e_data_cal_respond_get_attachment_uris
e_data_cal_respond_discard_alarm
-e_data_cal_respond_get_view
e_data_cal_respond_get_timezone
e_data_cal_respond_add_timezone
e_data_cal_report_error
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]