[evolution-data-server/openismus-work-3-8] EBookClient: Implemented e_book_client_get_cursor() Sync and Async methods
- From: Tristan Van Berkom <tvb src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server/openismus-work-3-8] EBookClient: Implemented e_book_client_get_cursor() Sync and Async methods
- Date: Tue, 20 Aug 2013 11:13:56 +0000 (UTC)
commit 54d4c2e6b0a2ac9d60748925855c13696423a55a
Author: Tristan Van Berkom <tristanvb openismus com>
Date: Tue Jul 2 17:48:48 2013 +0900
EBookClient: Implemented e_book_client_get_cursor() Sync and Async methods
addressbook/libebook/e-book-client.c | 377 ++++++++++++++++++++++++++++++++++
addressbook/libebook/e-book-client.h | 22 ++
2 files changed, 399 insertions(+), 0 deletions(-)
---
diff --git a/addressbook/libebook/e-book-client.c b/addressbook/libebook/e-book-client.c
index 498df20..3fe3b01 100644
--- a/addressbook/libebook/e-book-client.c
+++ b/addressbook/libebook/e-book-client.c
@@ -66,10 +66,15 @@ struct _EBookClientPrivate {
struct _AsyncContext {
EContact *contact;
EBookClientView *client_view;
+ EBookClientCursor *client_cursor;
GSList *object_list;
GSList *string_list;
+ EContactField *sort_fields;
+ EBookSortType *sort_types;
+ guint n_sort_fields;
gchar *sexp;
gchar *uid;
+ GMainContext *context;
};
struct _SignalClosure {
@@ -124,6 +129,12 @@ async_context_free (AsyncContext *async_context)
if (async_context->client_view != NULL)
g_object_unref (async_context->client_view);
+ if (async_context->client_cursor != NULL)
+ g_object_unref (async_context->client_cursor);
+
+ if (async_context->context)
+ g_main_context_unref (async_context->context);
+
g_slist_free_full (
async_context->object_list,
(GDestroyNotify) g_object_unref);
@@ -132,6 +143,9 @@ async_context_free (AsyncContext *async_context)
async_context->string_list,
(GDestroyNotify) g_free);
+ g_free (async_context->sort_fields);
+ g_free (async_context->sort_types);
+
g_free (async_context->sexp);
g_free (async_context->uid);
@@ -987,6 +1001,13 @@ e_book_client_class_init (EBookClientClass *class)
client_class->open_sync = book_client_open_sync;
client_class->refresh_sync = book_client_refresh_sync;
+ /**
+ * EBookClient:locale:
+ *
+ * The currently active locale for this addressbook.
+ *
+ * Since: 3.10
+ */
g_object_class_install_property (
object_class,
PROP_LOCALE,
@@ -3553,6 +3574,362 @@ e_book_client_get_view_sync (EBookClient *client,
return success;
}
+/* Helper for e_book_client_get_cursor() */
+static const gchar **
+sort_param_to_strv (gpointer param,
+ gint n_fields,
+ gboolean keys)
+{
+ const gchar **array;
+ gint i;
+
+ array = (const gchar **)g_new0 (gchar *, n_fields + 1);
+
+ /* string arrays are shallow allocated, the strings themselves
+ * are intern strings and don't need to be dupped.
+ */
+ for (i = 0; i < n_fields; i++) {
+
+ if (keys) {
+ EContactField *fields = (EContactField *)param;
+
+ array[i] = e_contact_field_name (fields[i]);
+ } else {
+ EBookSortType *types = (EBookSortType *)param;
+
+ array[i] = e_enum_to_string (E_TYPE_BOOK_SORT_TYPE,
+ types[i]);
+ }
+ }
+
+ return array;
+}
+
+static void
+book_client_get_cursor_in_dbus_thread (GSimpleAsyncResult *simple,
+ GObject *source_object,
+ GCancellable *cancellable)
+{
+ EBookClient *client = E_BOOK_CLIENT (source_object);
+ AsyncContext *async_context;
+ gchar *utf8_sexp;
+ gchar *object_path = NULL;
+ GError *local_error = NULL;
+ const gchar **sort_fields;
+ const gchar **sort_types;
+
+ async_context = g_simple_async_result_get_op_res_gpointer (simple);
+ sort_fields = sort_param_to_strv (async_context->sort_fields, async_context->n_sort_fields, TRUE);
+ sort_types = sort_param_to_strv (async_context->sort_types, async_context->n_sort_fields, FALSE);
+
+ /* Direct Read Access cursor don't need any
+ * D-Bus connection themselves, just give them
+ * an EDataBookCursor directly
+ */
+ if (client->priv->direct_book) {
+ EBookBackend *backend;
+ EDataBookCursor *cursor;
+
+ backend = e_data_book_get_backend (client->priv->direct_book);
+
+ cursor = e_book_backend_create_cursor (backend,
+ async_context->sort_fields,
+ async_context->sort_types,
+ async_context->n_sort_fields,
+ &local_error);
+
+ if (cursor) {
+ if (!e_data_book_cursor_set_sexp (cursor,
+ async_context->sexp,
+ &local_error)) {
+ e_book_backend_delete_cursor (backend,
+ cursor);
+ cursor = NULL;
+ }
+ }
+
+ if (cursor != NULL) {
+ EBookClientCursor *client_cursor;
+
+ /* The client cursor will take a ref, but
+ * e_book_backend_create_cursor() returns
+ * a pointer to a cursor owned by the backend,
+ * don't unref the returned pointer here.
+ */
+ client_cursor = g_initable_new (
+ E_TYPE_BOOK_CLIENT_CURSOR,
+ cancellable, &local_error,
+ "sort-fields", sort_fields,
+ "client", client,
+ "context", async_context->context,
+ "direct-cursor", cursor,
+ NULL);
+
+ /* Sanity check. */
+ g_return_if_fail (
+ ((client_cursor != NULL) && (local_error == NULL)) ||
+ ((client_cursor == NULL) && (local_error != NULL)));
+
+ async_context->client_cursor = client_cursor;
+ }
+
+ } else {
+ utf8_sexp = e_util_utf8_make_valid (async_context->sexp);
+
+ e_dbus_address_book_call_get_cursor_sync (
+ client->priv->dbus_proxy, utf8_sexp,
+ (const gchar *const *)sort_fields,
+ (const gchar *const *)sort_types,
+ &object_path, cancellable, &local_error);
+
+ g_free (utf8_sexp);
+
+ /* Sanity check. */
+ g_return_if_fail (
+ ((object_path != NULL) && (local_error == NULL)) ||
+ ((object_path == NULL) && (local_error != NULL)));
+
+ if (object_path != NULL) {
+ GDBusConnection *connection;
+ EBookClientCursor *client_cursor;
+
+ connection = g_dbus_proxy_get_connection (
+ G_DBUS_PROXY (client->priv->dbus_proxy));
+
+ client_cursor = g_initable_new (
+ E_TYPE_BOOK_CLIENT_CURSOR,
+ cancellable, &local_error,
+ "sort-fields", sort_fields,
+ "client", client,
+ "context", async_context->context,
+ "connection", connection,
+ "object-path", object_path,
+ NULL);
+
+ /* Sanity check. */
+ g_return_if_fail (
+ ((client_cursor != NULL) && (local_error == NULL)) ||
+ ((client_cursor == NULL) && (local_error != NULL)));
+
+ async_context->client_cursor = client_cursor;
+
+ g_free (object_path);
+ }
+ }
+
+ if (local_error != NULL) {
+ g_dbus_error_strip_remote_error (local_error);
+ g_simple_async_result_take_error (simple, local_error);
+ }
+
+ g_free (sort_fields);
+ g_free (sort_types);
+}
+
+/* Need to catch the GMainContext of the actual caller,
+ * we do this dance because e_async_closure_new ()
+ * steps on the thread default main context (so we
+ * can use this in the sync call as well).
+ */
+static void
+e_book_client_get_cursor_with_context (EBookClient *client,
+ const gchar *sexp,
+ EContactField *sort_fields,
+ EBookSortType *sort_types,
+ guint n_fields,
+ GMainContext *context,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *simple;
+ AsyncContext *async_context;
+
+ g_return_if_fail (E_IS_BOOK_CLIENT (client));
+ g_return_if_fail (sort_fields != NULL);
+ g_return_if_fail (sort_types != NULL);
+ g_return_if_fail (n_fields > 0);
+
+ async_context = g_slice_new0 (AsyncContext);
+ async_context->sexp = g_strdup (sexp);
+ async_context->sort_fields = g_memdup (sort_fields, sizeof (EContactField) * n_fields);
+ async_context->sort_types = g_memdup (sort_types, sizeof (EBookSortType) * n_fields);
+ async_context->n_sort_fields = n_fields;
+ async_context->context = g_main_context_ref (context);
+
+ simple = g_simple_async_result_new (
+ G_OBJECT (client), callback, user_data,
+ e_book_client_get_cursor);
+
+ g_simple_async_result_set_check_cancellable (simple, cancellable);
+
+ g_simple_async_result_set_op_res_gpointer (
+ simple, async_context, (GDestroyNotify) async_context_free);
+
+ book_client_run_in_dbus_thread (
+ simple, book_client_get_cursor_in_dbus_thread,
+ G_PRIORITY_DEFAULT, cancellable);
+
+ g_object_unref (simple);
+}
+
+/**
+ * e_book_client_get_cursor:
+ * @client: an #EBookClient
+ * @sexp: an S-expression representing the query
+ * @sort_fields: an array of #EContactFields to sort the cursor with
+ * @sort_types: an array of #EBookSortTypes to complement @sort_fields
+ * @n_fields: the length of the input @sort_fields and @sort_types arrays
+ * @cancellable: a #GCancellable; can be %NULL
+ * @callback: callback to call when a result is ready
+ * @user_data: user data for the @callback
+ *
+ * Create an #EBookClientCursor.
+ * The call is finished by e_book_client_get_view_finish()
+ * from the @callback.
+ *
+ * Note: @sexp can be obtained through #EBookQuery, by converting it
+ * to a string with e_book_query_to_string().
+ *
+ * Since: 3.10
+ */
+void
+e_book_client_get_cursor (EBookClient *client,
+ const gchar *sexp,
+ EContactField *sort_fields,
+ EBookSortType *sort_types,
+ guint n_fields,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GMainContext *context;
+
+ context = g_main_context_ref_thread_default ();
+ e_book_client_get_cursor_with_context (client, sexp,
+ sort_fields,
+ sort_types,
+ n_fields,
+ context,
+ cancellable,
+ callback,
+ user_data);
+ g_main_context_unref (context);
+}
+
+/**
+ * e_book_client_get_cursor_finish:
+ * @client: an #EBookClient
+ * @result: a #GAsyncResult
+ * @out_cursor: (out): return location for an #EBookClientCursor
+ * @error: (out): a #GError to set an error, if any
+ *
+ * Finishes previous call of e_book_client_get_cursor().
+ * If successful, then the @out_cursor is set to newly create
+ * #EBookClientCursor, the cursor should be freed with g_object_unref()
+ * when no longer needed.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.10
+ */
+gboolean
+e_book_client_get_cursor_finish (EBookClient *client,
+ GAsyncResult *result,
+ EBookClientCursor **out_cursor,
+ GError **error)
+{
+ GSimpleAsyncResult *simple;
+ AsyncContext *async_context;
+
+ g_return_val_if_fail (E_IS_BOOK_CLIENT (client), FALSE);
+ g_return_val_if_fail (
+ g_simple_async_result_is_valid (
+ result, G_OBJECT (client),
+ e_book_client_get_cursor), 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;
+
+ g_return_val_if_fail (async_context->client_cursor != NULL, FALSE);
+
+ if (out_cursor != NULL)
+ *out_cursor = g_object_ref (async_context->client_cursor);
+
+ return TRUE;
+}
+
+/**
+ * e_book_client_get_cursor_sync:
+ * @client: an #EBookClient
+ * @sexp: an S-expression representing the query
+ * @sort_fields: an array of #EContactFields to sort the cursor with
+ * @sort_types: an array of #EBookSortTypes to complement @sort_fields
+ * @n_fields: the length of the input @sort_fields and @sort_types arrays
+ * @out_cursor: (out): return location for an #EBookClientCursor
+ * @cancellable: a #GCancellable; can be %NULL
+ * @error: (out): a #GError to set an error, if any
+ *
+ * Create an #EBookClientCursor. If successful, then the @out_cursor is set
+ * to newly allocated #EBookClientCursor, the cursor should be freed with g_object_unref()
+ * when no longer needed.
+ *
+ * Note: @sexp can be obtained through #EBookQuery, by converting it
+ * to a string with e_book_query_to_string().
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.10
+ */
+gboolean
+e_book_client_get_cursor_sync (EBookClient *client,
+ const gchar *sexp,
+ EContactField *sort_fields,
+ EBookSortType *sort_types,
+ guint n_fields,
+ EBookClientCursor **out_cursor,
+ GCancellable *cancellable,
+ GError **error)
+{
+ EAsyncClosure *closure;
+ GAsyncResult *result;
+ gboolean success;
+ GMainContext *context;
+
+ g_return_val_if_fail (E_IS_BOOK_CLIENT (client), FALSE);
+ g_return_val_if_fail (sort_fields != NULL, FALSE);
+ g_return_val_if_fail (sort_types != NULL, FALSE);
+ g_return_val_if_fail (n_fields > 0, FALSE);
+ g_return_val_if_fail (out_cursor != NULL, FALSE);
+
+ /* Get the main context before e_async_closure_new () steps on it */
+ context = g_main_context_ref_thread_default ();
+
+ closure = e_async_closure_new ();
+
+ e_book_client_get_cursor_with_context (client, sexp,
+ sort_fields,
+ sort_types,
+ n_fields,
+ context,
+ cancellable,
+ e_async_closure_callback, closure);
+
+ g_main_context_unref (context);
+
+ result = e_async_closure_wait (closure);
+
+ success = e_book_client_get_cursor_finish (
+ client, result, out_cursor, error);
+
+ e_async_closure_free (closure);
+
+ return success;
+}
+
static void
book_client_set_locale (EBookClient *client,
const gchar *locale)
diff --git a/addressbook/libebook/e-book-client.h b/addressbook/libebook/e-book-client.h
index d4f72fa..8c7135f 100644
--- a/addressbook/libebook/e-book-client.h
+++ b/addressbook/libebook/e-book-client.h
@@ -29,6 +29,7 @@
#include <libedataserver/libedataserver.h>
#include <libebook/e-book-client-view.h>
+#include <libebook/e-book-client-cursor.h>
#include <libebook-contacts/libebook-contacts.h>
/* Standard GObject macros */
@@ -282,8 +283,29 @@ gboolean e_book_client_get_view_sync (EBookClient *client,
EBookClientView **out_view,
GCancellable *cancellable,
GError **error);
+void e_book_client_get_cursor (EBookClient *client,
+ const gchar *sexp,
+ EContactField *sort_fields,
+ EBookSortType *sort_types,
+ guint n_fields,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean e_book_client_get_cursor_finish (EBookClient *client,
+ GAsyncResult *result,
+ EBookClientCursor **out_cursor,
+ GError **error);
+gboolean e_book_client_get_cursor_sync (EBookClient *client,
+ const gchar *sexp,
+ EContactField *sort_fields,
+ EBookSortType *sort_types,
+ guint n_fields,
+ EBookClientCursor **out_cursor,
+ GCancellable *cancellable,
+ GError **error);
const gchar *e_book_client_get_locale (EBookClient *client);
+
#ifndef EDS_DISABLE_DEPRECATED
/**
* BOOK_BACKEND_PROPERTY_SUPPORTED_AUTH_METHODS:
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]