4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) version 3.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with the program; if not, see <http://www.gnu.org/licenses/>
18 * Copyright (C) 2011 Red Hat, Inc. (www.redhat.com)
19 * Copyright (C) 2012 Intel Corporation
28 #include <glib/gi18n-lib.h>
31 /* Private D-Bus classes. */
32 #include <e-dbus-address-book.h>
33 #include <e-dbus-address-book-factory.h>
34 #include <e-dbus-direct-book.h>
36 #include <libedataserver/libedataserver.h>
37 #include <libedataserver/e-client-private.h>
39 #include <libebackend/libebackend.h>
40 #include <libedata-book/libedata-book.h>
42 #include "e-book-client.h"
44 #define E_BOOK_CLIENT_GET_PRIVATE(obj) \
45 (G_TYPE_INSTANCE_GET_PRIVATE \
46 ((obj), E_TYPE_BOOK_CLIENT, EBookClientPrivate))
48 /* Set this to a sufficiently large value
49 * to cover most long-running operations. */
50 #define DBUS_PROXY_TIMEOUT_MS (3 * 60 * 1000) /* 3 minutes */
52 typedef struct _AsyncContext AsyncContext;
53 typedef struct _SignalClosure SignalClosure;
54 typedef struct _ConnectClosure ConnectClosure;
55 typedef struct _RunInThreadClosure RunInThreadClosure;
57 struct _EBookClientPrivate {
58 EDBusAddressBook *dbus_proxy;
59 EBookBackend *direct_backend;
60 guint name_watcher_id;
62 gulong dbus_proxy_error_handler_id;
63 gulong dbus_proxy_notify_handler_id;
66 struct _AsyncContext {
68 EBookClientView *client_view;
75 struct _SignalClosure {
81 struct _ConnectClosure {
83 GCancellable *cancellable;
86 struct _RunInThreadClosure {
87 GSimpleAsyncThreadFunc func;
88 GSimpleAsyncResult *simple;
89 GCancellable *cancellable;
92 /* Forward Declarations */
93 static void e_book_client_initable_init
94 (GInitableIface *interface);
95 static void e_book_client_async_initable_init
96 (GAsyncInitableIface *interface);
98 G_DEFINE_TYPE_WITH_CODE (
102 G_IMPLEMENT_INTERFACE (
104 e_book_client_initable_init)
105 G_IMPLEMENT_INTERFACE (
106 G_TYPE_ASYNC_INITABLE,
107 e_book_client_async_initable_init))
110 async_context_free (AsyncContext *async_context)
112 if (async_context->contact != NULL)
113 g_object_unref (async_context->contact);
115 if (async_context->client_view != NULL)
116 g_object_unref (async_context->client_view);
119 async_context->object_list,
120 (GDestroyNotify) g_object_unref);
123 async_context->string_list,
124 (GDestroyNotify) g_free);
126 g_free (async_context->sexp);
127 g_free (async_context->uid);
129 g_slice_free (AsyncContext, async_context);
133 signal_closure_free (SignalClosure *signal_closure)
135 g_weak_ref_set (&signal_closure->client, NULL);
137 g_free (signal_closure->property_name);
138 g_free (signal_closure->error_message);
140 g_slice_free (SignalClosure, signal_closure);
144 connect_closure_free (ConnectClosure *connect_closure)
146 if (connect_closure->source != NULL)
147 g_object_unref (connect_closure->source);
149 if (connect_closure->cancellable != NULL)
150 g_object_unref (connect_closure->cancellable);
152 g_slice_free (ConnectClosure, connect_closure);
156 run_in_thread_closure_free (RunInThreadClosure *run_in_thread_closure)
158 if (run_in_thread_closure->simple != NULL)
159 g_object_unref (run_in_thread_closure->simple);
161 if (run_in_thread_closure->cancellable != NULL)
162 g_object_unref (run_in_thread_closure->cancellable);
164 g_slice_free (RunInThreadClosure, run_in_thread_closure);
168 * Well-known book backend properties:
169 * @BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS: Retrieves comma-separated list
170 * of required fields by the backend. Use e_client_util_parse_comma_strings()
171 * to parse returned string value into a #GSList. These fields are required
172 * to be filled in for all contacts.
173 * @BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS: Retrieves comma-separated list
174 * of supported fields by the backend. Use e_client_util_parse_comma_strings()
175 * to parse returned string value into a #GSList. These fields can be
176 * stored for contacts.
178 * See also: @CLIENT_BACKEND_PROPERTY_OPENED, @CLIENT_BACKEND_PROPERTY_OPENING,
179 * @CLIENT_BACKEND_PROPERTY_ONLINE, @CLIENT_BACKEND_PROPERTY_READONLY
180 * @CLIENT_BACKEND_PROPERTY_CACHE_DIR, @CLIENT_BACKEND_PROPERTY_CAPABILITIES
183 static EBookBackend *
184 book_client_load_direct_backend (ESourceRegistry *registry,
186 const gchar *backend_path,
187 const gchar *backend_name,
191 static GHashTable *modules_table = NULL;
192 G_LOCK_DEFINE_STATIC (modules_table);
196 EBookBackend *backend;
197 EBookBackendFactoryClass *factory_class;
199 g_return_val_if_fail (backend_path != NULL, NULL);
200 g_return_val_if_fail (backend_name != NULL, NULL);
202 G_LOCK (modules_table);
204 if (modules_table == NULL)
205 modules_table = g_hash_table_new (
206 (GHashFunc) g_str_hash,
207 (GEqualFunc) g_str_equal);
209 module = g_hash_table_lookup (modules_table, backend_path);
211 if (module == NULL) {
212 module = e_module_new (backend_path);
213 g_hash_table_insert (
214 modules_table, g_strdup (backend_path), module);
217 G_UNLOCK (modules_table);
219 if (!g_type_module_use (G_TYPE_MODULE (module))) {
221 error, E_CLIENT_ERROR,
222 E_CLIENT_ERROR_OTHER_ERROR,
223 "Failed to use EModule at path '%s'",
228 factory_type = g_type_from_name (backend_name);
229 if (factory_type == G_TYPE_INVALID) {
231 error, E_CLIENT_ERROR,
232 E_CLIENT_ERROR_OTHER_ERROR,
233 "Failed to get backend factory '%s' "
234 "from EModule at path '%s'",
235 backend_name, backend_path);
236 g_type_module_unuse (G_TYPE_MODULE (module));
240 factory_class = g_type_class_ref (factory_type);
242 backend = g_object_new (
243 factory_class->backend_type,
244 "registry", registry,
245 "source", source, NULL);
247 /* The backend must be configured for direct access
248 * before calling g_initable_init(), since backends
249 * can access their content in initable_init(). */
250 e_book_backend_configure_direct (backend, config);
252 if (!g_initable_init (G_INITABLE (backend), NULL, error)) {
253 g_type_module_unuse (G_TYPE_MODULE (module));
254 g_object_unref (backend);
258 g_type_class_unref (factory_class);
260 /* XXX Until backend methods can be updated, EBookBackend
261 * still needs an EDataBook to catch "respond" calls. */
262 if (backend != NULL) {
263 EDataBook *data_book;
265 data_book = g_initable_new (
266 E_TYPE_DATA_BOOK, NULL, error,
267 "backend", backend, NULL);
269 if (data_book == NULL) {
270 g_type_module_unuse (G_TYPE_MODULE (module));
271 g_object_unref (backend);
275 g_clear_object (&data_book);
282 book_client_dbus_thread (gpointer user_data)
284 GMainContext *main_context = user_data;
285 GMainLoop *main_loop;
287 g_main_context_push_thread_default (main_context);
289 main_loop = g_main_loop_new (main_context, FALSE);
290 g_main_loop_run (main_loop);
291 g_main_loop_unref (main_loop);
293 g_main_context_pop_thread_default (main_context);
295 g_main_context_unref (main_context);
301 book_client_dbus_thread_init (gpointer unused)
303 GMainContext *main_context;
305 main_context = g_main_context_new ();
307 /* This thread terminates when the process itself terminates, so
308 * no need to worry about unreferencing the returned GThread. */
310 "book-client-dbus-thread",
311 book_client_dbus_thread,
312 g_main_context_ref (main_context));
317 static GMainContext *
318 book_client_ref_dbus_main_context (void)
320 static GOnce book_client_dbus_thread_once = G_ONCE_INIT;
323 &book_client_dbus_thread_once,
324 book_client_dbus_thread_init, NULL);
326 return g_main_context_ref (book_client_dbus_thread_once.retval);
330 book_client_run_in_dbus_thread_idle_cb (gpointer user_data)
332 RunInThreadClosure *closure = user_data;
333 GObject *source_object;
334 GAsyncResult *result;
336 result = G_ASYNC_RESULT (closure->simple);
337 source_object = g_async_result_get_source_object (result);
342 closure->cancellable);
344 if (source_object != NULL)
345 g_object_unref (source_object);
347 g_simple_async_result_complete_in_idle (closure->simple);
353 book_client_run_in_dbus_thread (GSimpleAsyncResult *simple,
354 GSimpleAsyncThreadFunc func,
356 GCancellable *cancellable)
358 RunInThreadClosure *closure;
359 GMainContext *main_context;
360 GSource *idle_source;
362 main_context = book_client_ref_dbus_main_context ();
364 closure = g_slice_new0 (RunInThreadClosure);
365 closure->func = func;
366 closure->simple = g_object_ref (simple);
368 if (G_IS_CANCELLABLE (cancellable))
369 closure->cancellable = g_object_ref (cancellable);
371 idle_source = g_idle_source_new ();
372 g_source_set_priority (idle_source, io_priority);
373 g_source_set_callback (
374 idle_source, book_client_run_in_dbus_thread_idle_cb,
375 closure, (GDestroyNotify) run_in_thread_closure_free);
376 g_source_attach (idle_source, main_context);
377 g_source_unref (idle_source);
379 g_main_context_unref (main_context);
383 book_client_emit_backend_died_idle_cb (gpointer user_data)
385 SignalClosure *signal_closure = user_data;
388 client = g_weak_ref_get (&signal_closure->client);
390 if (client != NULL) {
391 g_signal_emit_by_name (client, "backend-died");
392 g_object_unref (client);
399 book_client_emit_backend_error_idle_cb (gpointer user_data)
401 SignalClosure *signal_closure = user_data;
404 client = g_weak_ref_get (&signal_closure->client);
406 if (client != NULL) {
407 g_signal_emit_by_name (
408 client, "backend-error",
409 signal_closure->error_message);
410 g_object_unref (client);
417 book_client_emit_backend_property_changed_idle_cb (gpointer user_data)
419 SignalClosure *signal_closure = user_data;
422 client = g_weak_ref_get (&signal_closure->client);
424 if (client != NULL) {
425 gchar *prop_value = NULL;
427 /* XXX Despite appearances, this function does not block. */
428 e_client_get_backend_property_sync (
430 signal_closure->property_name,
431 &prop_value, NULL, NULL);
433 if (prop_value != NULL) {
434 g_signal_emit_by_name (
436 "backend-property-changed",
437 signal_closure->property_name,
442 g_object_unref (client);
449 book_client_dbus_proxy_error_cb (EDBusAddressBook *dbus_proxy,
450 const gchar *error_message,
451 GWeakRef *client_weak_ref)
455 client = g_weak_ref_get (client_weak_ref);
457 if (client != NULL) {
458 GSource *idle_source;
459 GMainContext *main_context;
460 SignalClosure *signal_closure;
462 signal_closure = g_slice_new0 (SignalClosure);
463 g_weak_ref_set (&signal_closure->client, client);
464 signal_closure->error_message = g_strdup (error_message);
466 main_context = e_client_ref_main_context (client);
468 idle_source = g_idle_source_new ();
469 g_source_set_callback (
471 book_client_emit_backend_error_idle_cb,
473 (GDestroyNotify) signal_closure_free);
474 g_source_attach (idle_source, main_context);
475 g_source_unref (idle_source);
477 g_main_context_unref (main_context);
479 g_object_unref (client);
484 book_client_dbus_proxy_notify_cb (EDBusAddressBook *dbus_proxy,
486 GWeakRef *client_weak_ref)
489 const gchar *backend_prop_name = NULL;
491 client = g_weak_ref_get (client_weak_ref);
495 if (g_str_equal (pspec->name, "cache-dir")) {
496 backend_prop_name = CLIENT_BACKEND_PROPERTY_CACHE_DIR;
499 if (g_str_equal (pspec->name, "capabilities")) {
503 backend_prop_name = CLIENT_BACKEND_PROPERTY_CAPABILITIES;
505 strv = e_dbus_address_book_dup_capabilities (dbus_proxy);
507 csv = g_strjoinv (",", strv);
510 e_client_set_capabilities (client, csv);
514 if (g_str_equal (pspec->name, "online")) {
517 backend_prop_name = CLIENT_BACKEND_PROPERTY_ONLINE;
519 online = e_dbus_address_book_get_online (dbus_proxy);
520 e_client_set_online (client, online);
523 if (g_str_equal (pspec->name, "required-fields")) {
524 backend_prop_name = BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS;
527 if (g_str_equal (pspec->name, "revision")) {
528 backend_prop_name = CLIENT_BACKEND_PROPERTY_REVISION;
531 if (g_str_equal (pspec->name, "supported-fields")) {
532 backend_prop_name = BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS;
535 if (g_str_equal (pspec->name, "writable")) {
538 backend_prop_name = CLIENT_BACKEND_PROPERTY_READONLY;
540 writable = e_dbus_address_book_get_writable (dbus_proxy);
541 e_client_set_readonly (client, !writable);
544 if (backend_prop_name != NULL) {
545 GSource *idle_source;
546 GMainContext *main_context;
547 SignalClosure *signal_closure;
549 signal_closure = g_slice_new0 (SignalClosure);
550 g_weak_ref_set (&signal_closure->client, client);
551 signal_closure->property_name = g_strdup (backend_prop_name);
553 main_context = e_client_ref_main_context (client);
555 idle_source = g_idle_source_new ();
556 g_source_set_callback (
558 book_client_emit_backend_property_changed_idle_cb,
560 (GDestroyNotify) signal_closure_free);
561 g_source_attach (idle_source, main_context);
562 g_source_unref (idle_source);
564 g_main_context_unref (main_context);
567 g_object_unref (client);
571 book_client_name_vanished_cb (GDBusConnection *connection,
573 GWeakRef *client_weak_ref)
577 client = g_weak_ref_get (client_weak_ref);
579 if (client != NULL) {
580 GSource *idle_source;
581 GMainContext *main_context;
582 SignalClosure *signal_closure;
584 signal_closure = g_slice_new0 (SignalClosure);
585 g_weak_ref_set (&signal_closure->client, client);
587 main_context = e_client_ref_main_context (client);
589 idle_source = g_idle_source_new ();
590 g_source_set_callback (
592 book_client_emit_backend_died_idle_cb,
594 (GDestroyNotify) signal_closure_free);
595 g_source_attach (idle_source, main_context);
596 g_source_unref (idle_source);
598 g_main_context_unref (main_context);
600 g_object_unref (client);
605 book_client_dispose (GObject *object)
607 EBookClientPrivate *priv;
609 priv = E_BOOK_CLIENT_GET_PRIVATE (object);
611 if (priv->dbus_proxy_error_handler_id > 0) {
612 g_signal_handler_disconnect (
614 priv->dbus_proxy_error_handler_id);
615 priv->dbus_proxy_error_handler_id = 0;
618 if (priv->dbus_proxy_notify_handler_id > 0) {
619 g_signal_handler_disconnect (
621 priv->dbus_proxy_notify_handler_id);
622 priv->dbus_proxy_notify_handler_id = 0;
625 if (priv->dbus_proxy != NULL) {
626 /* Call close() asynchronously so we don't block dispose().
627 * Also omit a callback function, so the GDBusMessage uses
628 * G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED. */
629 e_dbus_address_book_call_close (
630 priv->dbus_proxy, NULL, NULL, NULL);
631 g_object_unref (priv->dbus_proxy);
632 priv->dbus_proxy = NULL;
635 if (priv->direct_backend != NULL) {
636 g_object_unref (priv->direct_backend);
637 priv->direct_backend = NULL;
640 /* Chain up to parent's dispose() method. */
641 G_OBJECT_CLASS (e_book_client_parent_class)->dispose (object);
645 book_client_finalize (GObject *object)
647 EBookClientPrivate *priv;
649 priv = E_BOOK_CLIENT_GET_PRIVATE (object);
651 if (priv->name_watcher_id > 0)
652 g_bus_unwatch_name (priv->name_watcher_id);
654 /* Chain up to parent's finalize() method. */
655 G_OBJECT_CLASS (e_book_client_parent_class)->finalize (object);
659 book_client_get_dbus_proxy (EClient *client)
661 EBookClientPrivate *priv;
663 priv = E_BOOK_CLIENT_GET_PRIVATE (client);
665 return G_DBUS_PROXY (priv->dbus_proxy);
669 book_client_get_backend_property_sync (EClient *client,
670 const gchar *prop_name,
672 GCancellable *cancellable,
675 EBookClient *book_client;
676 EDBusAddressBook *dbus_proxy;
679 book_client = E_BOOK_CLIENT (client);
680 dbus_proxy = book_client->priv->dbus_proxy;
682 if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_OPENED)) {
683 *prop_value = g_strdup ("TRUE");
687 if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_OPENING)) {
688 *prop_value = g_strdup ("FALSE");
692 if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_ONLINE)) {
693 if (e_dbus_address_book_get_online (dbus_proxy))
694 *prop_value = g_strdup ("TRUE");
696 *prop_value = g_strdup ("FALSE");
700 if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_READONLY)) {
701 if (e_dbus_address_book_get_writable (dbus_proxy))
702 *prop_value = g_strdup ("FALSE");
704 *prop_value = g_strdup ("TRUE");
708 if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_CACHE_DIR)) {
709 *prop_value = e_dbus_address_book_dup_cache_dir (dbus_proxy);
713 if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_REVISION)) {
714 *prop_value = e_dbus_address_book_dup_revision (dbus_proxy);
718 if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_CAPABILITIES)) {
719 strv = e_dbus_address_book_dup_capabilities (dbus_proxy);
721 *prop_value = g_strjoinv (",", strv);
723 *prop_value = g_strdup ("");
728 if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS)) {
729 strv = e_dbus_address_book_dup_required_fields (dbus_proxy);
731 *prop_value = g_strjoinv (",", strv);
733 *prop_value = g_strdup ("");
738 if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS)) {
739 strv = e_dbus_address_book_dup_supported_fields (dbus_proxy);
741 *prop_value = g_strjoinv (",", strv);
743 *prop_value = g_strdup ("");
749 error, E_CLIENT_ERROR, E_CLIENT_ERROR_NOT_SUPPORTED,
750 _("Unknown book property '%s'"), prop_name);
756 book_client_set_backend_property_sync (EClient *client,
757 const gchar *prop_name,
758 const gchar *prop_value,
759 GCancellable *cancellable,
763 error, E_CLIENT_ERROR,
764 E_CLIENT_ERROR_NOT_SUPPORTED,
765 _("Cannot change value of book property '%s'"),
772 book_client_open_sync (EClient *client,
773 gboolean only_if_exists,
774 GCancellable *cancellable,
777 EBookClient *book_client;
778 GError *local_error = NULL;
780 g_return_val_if_fail (E_IS_BOOK_CLIENT (client), FALSE);
782 book_client = E_BOOK_CLIENT (client);
784 e_dbus_address_book_call_open_sync (
785 book_client->priv->dbus_proxy, cancellable, &local_error);
787 if (local_error != NULL) {
788 g_dbus_error_strip_remote_error (local_error);
789 g_propagate_error (error, local_error);
797 book_client_refresh_sync (EClient *client,
798 GCancellable *cancellable,
801 EBookClient *book_client;
802 GError *local_error = NULL;
804 g_return_val_if_fail (E_IS_BOOK_CLIENT (client), FALSE);
806 book_client = E_BOOK_CLIENT (client);
808 e_dbus_address_book_call_refresh_sync (
809 book_client->priv->dbus_proxy, cancellable, &local_error);
811 if (local_error != NULL) {
812 g_dbus_error_strip_remote_error (local_error);
813 g_propagate_error (error, local_error);
821 book_client_init_in_dbus_thread (GSimpleAsyncResult *simple,
822 GObject *source_object,
823 GCancellable *cancellable)
825 EBookClientPrivate *priv;
826 EDBusAddressBookFactory *factory_proxy;
827 GDBusConnection *connection;
832 gchar *object_path = NULL;
834 GError *local_error = NULL;
836 priv = E_BOOK_CLIENT_GET_PRIVATE (source_object);
838 client = E_CLIENT (source_object);
839 source = e_client_get_source (client);
840 uid = e_source_get_uid (source);
842 connection = g_bus_get_sync (
843 G_BUS_TYPE_SESSION, cancellable, &local_error);
847 ((connection != NULL) && (local_error == NULL)) ||
848 ((connection == NULL) && (local_error != NULL)));
850 if (local_error != NULL) {
851 g_dbus_error_strip_remote_error (local_error);
852 g_simple_async_result_take_error (simple, local_error);
856 factory_proxy = e_dbus_address_book_factory_proxy_new_sync (
858 G_DBUS_PROXY_FLAGS_NONE,
859 ADDRESS_BOOK_DBUS_SERVICE_NAME,
860 "/org/gnome/evolution/dataserver/AddressBookFactory",
861 cancellable, &local_error);
865 ((factory_proxy != NULL) && (local_error == NULL)) ||
866 ((factory_proxy == NULL) && (local_error != NULL)));
868 if (local_error != NULL) {
869 g_dbus_error_strip_remote_error (local_error);
870 g_simple_async_result_take_error (simple, local_error);
871 g_object_unref (connection);
875 e_dbus_address_book_factory_call_open_address_book_sync (
876 factory_proxy, uid, &object_path, cancellable, &local_error);
878 g_object_unref (factory_proxy);
882 ((object_path != NULL) && (local_error == NULL)) ||
883 ((object_path == NULL) && (local_error != NULL)));
885 if (local_error != NULL) {
886 g_dbus_error_strip_remote_error (local_error);
887 g_simple_async_result_take_error (simple, local_error);
888 g_object_unref (connection);
892 priv->dbus_proxy = e_dbus_address_book_proxy_new_sync (
894 G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
895 ADDRESS_BOOK_DBUS_SERVICE_NAME,
896 object_path, cancellable, &local_error);
898 g_free (object_path);
902 ((priv->dbus_proxy != NULL) && (local_error == NULL)) ||
903 ((priv->dbus_proxy == NULL) && (local_error != NULL)));
905 if (local_error != NULL) {
906 g_dbus_error_strip_remote_error (local_error);
907 g_simple_async_result_take_error (simple, local_error);
908 g_object_unref (connection);
912 /* Configure our new GDBusProxy. */
914 proxy = G_DBUS_PROXY (priv->dbus_proxy);
916 g_dbus_proxy_set_default_timeout (proxy, DBUS_PROXY_TIMEOUT_MS);
918 priv->name_watcher_id = g_bus_watch_name_on_connection (
920 g_dbus_proxy_get_name (proxy),
921 G_BUS_NAME_WATCHER_FLAGS_NONE,
922 (GBusNameAppearedCallback) NULL,
923 (GBusNameVanishedCallback) book_client_name_vanished_cb,
924 e_weak_ref_new (client),
925 (GDestroyNotify) e_weak_ref_free);
927 handler_id = g_signal_connect_data (
929 G_CALLBACK (book_client_dbus_proxy_error_cb),
930 e_weak_ref_new (client),
931 (GClosureNotify) e_weak_ref_free,
933 priv->dbus_proxy_error_handler_id = handler_id;
935 handler_id = g_signal_connect_data (
937 G_CALLBACK (book_client_dbus_proxy_notify_cb),
938 e_weak_ref_new (client),
939 (GClosureNotify) e_weak_ref_free,
941 priv->dbus_proxy_notify_handler_id = handler_id;
943 /* Initialize our public-facing GObject properties. */
944 g_object_notify (G_OBJECT (proxy), "online");
945 g_object_notify (G_OBJECT (proxy), "writable");
946 g_object_notify (G_OBJECT (proxy), "capabilities");
948 g_object_unref (connection);
952 book_client_initable_init (GInitable *initable,
953 GCancellable *cancellable,
956 EAsyncClosure *closure;
957 GAsyncResult *result;
960 closure = e_async_closure_new ();
962 g_async_initable_init_async (
963 G_ASYNC_INITABLE (initable),
964 G_PRIORITY_DEFAULT, cancellable,
965 e_async_closure_callback, closure);
967 result = e_async_closure_wait (closure);
969 success = g_async_initable_init_finish (
970 G_ASYNC_INITABLE (initable), result, error);
972 e_async_closure_free (closure);
978 book_client_initable_init_async (GAsyncInitable *initable,
980 GCancellable *cancellable,
981 GAsyncReadyCallback callback,
984 GSimpleAsyncResult *simple;
986 simple = g_simple_async_result_new (
987 G_OBJECT (initable), callback, user_data,
988 book_client_initable_init_async);
990 g_simple_async_result_set_check_cancellable (simple, cancellable);
992 book_client_run_in_dbus_thread (
993 simple, book_client_init_in_dbus_thread,
994 io_priority, cancellable);
996 g_object_unref (simple);
1000 book_client_initable_init_finish (GAsyncInitable *initable,
1001 GAsyncResult *result,
1004 GSimpleAsyncResult *simple;
1006 g_return_val_if_fail (
1007 g_simple_async_result_is_valid (
1008 result, G_OBJECT (initable),
1009 book_client_initable_init_async), FALSE);
1011 simple = G_SIMPLE_ASYNC_RESULT (result);
1013 /* Assume success unless a GError is set. */
1014 return !g_simple_async_result_propagate_error (simple, error);
1018 e_book_client_class_init (EBookClientClass *class)
1020 GObjectClass *object_class;
1021 EClientClass *client_class;
1023 g_type_class_add_private (class, sizeof (EBookClientPrivate));
1025 object_class = G_OBJECT_CLASS (class);
1026 object_class->dispose = book_client_dispose;
1027 object_class->finalize = book_client_finalize;
1029 client_class = E_CLIENT_CLASS (class);
1030 client_class->get_dbus_proxy = book_client_get_dbus_proxy;
1031 client_class->get_backend_property_sync = book_client_get_backend_property_sync;
1032 client_class->set_backend_property_sync = book_client_set_backend_property_sync;
1033 client_class->open_sync = book_client_open_sync;
1034 client_class->refresh_sync = book_client_refresh_sync;
1038 e_book_client_initable_init (GInitableIface *interface)
1040 interface->init = book_client_initable_init;
1044 e_book_client_async_initable_init (GAsyncInitableIface *interface)
1046 interface->init_async = book_client_initable_init_async;
1047 interface->init_finish = book_client_initable_init_finish;
1051 e_book_client_init (EBookClient *client)
1053 client->priv = E_BOOK_CLIENT_GET_PRIVATE (client);
1057 * e_book_client_connect_sync:
1058 * @source: an #ESource
1059 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
1060 * @error: return location for a #GError, or %NULL
1062 * Creates a new #EBookClient for @source. If an error occurs, the function
1063 * will set @error and return %FALSE.
1065 * Unlike with e_book_client_new(), there is no need to call
1066 * e_client_open_sync() after obtaining the #EBookClient.
1068 * For error handling convenience, any error message returned by this
1069 * function will have a descriptive prefix that includes the display
1072 * Returns: (transfer full) (type EBookClient): a new #EBookClient, or %NULL
1077 e_book_client_connect_sync (ESource *source,
1078 GCancellable *cancellable,
1081 EBookClient *client;
1082 GError *local_error = NULL;
1084 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
1086 client = g_object_new (
1088 "source", source, NULL);
1090 g_initable_init (G_INITABLE (client), cancellable, &local_error);
1092 if (local_error == NULL)
1093 e_dbus_address_book_call_open_sync (
1094 client->priv->dbus_proxy, cancellable, &local_error);
1096 if (local_error != NULL) {
1097 g_dbus_error_strip_remote_error (local_error);
1098 g_propagate_error (error, local_error);
1100 error, _("Unable to connect to '%s': "),
1101 e_source_get_display_name (source));
1102 g_object_unref (client);
1106 return E_CLIENT (client);
1109 /* Helper for e_book_client_connect() */
1111 book_client_connect_open_cb (GObject *source_object,
1112 GAsyncResult *result,
1115 GSimpleAsyncResult *simple;
1116 GError *local_error = NULL;
1118 simple = G_SIMPLE_ASYNC_RESULT (user_data);
1120 e_dbus_address_book_call_open_finish (
1121 E_DBUS_ADDRESS_BOOK (source_object), result, &local_error);
1123 if (local_error != NULL) {
1124 g_dbus_error_strip_remote_error (local_error);
1125 g_simple_async_result_take_error (simple, local_error);
1128 g_simple_async_result_complete (simple);
1130 g_object_unref (simple);
1133 /* Helper for e_book_client_connect() */
1135 book_client_connect_init_cb (GObject *source_object,
1136 GAsyncResult *result,
1139 GSimpleAsyncResult *simple;
1140 EBookClientPrivate *priv;
1141 ConnectClosure *closure;
1142 GError *local_error = NULL;
1144 simple = G_SIMPLE_ASYNC_RESULT (user_data);
1146 g_async_initable_init_finish (
1147 G_ASYNC_INITABLE (source_object), result, &local_error);
1149 if (local_error != NULL) {
1150 g_simple_async_result_take_error (simple, local_error);
1151 g_simple_async_result_complete (simple);
1155 /* Note, we're repurposing some function parameters. */
1157 result = G_ASYNC_RESULT (simple);
1158 source_object = g_async_result_get_source_object (result);
1159 closure = g_simple_async_result_get_op_res_gpointer (simple);
1161 priv = E_BOOK_CLIENT_GET_PRIVATE (source_object);
1163 e_dbus_address_book_call_open (
1165 closure->cancellable,
1166 book_client_connect_open_cb,
1167 g_object_ref (simple));
1169 g_object_unref (source_object);
1172 g_object_unref (simple);
1176 * e_book_client_connect:
1177 * @source: an #ESource
1178 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
1179 * @callback: (scope async): a #GAsyncReadyCallback to call when the request
1181 * @user_data: (closure): data to pass to the callback function
1183 * Asynchronously creates a new #EBookClient for @source.
1185 * Unlike with e_book_client_new(), there is no need to call e_client_open()
1186 * after obtaining the #EBookClient.
1188 * When the operation is finished, @callback will be called. You can then
1189 * call e_book_client_connect_finish() to get the result of the operation.
1194 e_book_client_connect (ESource *source,
1195 GCancellable *cancellable,
1196 GAsyncReadyCallback callback,
1199 GSimpleAsyncResult *simple;
1200 ConnectClosure *closure;
1201 EBookClient *client;
1203 g_return_if_fail (E_IS_SOURCE (source));
1205 /* Two things with this: 1) instantiate the client object
1206 * immediately to make sure the thread-default GMainContext
1207 * gets plucked, and 2) do not call the D-Bus open() method
1208 * from our designated D-Bus thread -- it may take a long
1209 * time and block other clients from receiving signals. */
1211 closure = g_slice_new0 (ConnectClosure);
1212 closure->source = g_object_ref (source);
1214 if (G_IS_CANCELLABLE (cancellable))
1215 closure->cancellable = g_object_ref (cancellable);
1217 client = g_object_new (
1219 "source", source, NULL);
1221 simple = g_simple_async_result_new (
1222 G_OBJECT (client), callback,
1223 user_data, e_book_client_connect);
1225 g_simple_async_result_set_check_cancellable (simple, cancellable);
1227 g_simple_async_result_set_op_res_gpointer (
1228 simple, closure, (GDestroyNotify) connect_closure_free);
1230 g_async_initable_init_async (
1231 G_ASYNC_INITABLE (client),
1232 G_PRIORITY_DEFAULT, cancellable,
1233 book_client_connect_init_cb,
1234 g_object_ref (simple));
1236 g_object_unref (simple);
1237 g_object_unref (client);
1241 * e_book_client_connect_finish:
1242 * @result: a #GAsyncResult
1243 * @error: return location for a #GError, or %NULL
1245 * Finishes the operation started with e_book_client_connect(). If an
1246 * error occurs in connecting to the D-Bus service, the function sets
1247 * @error and returns %NULL.
1249 * For error handling convenience, any error message returned by this
1250 * function will have a descriptive prefix that includes the display
1251 * name of the #ESource passed to e_book_client_connect().
1253 * Returns: (transfer full) (type EBookClient): a new #EBookClient, or %NULL
1258 e_book_client_connect_finish (GAsyncResult *result,
1261 GSimpleAsyncResult *simple;
1262 ConnectClosure *closure;
1263 gpointer source_tag;
1265 g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (result), NULL);
1267 simple = G_SIMPLE_ASYNC_RESULT (result);
1268 closure = g_simple_async_result_get_op_res_gpointer (simple);
1270 source_tag = g_simple_async_result_get_source_tag (simple);
1271 g_return_val_if_fail (source_tag == e_book_client_connect, NULL);
1273 if (g_simple_async_result_propagate_error (simple, error)) {
1275 error, _("Unable to connect to '%s': "),
1276 e_source_get_display_name (closure->source));
1280 return E_CLIENT (g_async_result_get_source_object (result));
1284 * e_book_client_new:
1285 * @source: An #ESource pointer
1286 * @error: A #GError pointer
1288 * Creates a new #EBookClient corresponding to the given source. There are
1289 * only two operations that are valid on this book at this point:
1290 * e_client_open(), and e_client_remove().
1292 * Returns: a new but unopened #EBookClient.
1296 * Deprecated: 3.8: It covertly makes synchronous D-Bus calls, with no
1297 * way to cancel. Use e_book_client_connect() instead,
1298 * which combines e_book_client_new() and e_client_open()
1302 e_book_client_new (ESource *source,
1305 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
1307 return g_initable_new (
1308 E_TYPE_BOOK_CLIENT, NULL, error,
1309 "source", source, NULL);
1312 /* Direct Read Access connect helper */
1314 connect_direct (EBookClient *client,
1315 GCancellable *cancellable,
1316 ESourceRegistry *registry)
1318 EBookClientPrivate *priv;
1319 EDBusDirectBook *direct_config;
1320 const gchar *backend_name, *backend_path, *config;
1322 priv = E_BOOK_CLIENT_GET_PRIVATE (client);
1325 g_object_ref (registry);
1327 registry = e_source_registry_new_sync (cancellable, NULL);
1333 direct_config = e_dbus_direct_book_proxy_new_sync (
1334 g_dbus_proxy_get_connection (G_DBUS_PROXY (priv->dbus_proxy)),
1335 G_DBUS_PROXY_FLAGS_NONE,
1336 ADDRESS_BOOK_DBUS_SERVICE_NAME,
1337 g_dbus_proxy_get_object_path (G_DBUS_PROXY (priv->dbus_proxy)),
1340 backend_path = e_dbus_direct_book_get_backend_path (direct_config);
1341 backend_name = e_dbus_direct_book_get_backend_name (direct_config);
1342 config = e_dbus_direct_book_get_backend_config (direct_config);
1344 if (backend_path != NULL && *backend_path != '\0' &&
1345 backend_name != NULL && *backend_name != '\0') {
1346 priv->direct_backend = book_client_load_direct_backend (
1347 registry, e_client_get_source (E_CLIENT (client)),
1354 g_object_unref (direct_config);
1355 g_object_unref (registry);
1357 /* We have to perform the opening of the direct backend separately
1358 * from the EClient->open() implementation, because the direct
1359 * backend does not exist yet. */
1360 if (priv->direct_backend != NULL &&
1361 !e_book_backend_open_sync (priv->direct_backend,
1364 g_clear_object (&priv->direct_backend);
1368 * e_book_client_connect_direct_sync:
1369 * @registry: an #ESourceRegistry
1370 * @source: an #ESource
1371 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
1372 * @error: return location for a #GError, or %NULL
1374 * Like e_book_client_connect_sync(), except creates the book client for
1375 * direct read access to the underlying addressbook.
1377 * Returns: (transfer full) (type EBookClient): a new but unopened #EBookClient.
1382 e_book_client_connect_direct_sync (ESourceRegistry *registry,
1384 GCancellable *cancellable,
1389 client = e_book_client_connect_sync (source, cancellable, error);
1394 /* Connect the direct EDataBook connection */
1395 connect_direct (E_BOOK_CLIENT (client), cancellable, registry);
1401 /* Helper for e_book_client_connect_direct() */
1403 book_client_connect_direct_init_cb (GObject *source_object,
1404 GAsyncResult *result,
1407 GSimpleAsyncResult *simple;
1408 EBookClientPrivate *priv;
1409 ConnectClosure *closure;
1410 GError *error = NULL;
1412 simple = G_SIMPLE_ASYNC_RESULT (user_data);
1414 g_async_initable_init_finish (
1415 G_ASYNC_INITABLE (source_object), result, &error);
1417 if (error != NULL) {
1418 g_simple_async_result_take_error (simple, error);
1419 g_simple_async_result_complete (simple);
1423 /* Note, we're repurposing some function parameters. */
1424 result = G_ASYNC_RESULT (simple);
1425 source_object = g_async_result_get_source_object (result);
1426 closure = g_simple_async_result_get_op_res_gpointer (simple);
1428 priv = E_BOOK_CLIENT_GET_PRIVATE (source_object);
1430 e_dbus_address_book_call_open (
1432 closure->cancellable,
1433 book_client_connect_open_cb,
1434 g_object_ref (simple));
1436 /* Make the DRA connection */
1437 connect_direct (E_BOOK_CLIENT (source_object), closure->cancellable, NULL);
1439 g_object_unref (source_object);
1442 g_object_unref (simple);
1446 * e_book_client_connect_direct:
1447 * @source: an #ESource
1448 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
1449 * @callback: (scope async): a #GAsyncReadyCallback to call when the request
1451 * @user_data: (closure): data to pass to the callback function
1453 * Like e_book_client_connect(), except creates the book client for
1454 * direct read access to the underlying addressbook.
1456 * When the operation is finished, @callback will be called. You can then
1457 * call e_book_client_connect_direct_finish() to get the result of the operation.
1462 e_book_client_connect_direct (ESource *source,
1463 GCancellable *cancellable,
1464 GAsyncReadyCallback callback,
1467 GSimpleAsyncResult *simple;
1468 ConnectClosure *closure;
1469 EBookClient *client;
1471 g_return_if_fail (E_IS_SOURCE (source));
1473 /* Two things with this: 1) instantiate the client object
1474 * immediately to make sure the thread-default GMainContext
1475 * gets plucked, and 2) do not call the D-Bus open() method
1476 * from our designated D-Bus thread -- it may take a long
1477 * time and block other clients from receiving signals. */
1478 closure = g_slice_new0 (ConnectClosure);
1479 closure->source = g_object_ref (source);
1481 if (G_IS_CANCELLABLE (cancellable))
1482 closure->cancellable = g_object_ref (cancellable);
1484 client = g_object_new (
1486 "source", source, NULL);
1488 simple = g_simple_async_result_new (
1489 G_OBJECT (client), callback,
1490 user_data, e_book_client_connect_direct);
1492 g_simple_async_result_set_check_cancellable (simple, cancellable);
1494 g_simple_async_result_set_op_res_gpointer (
1495 simple, closure, (GDestroyNotify) connect_closure_free);
1497 g_async_initable_init_async (
1498 G_ASYNC_INITABLE (client),
1499 G_PRIORITY_DEFAULT, cancellable,
1500 book_client_connect_direct_init_cb,
1501 g_object_ref (simple));
1503 g_object_unref (simple);
1504 g_object_unref (client);
1508 * e_book_client_connect_direct_finish:
1509 * @result: a #GAsyncResult
1510 * @error: return location for a #GError, or %NULL
1512 * Finishes the operation started with e_book_client_connect_direct().
1513 * If an error occurs in connecting to the D-Bus service, the function sets
1514 * @error and returns %NULL.
1516 * For error handling convenience, any error message returned by this
1517 * function will have a descriptive prefix that includes the display
1518 * name of the #ESource passed to e_book_client_connect_direct().
1520 * Returns: (transfer full) (type EBookClient): a new #EBookClient, or %NULL
1525 e_book_client_connect_direct_finish (GAsyncResult *result,
1528 GSimpleAsyncResult *simple;
1529 ConnectClosure *closure;
1530 gpointer source_tag;
1532 g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (result), NULL);
1534 simple = G_SIMPLE_ASYNC_RESULT (result);
1535 closure = g_simple_async_result_get_op_res_gpointer (simple);
1537 source_tag = g_simple_async_result_get_source_tag (simple);
1538 g_return_val_if_fail (source_tag == e_book_client_connect_direct, NULL);
1540 if (g_simple_async_result_propagate_error (simple, error)) {
1542 error, _("Unable to connect to '%s': "),
1543 e_source_get_display_name (closure->source));
1547 return E_CLIENT (g_async_result_get_source_object (result));
1550 #define SELF_UID_PATH_ID "org.gnome.evolution-data-server.addressbook"
1551 #define SELF_UID_KEY "self-contact-uid"
1560 vcard = g_string_new ("BEGIN:VCARD\nVERSION:3.0\n");
1562 s = g_get_user_name ();
1564 g_string_append_printf (vcard, "NICKNAME:%s\n", s);
1566 s = g_get_real_name ();
1567 if (s && strcmp (s, "Unknown") != 0) {
1568 ENameWestern *western;
1570 g_string_append_printf (vcard, "FN:%s\n", s);
1572 western = e_name_western_parse (s);
1573 g_string_append_printf (
1574 vcard, "N:%s;%s;%s;%s;%s\n",
1575 western->last ? western->last : "",
1576 western->first ? western->first : "",
1577 western->middle ? western->middle : "",
1578 western->prefix ? western->prefix : "",
1579 western->suffix ? western->suffix : "");
1580 e_name_western_free (western);
1582 g_string_append (vcard, "END:VCARD");
1584 contact = e_contact_new_from_vcard (vcard->str);
1586 g_string_free (vcard, TRUE);
1592 * e_book_client_get_self:
1593 * @registry: an #ESourceRegistry
1594 * @out_contact: (out): an #EContact pointer to set
1595 * @out_client: (out): an #EBookClient pointer to set
1596 * @error: a #GError to set on failure
1598 * Get the #EContact referring to the user of the address book
1599 * and set it in @out_contact and @out_client.
1601 * Returns: %TRUE if successful, otherwise %FALSE.
1606 e_book_client_get_self (ESourceRegistry *registry,
1607 EContact **out_contact,
1608 EBookClient **out_client,
1611 EBookClient *book_client;
1613 EContact *contact = NULL;
1614 GSettings *settings;
1618 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), FALSE);
1619 g_return_val_if_fail (out_contact != NULL, FALSE);
1620 g_return_val_if_fail (out_client != NULL, FALSE);
1622 source = e_source_registry_ref_builtin_address_book (registry);
1623 book_client = e_book_client_new (source, error);
1624 g_object_unref (source);
1626 if (book_client == NULL)
1629 success = e_client_open_sync (
1630 E_CLIENT (book_client), FALSE, NULL, error);
1632 g_object_unref (book_client);
1636 *out_client = book_client;
1638 settings = g_settings_new (SELF_UID_PATH_ID);
1639 uid = g_settings_get_string (settings, SELF_UID_KEY);
1640 g_object_unref (settings);
1643 /* Don't care about errors because
1644 * we'll create a new card on failure. */
1645 e_book_client_get_contact_sync (
1646 book_client, uid, &contact, NULL, NULL);
1649 if (contact != NULL) {
1650 *out_client = book_client;
1651 *out_contact = contact;
1657 contact = make_me_card ();
1658 success = e_book_client_add_contact_sync (
1659 book_client, contact, &uid, NULL, error);
1661 g_object_unref (book_client);
1662 g_object_unref (contact);
1667 e_contact_set (contact, E_CONTACT_UID, uid);
1671 e_book_client_set_self (book_client, contact, NULL);
1673 *out_client = book_client;
1674 *out_contact = contact;
1680 * e_book_client_set_self:
1681 * @client: an #EBookClient
1682 * @contact: an #EContact
1683 * @error: a #GError to set on failure
1685 * Specify that @contact residing in @client is the #EContact that
1686 * refers to the user of the address book.
1688 * Returns: %TRUE if successful, %FALSE otherwise.
1693 e_book_client_set_self (EBookClient *client,
1697 GSettings *settings;
1699 g_return_val_if_fail (E_IS_BOOK_CLIENT (client), FALSE);
1700 g_return_val_if_fail (contact != NULL, FALSE);
1701 g_return_val_if_fail (
1702 e_contact_get_const (contact, E_CONTACT_UID) != NULL, FALSE);
1704 settings = g_settings_new (SELF_UID_PATH_ID);
1705 g_settings_set_string (
1706 settings, SELF_UID_KEY,
1707 e_contact_get_const (contact, E_CONTACT_UID));
1708 g_object_unref (settings);
1714 * e_book_client_is_self:
1715 * @contact: an #EContact
1717 * Check if @contact is the user of the address book.
1719 * Returns: %TRUE if @contact is the user, %FALSE otherwise.
1724 e_book_client_is_self (EContact *contact)
1726 static GSettings *settings;
1727 static GMutex mutex;
1728 const gchar *contact_uid;
1732 g_return_val_if_fail (contact && E_IS_CONTACT (contact), FALSE);
1735 * It would be nice to attach this instance to the EBookClient
1736 * instance so that it can be free again later, but
1737 * unfortunately the API doesn't allow that.
1739 g_mutex_lock (&mutex);
1741 settings = g_settings_new (SELF_UID_PATH_ID);
1742 uid = g_settings_get_string (settings, SELF_UID_KEY);
1743 g_mutex_unlock (&mutex);
1745 contact_uid = e_contact_get_const (contact, E_CONTACT_UID);
1746 is_self = (uid != NULL) && (g_strcmp0 (uid, contact_uid) == 0);
1753 /* Helper for e_book_client_add_contact() */
1755 book_client_add_contact_thread (GSimpleAsyncResult *simple,
1756 GObject *source_object,
1757 GCancellable *cancellable)
1759 AsyncContext *async_context;
1760 GError *local_error = NULL;
1762 async_context = g_simple_async_result_get_op_res_gpointer (simple);
1764 e_book_client_add_contact_sync (
1765 E_BOOK_CLIENT (source_object),
1766 async_context->contact,
1767 &async_context->uid,
1768 cancellable, &local_error);
1770 if (local_error != NULL)
1771 g_simple_async_result_take_error (simple, local_error);
1775 * e_book_client_add_contact:
1776 * @client: an #EBookClient
1777 * @contact: an #EContact
1778 * @cancellable: a #GCancellable; can be %NULL
1779 * @callback: callback to call when a result is ready
1780 * @user_data: user data for the @callback
1782 * Adds @contact to @client.
1783 * The call is finished by e_book_client_add_contact_finish()
1784 * from the @callback.
1789 e_book_client_add_contact (EBookClient *client,
1791 GCancellable *cancellable,
1792 GAsyncReadyCallback callback,
1795 GSimpleAsyncResult *simple;
1796 AsyncContext *async_context;
1798 g_return_if_fail (E_IS_BOOK_CLIENT (client));
1799 g_return_if_fail (E_IS_CONTACT (contact));
1801 async_context = g_slice_new0 (AsyncContext);
1802 async_context->contact = g_object_ref (contact);
1804 simple = g_simple_async_result_new (
1805 G_OBJECT (client), callback, user_data,
1806 e_book_client_add_contact);
1808 g_simple_async_result_set_check_cancellable (simple, cancellable);
1810 g_simple_async_result_set_op_res_gpointer (
1811 simple, async_context, (GDestroyNotify) async_context_free);
1813 g_simple_async_result_run_in_thread (
1814 simple, book_client_add_contact_thread,
1815 G_PRIORITY_DEFAULT, cancellable);
1817 g_object_unref (simple);
1821 * e_book_client_add_contact_finish:
1822 * @client: an #EBookClient
1823 * @result: a #GAsyncResult
1824 * @out_added_uid: (out): UID of a newly added contact; can be %NULL
1825 * @error: (out): a #GError to set an error, if any
1827 * Finishes previous call of e_book_client_add_contact() and
1828 * sets @out_added_uid to a UID of a newly added contact.
1829 * This string should be freed with g_free().
1831 * Note: This is not modifying original #EContact.
1833 * Returns: %TRUE if successful, %FALSE otherwise.
1838 e_book_client_add_contact_finish (EBookClient *client,
1839 GAsyncResult *result,
1840 gchar **out_added_uid,
1843 GSimpleAsyncResult *simple;
1844 AsyncContext *async_context;
1846 g_return_val_if_fail (
1847 g_simple_async_result_is_valid (
1848 result, G_OBJECT (client),
1849 e_book_client_add_contact), FALSE);
1851 simple = G_SIMPLE_ASYNC_RESULT (result);
1852 async_context = g_simple_async_result_get_op_res_gpointer (simple);
1854 if (g_simple_async_result_propagate_error (simple, error))
1857 g_return_val_if_fail (async_context->uid != NULL, FALSE);
1859 if (out_added_uid != NULL) {
1860 *out_added_uid = async_context->uid;
1861 async_context->uid = NULL;
1868 * e_book_client_add_contact_sync:
1869 * @client: an #EBookClient
1870 * @contact: an #EContact
1871 * @out_added_uid: (out): UID of a newly added contact; can be %NULL
1872 * @cancellable: a #GCancellable; can be %NULL
1873 * @error: (out): a #GError to set an error, if any
1875 * Adds @contact to @client and
1876 * sets @out_added_uid to a UID of a newly added contact.
1877 * This string should be freed with g_free().
1879 * Note: This is not modifying original @contact, thus if it's needed,
1880 * then use e_contact_set (contact, E_CONTACT_UID, new_uid).
1882 * Returns: %TRUE if successful, %FALSE otherwise.
1887 e_book_client_add_contact_sync (EBookClient *client,
1889 gchar **out_added_uid,
1890 GCancellable *cancellable,
1893 GSList link = { contact, NULL };
1894 GSList *uids = NULL;
1897 g_return_val_if_fail (E_IS_BOOK_CLIENT (client), FALSE);
1898 g_return_val_if_fail (E_IS_CONTACT (contact), FALSE);
1900 success = e_book_client_add_contacts_sync (
1901 client, &link, &uids, cancellable, error);
1904 g_return_val_if_fail (
1905 (success && (uids != NULL)) ||
1906 (!success && (uids == NULL)), FALSE);
1909 if (out_added_uid != NULL)
1910 *out_added_uid = g_strdup (uids->data);
1912 g_slist_free_full (uids, (GDestroyNotify) g_free);
1918 /* Helper for e_book_client_add_contacts() */
1920 book_client_add_contacts_thread (GSimpleAsyncResult *simple,
1921 GObject *source_object,
1922 GCancellable *cancellable)
1924 AsyncContext *async_context;
1925 GError *local_error = NULL;
1927 async_context = g_simple_async_result_get_op_res_gpointer (simple);
1929 e_book_client_add_contacts_sync (
1930 E_BOOK_CLIENT (source_object),
1931 async_context->object_list,
1932 &async_context->string_list,
1933 cancellable, &local_error);
1935 if (local_error != NULL)
1936 g_simple_async_result_take_error (simple, local_error);
1940 * e_book_client_add_contacts:
1941 * @client: an #EBookClient
1942 * @contacts: (element-type EContact): a #GSList of #EContact objects to add
1943 * @cancellable: (allow-none): a #GCancellable; can be %NULL
1944 * @callback: callback to call when a result is ready
1945 * @user_data: user data for the @callback
1947 * Adds @contacts to @client.
1948 * The call is finished by e_book_client_add_contacts_finish()
1949 * from the @callback.
1954 e_book_client_add_contacts (EBookClient *client,
1956 GCancellable *cancellable,
1957 GAsyncReadyCallback callback,
1960 GSimpleAsyncResult *simple;
1961 AsyncContext *async_context;
1963 g_return_if_fail (E_IS_BOOK_CLIENT (client));
1964 g_return_if_fail (contacts != NULL);
1966 async_context = g_slice_new0 (AsyncContext);
1967 async_context->object_list = g_slist_copy_deep (
1968 contacts, (GCopyFunc) g_object_ref, NULL);
1970 simple = g_simple_async_result_new (
1971 G_OBJECT (client), callback, user_data,
1972 e_book_client_add_contacts);
1974 g_simple_async_result_set_check_cancellable (simple, cancellable);
1976 g_simple_async_result_set_op_res_gpointer (
1977 simple, async_context, (GDestroyNotify) async_context_free);
1979 g_simple_async_result_run_in_thread (
1980 simple, book_client_add_contacts_thread,
1981 G_PRIORITY_DEFAULT, cancellable);
1983 g_object_unref (simple);
1987 * e_book_client_add_contacts_finish:
1988 * @client: an #EBookClient
1989 * @result: a #GAsyncResult
1990 * @out_added_uids: (out) (element-type utf8) (allow-none): UIDs of
1991 * newly added contacts; can be %NULL
1992 * @error: (out): a #GError to set an error, if any
1994 * Finishes previous call of e_book_client_add_contacts() and
1995 * sets @out_added_uids to the UIDs of newly added contacts if successful.
1996 * This #GSList should be freed with e_client_util_free_string_slist().
1998 * If any of the contacts cannot be inserted, all of the insertions will be
1999 * reverted and this method will return %FALSE.
2001 * Note: This is not modifying original #EContact objects.
2003 * Returns: %TRUE if successful, %FALSE otherwise.
2008 e_book_client_add_contacts_finish (EBookClient *client,
2009 GAsyncResult *result,
2010 GSList **out_added_uids,
2013 GSimpleAsyncResult *simple;
2014 AsyncContext *async_context;
2016 g_return_val_if_fail (
2017 g_simple_async_result_is_valid (
2018 result, G_OBJECT (client),
2019 e_book_client_add_contacts), FALSE);
2021 simple = G_SIMPLE_ASYNC_RESULT (result);
2022 async_context = g_simple_async_result_get_op_res_gpointer (simple);
2024 if (g_simple_async_result_propagate_error (simple, error))
2027 if (out_added_uids != NULL) {
2028 *out_added_uids = async_context->string_list;
2029 async_context->string_list = NULL;
2036 * e_book_client_add_contacts_sync:
2037 * @client: an #EBookClient
2038 * @contacts: (element-type EContact): a #GSList of #EContact objects to add
2039 * @out_added_uids: (out) (element-type utf8) (allow-none): UIDs of newly
2040 * added contacts; can be %NULL
2041 * @cancellable: a #GCancellable; can be %NULL
2042 * @error: (out): a #GError to set an error, if any
2044 * Adds @contacts to @client and
2045 * sets @out_added_uids to the UIDs of newly added contacts if successful.
2046 * This #GSList should be freed with e_client_util_free_string_slist().
2048 * If any of the contacts cannot be inserted, all of the insertions will be
2049 * reverted and this method will return %FALSE.
2051 * Note: This is not modifying original @contacts, thus if it's needed,
2052 * then use e_contact_set (contact, E_CONTACT_UID, new_uid).
2054 * Returns: %TRUE if successful, %FALSE otherwise.
2059 e_book_client_add_contacts_sync (EBookClient *client,
2061 GSList **out_added_uids,
2062 GCancellable *cancellable,
2067 gchar **uids = NULL;
2069 GError *local_error = NULL;
2071 g_return_val_if_fail (E_IS_BOOK_CLIENT (client), FALSE);
2072 g_return_val_if_fail (contacts != NULL, FALSE);
2074 /* Build a string array, ensuring each element is valid UTF-8. */
2075 strv = g_new0 (gchar *, g_slist_length (contacts) + 1);
2076 for (link = contacts; link != NULL; link = g_slist_next (link)) {
2080 vcard = E_VCARD (link->data);
2081 string = e_vcard_to_string (vcard, EVC_FORMAT_VCARD_30);
2082 strv[ii++] = e_util_utf8_make_valid (string);
2086 e_dbus_address_book_call_create_contacts_sync (
2087 client->priv->dbus_proxy,
2088 (const gchar * const *) strv,
2089 &uids, cancellable, &local_error);
2094 g_return_val_if_fail (
2095 ((uids != NULL) && (local_error == NULL)) ||
2096 ((uids == NULL) && (local_error != NULL)), FALSE);
2098 if (local_error != NULL) {
2099 g_dbus_error_strip_remote_error (local_error);
2100 g_propagate_error (error, local_error);
2104 /* XXX We should have passed the string array directly
2105 * back to the caller instead of building a linked
2106 * list. This is unnecessary work. */
2107 if (out_added_uids != NULL) {
2111 /* Take ownership of the string array elements. */
2112 for (ii = 0; uids[ii] != NULL; ii++) {
2113 tmp = g_slist_prepend (tmp, uids[ii]);
2117 *out_added_uids = g_slist_reverse (tmp);
2125 /* Helper for e_book_client_modify_contact() */
2127 book_client_modify_contact_thread (GSimpleAsyncResult *simple,
2128 GObject *source_object,
2129 GCancellable *cancellable)
2131 AsyncContext *async_context;
2132 GError *local_error = NULL;
2134 async_context = g_simple_async_result_get_op_res_gpointer (simple);
2136 e_book_client_modify_contact_sync (
2137 E_BOOK_CLIENT (source_object),
2138 async_context->contact,
2139 cancellable, &local_error);
2141 if (local_error != NULL)
2142 g_simple_async_result_take_error (simple, local_error);
2146 * e_book_client_modify_contact:
2147 * @client: an #EBookClient
2148 * @contact: an #EContact
2149 * @cancellable: a #GCancellable; can be %NULL
2150 * @callback: callback to call when a result is ready
2151 * @user_data: user data for the @callback
2153 * Applies the changes made to @contact to the stored version in @client.
2154 * The call is finished by e_book_client_modify_contact_finish()
2155 * from the @callback.
2160 e_book_client_modify_contact (EBookClient *client,
2162 GCancellable *cancellable,
2163 GAsyncReadyCallback callback,
2166 GSimpleAsyncResult *simple;
2167 AsyncContext *async_context;
2169 g_return_if_fail (E_IS_BOOK_CLIENT (client));
2170 g_return_if_fail (E_IS_CONTACT (contact));
2172 async_context = g_slice_new0 (AsyncContext);
2173 async_context->contact = g_object_ref (contact);
2175 simple = g_simple_async_result_new (
2176 G_OBJECT (client), callback, user_data,
2177 e_book_client_modify_contact);
2179 g_simple_async_result_set_check_cancellable (simple, cancellable);
2181 g_simple_async_result_set_op_res_gpointer (
2182 simple, async_context, (GDestroyNotify) async_context_free);
2184 g_simple_async_result_run_in_thread (
2185 simple, book_client_modify_contact_thread,
2186 G_PRIORITY_DEFAULT, cancellable);
2188 g_object_unref (simple);
2192 * e_book_client_modify_contact_finish:
2193 * @client: an #EBookClient
2194 * @result: a #GAsyncResult
2195 * @error: (out): a #GError to set an error, if any
2197 * Finishes previous call of e_book_client_modify_contact().
2199 * Returns: %TRUE if successful, %FALSE otherwise.
2204 e_book_client_modify_contact_finish (EBookClient *client,
2205 GAsyncResult *result,
2208 GSimpleAsyncResult *simple;
2210 g_return_val_if_fail (
2211 g_simple_async_result_is_valid (
2212 result, G_OBJECT (client),
2213 e_book_client_modify_contact), FALSE);
2215 simple = G_SIMPLE_ASYNC_RESULT (result);
2217 /* Assume success unless a GError is set. */
2218 return !g_simple_async_result_propagate_error (simple, error);
2222 * e_book_client_modify_contact_sync:
2223 * @client: an #EBookClient
2224 * @contact: an #EContact
2225 * @cancellable: a #GCancellable; can be %NULL
2226 * @error: (out): a #GError to set an error, if any
2228 * Applies the changes made to @contact to the stored version in @client.
2230 * Returns: %TRUE if successful, %FALSE otherwise.
2235 e_book_client_modify_contact_sync (EBookClient *client,
2237 GCancellable *cancellable,
2240 GSList link = { contact, NULL };
2242 g_return_val_if_fail (E_IS_BOOK_CLIENT (client), FALSE);
2243 g_return_val_if_fail (E_IS_CONTACT (contact), FALSE);
2245 return e_book_client_modify_contacts_sync (
2246 client, &link, cancellable, error);
2249 /* Helper for e_book_client_modify_contacts() */
2251 book_client_modify_contacts_thread (GSimpleAsyncResult *simple,
2252 GObject *source_object,
2253 GCancellable *cancellable)
2255 AsyncContext *async_context;
2256 GError *local_error = NULL;
2258 async_context = g_simple_async_result_get_op_res_gpointer (simple);
2260 e_book_client_modify_contacts_sync (
2261 E_BOOK_CLIENT (source_object),
2262 async_context->object_list,
2263 cancellable, &local_error);
2265 if (local_error != NULL)
2266 g_simple_async_result_take_error (simple, local_error);
2270 * e_book_client_modify_contacts:
2271 * @client: an #EBookClient
2272 * @contacts: (element-type EContact): a #GSList of #EContact objects
2273 * @cancellable: (allow-none): a #GCancellable; can be %NULL
2274 * @callback: callback to call when a result is ready
2275 * @user_data: user data for the @callback
2277 * Applies the changes made to @contacts to the stored versions in @client.
2278 * The call is finished by e_book_client_modify_contacts_finish()
2279 * from the @callback.
2284 e_book_client_modify_contacts (EBookClient *client,
2286 GCancellable *cancellable,
2287 GAsyncReadyCallback callback,
2290 GSimpleAsyncResult *simple;
2291 AsyncContext *async_context;
2293 g_return_if_fail (E_IS_BOOK_CLIENT (client));
2294 g_return_if_fail (contacts != NULL);
2296 async_context = g_slice_new0 (AsyncContext);
2297 async_context->object_list = g_slist_copy_deep (
2298 contacts, (GCopyFunc) g_object_ref, NULL);
2300 simple = g_simple_async_result_new (
2301 G_OBJECT (client), callback, user_data,
2302 e_book_client_modify_contacts);
2304 g_simple_async_result_set_check_cancellable (simple, cancellable);
2306 g_simple_async_result_set_op_res_gpointer (
2307 simple, async_context, (GDestroyNotify) async_context_free);
2309 g_simple_async_result_run_in_thread (
2310 simple, book_client_modify_contacts_thread,
2311 G_PRIORITY_DEFAULT, cancellable);
2313 g_object_unref (simple);
2317 * e_book_client_modify_contacts_finish:
2318 * @client: an #EBookClient
2319 * @result: a #GAsyncResult
2320 * @error: (out): a #GError to set an error, if any
2322 * Finishes previous call of e_book_client_modify_contacts().
2324 * Returns: %TRUE if successful, %FALSE otherwise.
2329 e_book_client_modify_contacts_finish (EBookClient *client,
2330 GAsyncResult *result,
2333 GSimpleAsyncResult *simple;
2335 g_return_val_if_fail (
2336 g_simple_async_result_is_valid (
2337 result, G_OBJECT (client),
2338 e_book_client_modify_contacts), FALSE);
2340 simple = G_SIMPLE_ASYNC_RESULT (result);
2342 /* Assume success unless a GError is set. */
2343 return !g_simple_async_result_propagate_error (simple, error);
2347 * e_book_client_modify_contacts_sync:
2348 * @client: an #EBookClient
2349 * @contacts: (element-type EContact): a #GSList of #EContact objects
2350 * @cancellable: (allow-none): a #GCancellable; can be %NULL
2351 * @error: (out): a #GError to set an error, if any
2353 * Applies the changes made to @contacts to the stored versions in @client.
2355 * Returns: %TRUE if successful, %FALSE otherwise.
2360 e_book_client_modify_contacts_sync (EBookClient *client,
2362 GCancellable *cancellable,
2368 GError *local_error = NULL;
2370 g_return_val_if_fail (E_IS_BOOK_CLIENT (client), FALSE);
2371 g_return_val_if_fail (contacts != NULL, FALSE);
2373 /* Build a string array, ensuring each element is valid UTF-8. */
2374 strv = g_new0 (gchar *, g_slist_length (contacts) + 1);
2375 for (link = contacts; link != NULL; link = g_slist_next (link)) {
2379 vcard = E_VCARD (link->data);
2380 string = e_vcard_to_string (vcard, EVC_FORMAT_VCARD_30);
2381 strv[ii++] = e_util_utf8_make_valid (string);
2385 e_dbus_address_book_call_modify_contacts_sync (
2386 client->priv->dbus_proxy,
2387 (const gchar * const *) strv,
2388 cancellable, &local_error);
2392 if (local_error != NULL) {
2393 g_dbus_error_strip_remote_error (local_error);
2394 g_propagate_error (error, local_error);
2401 /* Helper for e_book_client_remove_contact() */
2403 book_client_remove_contact_thread (GSimpleAsyncResult *simple,
2404 GObject *source_object,
2405 GCancellable *cancellable)
2407 AsyncContext *async_context;
2408 GError *local_error = NULL;
2410 async_context = g_simple_async_result_get_op_res_gpointer (simple);
2412 e_book_client_remove_contact_sync (
2413 E_BOOK_CLIENT (source_object),
2414 async_context->contact,
2415 cancellable, &local_error);
2417 if (local_error != NULL)
2418 g_simple_async_result_take_error (simple, local_error);
2422 * e_book_client_remove_contact:
2423 * @client: an #EBookClient
2424 * @contact: an #EContact
2425 * @cancellable: a #GCancellable; can be %NULL
2426 * @callback: callback to call when a result is ready
2427 * @user_data: user data for the @callback
2429 * Removes @contact from the @client.
2430 * The call is finished by e_book_client_remove_contact_finish()
2431 * from the @callback.
2436 e_book_client_remove_contact (EBookClient *client,
2437 /* const */ EContact *contact,
2438 GCancellable *cancellable,
2439 GAsyncReadyCallback callback,
2442 GSimpleAsyncResult *simple;
2443 AsyncContext *async_context;
2445 g_return_if_fail (E_IS_BOOK_CLIENT (client));
2446 g_return_if_fail (E_IS_CONTACT (contact));
2448 async_context = g_slice_new0 (AsyncContext);
2449 async_context->contact = g_object_ref (contact);
2451 simple = g_simple_async_result_new (
2452 G_OBJECT (client), callback, user_data,
2453 e_book_client_remove_contact);
2455 g_simple_async_result_set_check_cancellable (simple, cancellable);
2457 g_simple_async_result_set_op_res_gpointer (
2458 simple, async_context, (GDestroyNotify) async_context_free);
2460 g_simple_async_result_run_in_thread (
2461 simple, book_client_remove_contact_thread,
2462 G_PRIORITY_DEFAULT, cancellable);
2464 g_object_unref (simple);
2468 * e_book_client_remove_contact_finish:
2469 * @client: an #EBookClient
2470 * @result: a #GAsyncResult
2471 * @error: (out): a #GError to set an error, if any
2473 * Finishes previous call of e_book_client_remove_contact().
2475 * Returns: %TRUE if successful, %FALSE otherwise.
2480 e_book_client_remove_contact_finish (EBookClient *client,
2481 GAsyncResult *result,
2484 GSimpleAsyncResult *simple;
2486 g_return_val_if_fail (
2487 g_simple_async_result_is_valid (
2488 result, G_OBJECT (client),
2489 e_book_client_remove_contact), FALSE);
2491 simple = G_SIMPLE_ASYNC_RESULT (result);
2493 /* Assume success unless a GError is set. */
2494 return !g_simple_async_result_propagate_error (simple, error);
2498 * e_book_client_remove_contact_sync:
2499 * @client: an #EBookClient
2500 * @contact: an #EContact
2501 * @cancellable: a #GCancellable; can be %NULL
2502 * @error: (out): a #GError to set an error, if any
2504 * Removes @contact from the @client.
2506 * Returns: %TRUE if successful, %FALSE otherwise.
2511 e_book_client_remove_contact_sync (EBookClient *client,
2513 GCancellable *cancellable,
2518 g_return_val_if_fail (E_IS_BOOK_CLIENT (client), FALSE);
2519 g_return_val_if_fail (E_IS_CONTACT (contact), FALSE);
2521 uid = e_contact_get_const (contact, E_CONTACT_UID);
2522 g_return_val_if_fail (uid != NULL, FALSE);
2524 return e_book_client_remove_contact_by_uid_sync (
2525 client, uid, cancellable, error);
2528 /* Helper for e_book_client_remove_contact_by_uid() */
2530 book_client_remove_contact_by_uid_thread (GSimpleAsyncResult *simple,
2531 GObject *source_object,
2532 GCancellable *cancellable)
2534 AsyncContext *async_context;
2535 GError *local_error = NULL;
2537 async_context = g_simple_async_result_get_op_res_gpointer (simple);
2539 e_book_client_remove_contact_by_uid_sync (
2540 E_BOOK_CLIENT (source_object),
2542 cancellable, &local_error);
2544 if (local_error != NULL)
2545 g_simple_async_result_take_error (simple, local_error);
2549 * e_book_client_remove_contact_by_uid:
2550 * @client: an #EBookClient
2551 * @uid: a UID of a contact to remove
2552 * @cancellable: a #GCancellable; can be %NULL
2553 * @callback: callback to call when a result is ready
2554 * @user_data: user data for the @callback
2556 * Removes contact with @uid from the @client.
2557 * The call is finished by e_book_client_remove_contact_by_uid_finish()
2558 * from the @callback.
2563 e_book_client_remove_contact_by_uid (EBookClient *client,
2565 GCancellable *cancellable,
2566 GAsyncReadyCallback callback,
2569 GSimpleAsyncResult *simple;
2570 AsyncContext *async_context;
2572 g_return_if_fail (E_IS_BOOK_CLIENT (client));
2573 g_return_if_fail (uid != NULL);
2575 async_context = g_slice_new0 (AsyncContext);
2576 async_context->uid = g_strdup (uid);
2578 simple = g_simple_async_result_new (
2579 G_OBJECT (client), callback, user_data,
2580 e_book_client_remove_contact_by_uid);
2582 g_simple_async_result_set_check_cancellable (simple, cancellable);
2584 g_simple_async_result_set_op_res_gpointer (
2585 simple, async_context, (GDestroyNotify) async_context_free);
2587 g_simple_async_result_run_in_thread (
2588 simple, book_client_remove_contact_by_uid_thread,
2589 G_PRIORITY_DEFAULT, cancellable);
2591 g_object_unref (simple);
2595 * e_book_client_remove_contact_by_uid_finish:
2596 * @client: an #EBookClient
2597 * @result: a #GAsyncResult
2598 * @error: (out): a #GError to set an error, if any
2600 * Finishes previous call of e_book_client_remove_contact_by_uid().
2602 * Returns: %TRUE if successful, %FALSE otherwise.
2607 e_book_client_remove_contact_by_uid_finish (EBookClient *client,
2608 GAsyncResult *result,
2611 GSimpleAsyncResult *simple;
2613 g_return_val_if_fail (
2614 g_simple_async_result_is_valid (
2615 result, G_OBJECT (client),
2616 e_book_client_remove_contact_by_uid), FALSE);
2618 simple = G_SIMPLE_ASYNC_RESULT (result);
2620 /* Assume success unless a GError is set. */
2621 return !g_simple_async_result_propagate_error (simple, error);
2625 * e_book_client_remove_contact_by_uid_sync:
2626 * @client: an #EBookClient
2627 * @uid: a UID of a contact to remove
2628 * @cancellable: a #GCancellable; can be %NULL
2629 * @error: (out): a #GError to set an error, if any
2631 * Removes contact with @uid from the @client.
2633 * Returns: %TRUE if successful, %FALSE otherwise.
2638 e_book_client_remove_contact_by_uid_sync (EBookClient *client,
2640 GCancellable *cancellable,
2643 GSList link = { (gpointer) uid, NULL };
2645 g_return_val_if_fail (E_IS_BOOK_CLIENT (client), FALSE);
2646 g_return_val_if_fail (uid != NULL, FALSE);
2648 return e_book_client_remove_contacts_sync (
2649 client, &link, cancellable, error);
2652 /* Helper for e_book_client_remove_contacts() */
2654 book_client_remove_contacts_thread (GSimpleAsyncResult *simple,
2655 GObject *source_object,
2656 GCancellable *cancellable)
2658 AsyncContext *async_context;
2659 GError *local_error = NULL;
2661 async_context = g_simple_async_result_get_op_res_gpointer (simple);
2663 e_book_client_remove_contacts_sync (
2664 E_BOOK_CLIENT (source_object),
2665 async_context->string_list,
2666 cancellable, &local_error);
2668 if (local_error != NULL)
2669 g_simple_async_result_take_error (simple, local_error);
2673 * e_book_client_remove_contacts:
2674 * @client: an #EBookClient
2675 * @uids: (element-type utf8): a #GSList of UIDs to remove
2676 * @cancellable: a #GCancellable; can be %NULL
2677 * @callback: callback to call when a result is ready
2678 * @user_data: user data for the @callback
2680 * Removes the contacts with uids from the list @uids from @client. This is
2681 * always more efficient than calling e_book_client_remove_contact() if you
2682 * have more than one uid to remove, as some backends can implement it
2683 * as a batch request.
2684 * The call is finished by e_book_client_remove_contacts_finish()
2685 * from the @callback.
2690 e_book_client_remove_contacts (EBookClient *client,
2692 GCancellable *cancellable,
2693 GAsyncReadyCallback callback,
2696 GSimpleAsyncResult *simple;
2697 AsyncContext *async_context;
2699 g_return_if_fail (E_IS_BOOK_CLIENT (client));
2700 g_return_if_fail (uids != NULL);
2702 async_context = g_slice_new0 (AsyncContext);
2703 async_context->string_list = g_slist_copy_deep (
2704 (GSList *) uids, (GCopyFunc) g_strdup, NULL);
2706 simple = g_simple_async_result_new (
2707 G_OBJECT (client), callback, user_data,
2708 e_book_client_remove_contacts);
2710 g_simple_async_result_set_check_cancellable (simple, cancellable);
2712 g_simple_async_result_set_op_res_gpointer (
2713 simple, async_context, (GDestroyNotify) async_context_free);
2715 g_simple_async_result_run_in_thread (
2716 simple, book_client_remove_contacts_thread,
2717 G_PRIORITY_DEFAULT, cancellable);
2719 g_object_unref (simple);
2723 * e_book_client_remove_contacts_finish:
2724 * @client: an #EBookClient
2725 * @result: a #GAsyncResult
2726 * @error: (out): a #GError to set an error, if any
2728 * Finishes previous call of e_book_client_remove_contacts().
2730 * Returns: %TRUE if successful, %FALSE otherwise.
2735 e_book_client_remove_contacts_finish (EBookClient *client,
2736 GAsyncResult *result,
2739 GSimpleAsyncResult *simple;
2741 g_return_val_if_fail (
2742 g_simple_async_result_is_valid (
2743 result, G_OBJECT (client),
2744 e_book_client_remove_contacts), FALSE);
2746 simple = G_SIMPLE_ASYNC_RESULT (result);
2748 /* Assume success unless a GError is set. */
2749 return !g_simple_async_result_propagate_error (simple, error);
2753 * e_book_client_remove_contacts_sync:
2754 * @client: an #EBookClient
2755 * @uids: (element-type utf8): a #GSList of UIDs to remove
2756 * @cancellable: a #GCancellable; can be %NULL
2757 * @error: (out): a #GError to set an error, if any
2759 * Removes the contacts with uids from the list @uids from @client. This is
2760 * always more efficient than calling e_book_client_remove_contact() if you
2761 * have more than one uid to remove, as some backends can implement it
2762 * as a batch request.
2764 * Returns: %TRUE if successful, %FALSE otherwise.
2769 e_book_client_remove_contacts_sync (EBookClient *client,
2771 GCancellable *cancellable,
2776 GError *local_error = NULL;
2778 g_return_val_if_fail (E_IS_BOOK_CLIENT (client), FALSE);
2779 g_return_val_if_fail (uids != NULL, FALSE);
2781 strv = g_new0 (gchar *, g_slist_length ((GSList *) uids) + 1);
2782 while (uids != NULL) {
2783 strv[ii++] = e_util_utf8_make_valid (uids->data);
2784 uids = g_slist_next (uids);
2787 e_dbus_address_book_call_remove_contacts_sync (
2788 client->priv->dbus_proxy,
2789 (const gchar * const *) strv,
2790 cancellable, &local_error);
2794 if (local_error != NULL) {
2795 g_dbus_error_strip_remote_error (local_error);
2796 g_propagate_error (error, local_error);
2803 /* Helper for e_book_client_get_contact() */
2805 book_client_get_contact_thread (GSimpleAsyncResult *simple,
2806 GObject *source_object,
2807 GCancellable *cancellable)
2809 AsyncContext *async_context;
2810 GError *local_error = NULL;
2812 async_context = g_simple_async_result_get_op_res_gpointer (simple);
2814 e_book_client_get_contact_sync (
2815 E_BOOK_CLIENT (source_object),
2817 &async_context->contact,
2818 cancellable, &local_error);
2820 if (local_error != NULL)
2821 g_simple_async_result_take_error (simple, local_error);
2825 * e_book_client_get_contact:
2826 * @client: an #EBookClient
2827 * @uid: a unique string ID specifying the contact
2828 * @cancellable: a #GCancellable; can be %NULL
2829 * @callback: callback to call when a result is ready
2830 * @user_data: user data for the @callback
2832 * Receive #EContact from the @client for the gived @uid.
2833 * The call is finished by e_book_client_get_contact_finish()
2834 * from the @callback.
2839 e_book_client_get_contact (EBookClient *client,
2841 GCancellable *cancellable,
2842 GAsyncReadyCallback callback,
2845 GSimpleAsyncResult *simple;
2846 AsyncContext *async_context;
2848 g_return_if_fail (E_IS_BOOK_CLIENT (client));
2849 g_return_if_fail (uid != NULL);
2851 async_context = g_slice_new0 (AsyncContext);
2852 async_context->uid = g_strdup (uid);
2854 simple = g_simple_async_result_new (
2855 G_OBJECT (client), callback, user_data,
2856 e_book_client_get_contact);
2858 g_simple_async_result_set_check_cancellable (simple, cancellable);
2860 g_simple_async_result_set_op_res_gpointer (
2861 simple, async_context, (GDestroyNotify) async_context_free);
2863 g_simple_async_result_run_in_thread (
2864 simple, book_client_get_contact_thread,
2865 G_PRIORITY_DEFAULT, cancellable);
2867 g_object_unref (simple);
2871 * e_book_client_get_contact_finish:
2872 * @client: an #EBookClient
2873 * @result: a #GAsyncResult
2874 * @out_contact: (out): an #EContact for previously given uid
2875 * @error: (out): a #GError to set an error, if any
2877 * Finishes previous call of e_book_client_get_contact().
2878 * If successful, then the @out_contact is set to newly allocated
2879 * #EContact, which should be freed with g_object_unref().
2881 * Returns: %TRUE if successful, %FALSE otherwise.
2886 e_book_client_get_contact_finish (EBookClient *client,
2887 GAsyncResult *result,
2888 EContact **out_contact,
2891 GSimpleAsyncResult *simple;
2892 AsyncContext *async_context;
2894 g_return_val_if_fail (
2895 g_simple_async_result_is_valid (
2896 result, G_OBJECT (client),
2897 e_book_client_get_contact), FALSE);
2899 simple = G_SIMPLE_ASYNC_RESULT (result);
2900 async_context = g_simple_async_result_get_op_res_gpointer (simple);
2902 if (g_simple_async_result_propagate_error (simple, error))
2905 g_return_val_if_fail (async_context->contact != NULL, FALSE);
2907 if (out_contact != NULL)
2908 *out_contact = g_object_ref (async_context->contact);
2914 * e_book_client_get_contact_sync:
2915 * @client: an #EBookClient
2916 * @uid: a unique string ID specifying the contact
2917 * @out_contact: (out): an #EContact for given @uid
2918 * @cancellable: a #GCancellable; can be %NULL
2919 * @error: (out): a #GError to set an error, if any
2921 * Receive #EContact from the @client for the gived @uid.
2922 * If successful, then the @out_contact is set to newly allocated
2923 * #EContact, which should be freed with g_object_unref().
2925 * Returns: %TRUE if successful, %FALSE otherwise.
2930 e_book_client_get_contact_sync (EBookClient *client,
2932 EContact **out_contact,
2933 GCancellable *cancellable,
2937 gchar *vcard = NULL;
2938 GError *local_error = NULL;
2940 g_return_val_if_fail (E_IS_BOOK_CLIENT (client), FALSE);
2941 g_return_val_if_fail (uid != NULL, FALSE);
2942 g_return_val_if_fail (out_contact != NULL, FALSE);
2944 if (client->priv->direct_backend != NULL) {
2946 gboolean success = FALSE;
2948 /* Direct backend is not using D-Bus (obviously),
2949 * so no need to strip D-Bus info from the error. */
2950 contact = e_book_backend_get_contact_sync (
2951 client->priv->direct_backend,
2952 uid, cancellable, error);
2954 if (contact != NULL) {
2955 *out_contact = g_object_ref (contact);
2956 g_object_unref (contact);
2963 utf8_uid = e_util_utf8_make_valid (uid);
2965 e_dbus_address_book_call_get_contact_sync (
2966 client->priv->dbus_proxy, utf8_uid,
2967 &vcard, cancellable, &local_error);
2970 g_return_val_if_fail (
2971 ((vcard != NULL) && (local_error == NULL)) ||
2972 ((vcard == NULL) && (local_error != NULL)), FALSE);
2974 if (vcard != NULL) {
2976 e_contact_new_from_vcard_with_uid (vcard, utf8_uid);
2982 if (local_error != NULL) {
2983 g_dbus_error_strip_remote_error (local_error);
2984 g_propagate_error (error, local_error);
2991 /* Helper for e_book_client_get_contacts() */
2993 book_client_get_contacts_thread (GSimpleAsyncResult *simple,
2994 GObject *source_object,
2995 GCancellable *cancellable)
2997 AsyncContext *async_context;
2998 GError *local_error = NULL;
3000 async_context = g_simple_async_result_get_op_res_gpointer (simple);
3002 e_book_client_get_contacts_sync (
3003 E_BOOK_CLIENT (source_object),
3004 async_context->sexp,
3005 &async_context->object_list,
3006 cancellable, &local_error);
3008 if (local_error != NULL)
3009 g_simple_async_result_take_error (simple, local_error);
3013 * e_book_client_get_contacts:
3014 * @client: an #EBookClient
3015 * @sexp: an S-expression representing the query
3016 * @cancellable: a #GCancellable; can be %NULL
3017 * @callback: callback to call when a result is ready
3018 * @user_data: user data for the @callback
3020 * Query @client with @sexp, receiving a list of contacts which
3021 * matched. The call is finished by e_book_client_get_contacts_finish()
3022 * from the @callback.
3024 * Note: @sexp can be obtained through #EBookQuery, by converting it
3025 * to a string with e_book_query_to_string().
3030 e_book_client_get_contacts (EBookClient *client,
3032 GCancellable *cancellable,
3033 GAsyncReadyCallback callback,
3036 GSimpleAsyncResult *simple;
3037 AsyncContext *async_context;
3039 g_return_if_fail (E_IS_BOOK_CLIENT (client));
3040 g_return_if_fail (sexp != NULL);
3042 async_context = g_slice_new0 (AsyncContext);
3043 async_context->sexp = g_strdup (sexp);
3045 simple = g_simple_async_result_new (
3046 G_OBJECT (client), callback, user_data,
3047 e_book_client_get_contacts);
3049 g_simple_async_result_set_check_cancellable (simple, cancellable);
3051 g_simple_async_result_set_op_res_gpointer (
3052 simple, async_context, (GDestroyNotify) async_context_free);
3054 g_simple_async_result_run_in_thread (
3055 simple, book_client_get_contacts_thread,
3056 G_PRIORITY_DEFAULT, cancellable);
3058 g_object_unref (simple);
3062 * e_book_client_get_contacts_finish:
3063 * @client: an #EBookClient
3064 * @result: a #GAsyncResult
3065 * @out_contacts: (element-type EContact) (out) (transfer full): a #GSList
3066 * of matched #EContact-s
3067 * @error: (out): a #GError to set an error, if any
3069 * Finishes previous call of e_book_client_get_contacts().
3070 * If successful, then the @out_contacts is set to newly allocated list of
3071 * #EContact-s, which should be freed with e_client_util_free_object_slist().
3073 * Returns: %TRUE if successful, %FALSE otherwise.
3078 e_book_client_get_contacts_finish (EBookClient *client,
3079 GAsyncResult *result,
3080 GSList **out_contacts,
3083 GSimpleAsyncResult *simple;
3084 AsyncContext *async_context;
3086 g_return_val_if_fail (
3087 g_simple_async_result_is_valid (
3088 result, G_OBJECT (client),
3089 e_book_client_get_contacts), FALSE);
3091 simple = G_SIMPLE_ASYNC_RESULT (result);
3092 async_context = g_simple_async_result_get_op_res_gpointer (simple);
3094 if (g_simple_async_result_propagate_error (simple, error))
3097 if (out_contacts != NULL) {
3098 *out_contacts = async_context->object_list;
3099 async_context->object_list = NULL;
3106 * e_book_client_get_contacts_sync:
3107 * @client: an #EBookClient
3108 * @sexp: an S-expression representing the query
3109 * @out_contacts: (element-type EContact) (out): a #GSList of matched
3111 * @cancellable: a #GCancellable; can be %NULL
3112 * @error: (out): a #GError to set an error, if any
3114 * Query @client with @sexp, receiving a list of contacts which matched.
3115 * If successful, then the @out_contacts is set to newly allocated #GSList of
3116 * #EContact-s, which should be freed with e_client_util_free_object_slist().
3118 * Note: @sexp can be obtained through #EBookQuery, by converting it
3119 * to a string with e_book_query_to_string().
3121 * Returns: %TRUE if successful, %FALSE otherwise.
3126 e_book_client_get_contacts_sync (EBookClient *client,
3128 GSList **out_contacts,
3129 GCancellable *cancellable,
3133 gchar **vcards = NULL;
3134 GError *local_error = NULL;
3136 g_return_val_if_fail (E_IS_BOOK_CLIENT (client), FALSE);
3137 g_return_val_if_fail (sexp != NULL, FALSE);
3138 g_return_val_if_fail (out_contacts != NULL, FALSE);
3140 if (client->priv->direct_backend != NULL) {
3141 GQueue queue = G_QUEUE_INIT;
3142 GSList *list = NULL;
3145 /* Direct backend is not using D-Bus (obviously),
3146 * so no need to strip D-Bus info from the error. */
3147 success = e_book_backend_get_contact_list_sync (
3148 client->priv->direct_backend,
3149 sexp, &queue, cancellable, error);
3152 while (!g_queue_is_empty (&queue)) {
3155 contact = g_queue_pop_head (&queue);
3156 list = g_slist_prepend (list, contact);
3159 *out_contacts = g_slist_reverse (list);
3165 utf8_sexp = e_util_utf8_make_valid (sexp);
3167 e_dbus_address_book_call_get_contact_list_sync (
3168 client->priv->dbus_proxy, utf8_sexp,
3169 &vcards, cancellable, &local_error);
3174 g_return_val_if_fail (
3175 ((vcards != NULL) && (local_error == NULL)) ||
3176 ((vcards == NULL) && (local_error != NULL)), FALSE);
3178 if (vcards != NULL) {
3183 for (ii = 0; vcards[ii] != NULL; ii++) {
3184 contact = e_contact_new_from_vcard (vcards[ii]);
3185 tmp = g_slist_prepend (tmp, contact);
3188 *out_contacts = g_slist_reverse (tmp);
3190 g_strfreev (vcards);
3193 if (local_error != NULL) {
3194 g_dbus_error_strip_remote_error (local_error);
3195 g_propagate_error (error, local_error);
3202 /* Helper for e_book_client_get_contacts_uids() */
3204 book_client_get_contacts_uids_thread (GSimpleAsyncResult *simple,
3205 GObject *source_object,
3206 GCancellable *cancellable)
3208 AsyncContext *async_context;
3209 GError *local_error = NULL;
3211 async_context = g_simple_async_result_get_op_res_gpointer (simple);
3213 e_book_client_get_contacts_uids_sync (
3214 E_BOOK_CLIENT (source_object),
3215 async_context->sexp,
3216 &async_context->string_list,
3217 cancellable, &local_error);
3219 if (local_error != NULL)
3220 g_simple_async_result_take_error (simple, local_error);
3224 * e_book_client_get_contacts_uids:
3225 * @client: an #EBookClient
3226 * @sexp: an S-expression representing the query
3227 * @cancellable: a #GCancellable; can be %NULL
3228 * @callback: callback to call when a result is ready
3229 * @user_data: user data for the @callback
3231 * Query @client with @sexp, receiving a list of contacts UIDs which
3232 * matched. The call is finished by e_book_client_get_contacts_uids_finish()
3233 * from the @callback.
3235 * Note: @sexp can be obtained through #EBookQuery, by converting it
3236 * to a string with e_book_query_to_string().
3241 e_book_client_get_contacts_uids (EBookClient *client,
3243 GCancellable *cancellable,
3244 GAsyncReadyCallback callback,
3247 GSimpleAsyncResult *simple;
3248 AsyncContext *async_context;
3250 g_return_if_fail (E_IS_BOOK_CLIENT (client));
3251 g_return_if_fail (sexp != NULL);
3253 async_context = g_slice_new0 (AsyncContext);
3254 async_context->sexp = g_strdup (sexp);
3256 simple = g_simple_async_result_new (
3257 G_OBJECT (client), callback, user_data,
3258 e_book_client_get_contacts_uids);
3260 g_simple_async_result_set_check_cancellable (simple, cancellable);
3262 g_simple_async_result_set_op_res_gpointer (
3263 simple, async_context, (GDestroyNotify) async_context_free);
3265 g_simple_async_result_run_in_thread (
3266 simple, book_client_get_contacts_uids_thread,
3267 G_PRIORITY_DEFAULT, cancellable);
3269 g_object_unref (simple);
3273 * e_book_client_get_contacts_uids_finish:
3274 * @client: an #EBookClient
3275 * @result: a #GAsyncResult
3276 * @out_contact_uids: (element-type utf8) (out): a #GSList of matched
3277 * contact UIDs stored as strings
3278 * @error: (out): a #GError to set an error, if any
3280 * Finishes previous call of e_book_client_get_contacts_uids().
3281 * If successful, then the @out_contact_uids is set to newly allocated list
3282 * of UID strings, which should be freed with e_client_util_free_string_slist().
3284 * Returns: %TRUE if successful, %FALSE otherwise.
3289 e_book_client_get_contacts_uids_finish (EBookClient *client,
3290 GAsyncResult *result,
3291 GSList **out_contact_uids,
3294 GSimpleAsyncResult *simple;
3295 AsyncContext *async_context;
3297 g_return_val_if_fail (
3298 g_simple_async_result_is_valid (
3299 result, G_OBJECT (client),
3300 e_book_client_get_contacts_uids), FALSE);
3302 simple = G_SIMPLE_ASYNC_RESULT (result);
3303 async_context = g_simple_async_result_get_op_res_gpointer (simple);
3305 if (g_simple_async_result_propagate_error (simple, error))
3308 if (out_contact_uids != NULL) {
3309 *out_contact_uids = async_context->string_list;
3310 async_context->string_list = NULL;
3317 * e_book_client_get_contacts_uids_sync:
3318 * @client: an #EBookClient
3319 * @sexp: an S-expression representing the query
3320 * @out_contact_uids: (element-type utf8) (out): a #GSList of matched
3321 * contacts UIDs stored as strings
3322 * @cancellable: a #GCancellable; can be %NULL
3323 * @error: (out): a #GError to set an error, if any
3325 * Query @client with @sexp, receiving a list of contacts UIDs which matched.
3326 * If successful, then the @out_contact_uids is set to newly allocated list
3327 * of UID strings, which should be freed with e_client_util_free_string_slist().
3329 * Note: @sexp can be obtained through #EBookQuery, by converting it
3330 * to a string with e_book_query_to_string().
3332 * Returns: %TRUE if successful, %FALSE otherwise.
3337 e_book_client_get_contacts_uids_sync (EBookClient *client,
3339 GSList **out_contact_uids,
3340 GCancellable *cancellable,
3344 gchar **uids = NULL;
3345 GError *local_error = NULL;
3347 g_return_val_if_fail (E_IS_BOOK_CLIENT (client), FALSE);
3348 g_return_val_if_fail (sexp != NULL, FALSE);
3349 g_return_val_if_fail (out_contact_uids != NULL, FALSE);
3351 if (client->priv->direct_backend != NULL) {
3352 GQueue queue = G_QUEUE_INIT;
3353 GSList *list = NULL;
3356 /* Direct backend is not using D-Bus (obviously),
3357 * so no need to strip D-Bus info from the error. */
3358 success = e_book_backend_get_contact_list_uids_sync (
3359 client->priv->direct_backend,
3360 sexp, &queue, cancellable, error);
3363 while (!g_queue_is_empty (&queue)) {
3366 uid = g_queue_pop_head (&queue);
3367 list = g_slist_prepend (list, uid);
3370 *out_contact_uids = g_slist_reverse (list);
3376 utf8_sexp = e_util_utf8_make_valid (sexp);
3378 e_dbus_address_book_call_get_contact_list_uids_sync (
3379 client->priv->dbus_proxy, utf8_sexp,
3380 &uids, cancellable, &local_error);
3385 g_return_val_if_fail (
3386 ((uids != NULL) && (local_error == NULL)) ||
3387 ((uids == NULL) && (local_error != NULL)), FALSE);
3389 /* XXX We should have passed the string array directly
3390 * back to the caller instead of building a linked
3391 * list. This is unnecessary work. */
3396 /* Take ownership of the string array elements. */
3397 for (ii = 0; uids[ii] != NULL; ii++) {
3398 tmp = g_slist_prepend (tmp, uids[ii]);
3402 *out_contact_uids = g_slist_reverse (tmp);
3407 if (local_error != NULL) {
3408 g_dbus_error_strip_remote_error (local_error);
3409 g_propagate_error (error, local_error);
3416 /* Helper for e_book_client_get_view() */
3418 book_client_get_view_in_dbus_thread (GSimpleAsyncResult *simple,
3419 GObject *source_object,
3420 GCancellable *cancellable)
3422 EBookClient *client = E_BOOK_CLIENT (source_object);
3423 AsyncContext *async_context;
3425 gchar *object_path = NULL;
3426 GError *local_error = NULL;
3428 async_context = g_simple_async_result_get_op_res_gpointer (simple);
3430 utf8_sexp = e_util_utf8_make_valid (async_context->sexp);
3432 e_dbus_address_book_call_get_view_sync (
3433 client->priv->dbus_proxy, utf8_sexp,
3434 &object_path, cancellable, &local_error);
3440 ((object_path != NULL) && (local_error == NULL)) ||
3441 ((object_path == NULL) && (local_error != NULL)));
3443 if (object_path != NULL) {
3444 GDBusConnection *connection;
3445 EBookClientView *client_view;
3447 connection = g_dbus_proxy_get_connection (
3448 G_DBUS_PROXY (client->priv->dbus_proxy));
3450 client_view = g_initable_new (
3451 E_TYPE_BOOK_CLIENT_VIEW,
3452 cancellable, &local_error,
3454 "connection", connection,
3455 "object-path", object_path,
3456 "direct-backend", client->priv->direct_backend,
3461 ((client_view != NULL) && (local_error == NULL)) ||
3462 ((client_view == NULL) && (local_error != NULL)));
3464 async_context->client_view = client_view;
3466 g_free (object_path);
3469 if (local_error != NULL) {
3470 g_dbus_error_strip_remote_error (local_error);
3471 g_simple_async_result_take_error (simple, local_error);
3476 * e_book_client_get_view:
3477 * @client: an #EBookClient
3478 * @sexp: an S-expression representing the query
3479 * @cancellable: a #GCancellable; can be %NULL
3480 * @callback: callback to call when a result is ready
3481 * @user_data: user data for the @callback
3483 * Query @client with @sexp, creating an #EBookClientView.
3484 * The call is finished by e_book_client_get_view_finish()
3485 * from the @callback.
3487 * Note: @sexp can be obtained through #EBookQuery, by converting it
3488 * to a string with e_book_query_to_string().
3493 e_book_client_get_view (EBookClient *client,
3495 GCancellable *cancellable,
3496 GAsyncReadyCallback callback,
3499 GSimpleAsyncResult *simple;
3500 AsyncContext *async_context;
3502 g_return_if_fail (E_IS_BOOK_CLIENT (client));
3503 g_return_if_fail (sexp != NULL);
3505 async_context = g_slice_new0 (AsyncContext);
3506 async_context->sexp = g_strdup (sexp);
3508 simple = g_simple_async_result_new (
3509 G_OBJECT (client), callback, user_data,
3510 e_book_client_get_view);
3512 g_simple_async_result_set_check_cancellable (simple, cancellable);
3514 g_simple_async_result_set_op_res_gpointer (
3515 simple, async_context, (GDestroyNotify) async_context_free);
3517 book_client_run_in_dbus_thread (
3518 simple, book_client_get_view_in_dbus_thread,
3519 G_PRIORITY_DEFAULT, cancellable);
3521 g_object_unref (simple);
3525 * e_book_client_get_view_finish:
3526 * @client: an #EBookClient
3527 * @result: a #GAsyncResult
3528 * @out_view: (out): an #EBookClientView
3529 * @error: (out): a #GError to set an error, if any
3531 * Finishes previous call of e_book_client_get_view().
3532 * If successful, then the @out_view is set to newly allocated
3533 * #EBookClientView, which should be freed with g_object_unref().
3535 * Returns: %TRUE if successful, %FALSE otherwise.
3540 e_book_client_get_view_finish (EBookClient *client,
3541 GAsyncResult *result,
3542 EBookClientView **out_view,
3545 GSimpleAsyncResult *simple;
3546 AsyncContext *async_context;
3548 g_return_val_if_fail (
3549 g_simple_async_result_is_valid (
3550 result, G_OBJECT (client),
3551 e_book_client_get_view), FALSE);
3553 simple = G_SIMPLE_ASYNC_RESULT (result);
3554 async_context = g_simple_async_result_get_op_res_gpointer (simple);
3556 if (g_simple_async_result_propagate_error (simple, error))
3559 g_return_val_if_fail (async_context->client_view != NULL, FALSE);
3561 if (out_view != NULL)
3562 *out_view = g_object_ref (async_context->client_view);
3568 * e_book_client_get_view_sync:
3569 * @client: an #EBookClient
3570 * @sexp: an S-expression representing the query
3571 * @out_view: (out) an #EBookClientView
3572 * @cancellable: a #GCancellable; can be %NULL
3573 * @error: (out): a #GError to set an error, if any
3575 * Query @client with @sexp, creating an #EBookClientView.
3576 * If successful, then the @out_view is set to newly allocated
3577 * #EBookClientView, which should be freed with g_object_unref().
3579 * Note: @sexp can be obtained through #EBookQuery, by converting it
3580 * to a string with e_book_query_to_string().
3582 * Returns: %TRUE if successful, %FALSE otherwise.
3587 e_book_client_get_view_sync (EBookClient *client,
3589 EBookClientView **out_view,
3590 GCancellable *cancellable,
3593 EAsyncClosure *closure;
3594 GAsyncResult *result;
3597 g_return_val_if_fail (E_IS_BOOK_CLIENT (client), FALSE);
3598 g_return_val_if_fail (sexp != NULL, FALSE);
3599 g_return_val_if_fail (out_view != NULL, FALSE);
3601 closure = e_async_closure_new ();
3603 e_book_client_get_view (
3604 client, sexp, cancellable,
3605 e_async_closure_callback, closure);
3607 result = e_async_closure_wait (closure);
3609 success = e_book_client_get_view_finish (
3610 client, result, out_view, error);
3612 e_async_closure_free (closure);