Deprecate e_client_util_copy_object_slist().
[platform/upstream/evolution-data-server.git] / libedataserver / e-client.c
1 /*
2  * e-client.c
3  *
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.
8  *
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.
13  *
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/>
16  *
17  *
18  * Copyright (C) 2011 Red Hat, Inc. (www.redhat.com)
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <glib/gi18n-lib.h>
27 #include <gio/gio.h>
28
29 #include <libedataserver/e-data-server-util.h>
30
31 #include "e-gdbus-marshallers.h"
32
33 #include "e-client.h"
34 #include "e-client-private.h"
35
36 #define E_CLIENT_GET_PRIVATE(obj) \
37         (G_TYPE_INSTANCE_GET_PRIVATE \
38         ((obj), E_TYPE_CLIENT, EClientPrivate))
39
40 struct _EClientPrivate {
41         GRecMutex prop_mutex;
42
43         ESource *source;
44         gchar *uri;
45         gboolean online;
46         gboolean readonly;
47         gboolean opened;
48         gboolean capabilities_retrieved;
49         GSList *capabilities;
50
51         GHashTable *backend_property_cache;
52
53         GRecMutex ops_mutex;
54         guint32 last_opid;
55         GHashTable *ops; /* opid to GCancellable */
56 };
57
58 enum {
59         PROP_0,
60         PROP_SOURCE,
61         PROP_CAPABILITIES,
62         PROP_READONLY,
63         PROP_ONLINE,
64         PROP_OPENED
65 };
66
67 enum {
68         OPENED,
69         BACKEND_ERROR,
70         BACKEND_DIED,
71         BACKEND_PROPERTY_CHANGED,
72         LAST_SIGNAL
73 };
74
75 static guint signals[LAST_SIGNAL];
76
77 G_DEFINE_ABSTRACT_TYPE (EClient, e_client, G_TYPE_OBJECT)
78
79 /*
80  * Well-known client backend properties, which are common for each #EClient:
81  * @CLIENT_BACKEND_PROPERTY_OPENED: Is set to "TRUE" or "FALSE" depending
82  *   whether the backend is fully opened.
83  * @CLIENT_BACKEND_PROPERTY_OPENING: Is set to "TRUE" or "FALSE" depending
84  *   whether the backend is processing its opening phase.
85  * @CLIENT_BACKEND_PROPERTY_ONLINE: Is set to "TRUE" or "FALSE" depending
86  *   on the backend's loaded state. See also e_client_is_online().
87  * @CLIENT_BACKEND_PROPERTY_READONLY: Is set to "TRUE" or "FALSE" depending
88  *   on the backend's readonly state. See also e_client_is_readonly().
89  * @CLIENT_BACKEND_PROPERTY_CACHE_DIR: Local folder with cached data used
90  *   by the backend.
91  * @CLIENT_BACKEND_PROPERTY_CAPABILITIES: Retrieves comma-separated list
92  *   of capabilities supported by the backend. Preferred method of retreiving
93  *   and working with capabilities is e_client_get_capabilities() and
94  *   e_client_check_capability().
95  */
96
97 GQuark
98 e_client_error_quark (void)
99 {
100         static GQuark q = 0;
101
102         if (q == 0)
103                 q = g_quark_from_static_string ("e-client-error-quark");
104
105         return q;
106 }
107
108 /**
109  * e_client_error_to_string:
110  *
111  * FIXME: Document me.
112  *
113  * Since: 3.2
114  **/
115 const gchar *
116 e_client_error_to_string (EClientError code)
117 {
118         switch (code) {
119         case E_CLIENT_ERROR_INVALID_ARG:
120                 return _("Invalid argument");
121         case E_CLIENT_ERROR_BUSY:
122                 return _("Backend is busy");
123         case E_CLIENT_ERROR_SOURCE_NOT_LOADED:
124                 return _("Source not loaded");
125         case E_CLIENT_ERROR_SOURCE_ALREADY_LOADED:
126                 return _("Source already loaded");
127         case E_CLIENT_ERROR_AUTHENTICATION_FAILED:
128                 return _("Authentication failed");
129         case E_CLIENT_ERROR_AUTHENTICATION_REQUIRED:
130                 return _("Authentication required");
131         case E_CLIENT_ERROR_REPOSITORY_OFFLINE:
132                 return _("Repository offline");
133         case E_CLIENT_ERROR_OFFLINE_UNAVAILABLE:
134                 /* Translators: This means that the EClient does not support offline mode, or
135                  * it's not set to by a user, thus it is unavailable while user is not connected. */
136                 return _("Offline unavailable");
137         case E_CLIENT_ERROR_PERMISSION_DENIED:
138                 return _("Permission denied");
139         case E_CLIENT_ERROR_CANCELLED:
140                 return _("Cancelled");
141         case E_CLIENT_ERROR_COULD_NOT_CANCEL:
142                 return _("Could not cancel");
143         case E_CLIENT_ERROR_NOT_SUPPORTED:
144                 return _("Not supported");
145         case E_CLIENT_ERROR_UNSUPPORTED_AUTHENTICATION_METHOD:
146                 return _("Unsupported authentication method");
147         case E_CLIENT_ERROR_TLS_NOT_AVAILABLE:
148                 return _("TLS not available");
149         case E_CLIENT_ERROR_SEARCH_SIZE_LIMIT_EXCEEDED:
150                 return _("Search size limit exceeded");
151         case E_CLIENT_ERROR_SEARCH_TIME_LIMIT_EXCEEDED:
152                 return _("Search time limit exceeded");
153         case E_CLIENT_ERROR_INVALID_QUERY:
154                 return _("Invalid query");
155         case E_CLIENT_ERROR_QUERY_REFUSED:
156                 return _("Query refused");
157         case E_CLIENT_ERROR_DBUS_ERROR:
158                 return _("D-Bus error");
159         case E_CLIENT_ERROR_OTHER_ERROR:
160                 return _("Other error");
161         case E_CLIENT_ERROR_NOT_OPENED:
162                 return _("Backend is not opened yet");
163         }
164
165         return _("Unknown error");
166 }
167
168 /**
169  * e_client_error_create:
170  * @code: an #EClientError code to create
171  * @custom_msg: custom message to use for the error; can be %NULL
172  *
173  * Returns: a new #GError containing an E_CLIENT_ERROR of the given
174  * @code. If the @custom_msg is NULL, then the error message is
175  * the one returned from e_client_error_to_string() for the @code,
176  * otherwise the given message is used.
177  *
178  * Returned pointer should be freed with g_error_free().
179  *
180  * Since: 3.2
181  **/
182 GError *
183 e_client_error_create (EClientError code,
184                        const gchar *custom_msg)
185 {
186         return g_error_new_literal (E_CLIENT_ERROR, code, custom_msg ? custom_msg : e_client_error_to_string (code));
187 }
188
189 static void client_set_source (EClient *client, ESource *source);
190
191 static void
192 e_client_init (EClient *client)
193 {
194         client->priv = E_CLIENT_GET_PRIVATE (client);
195
196         client->priv->readonly = TRUE;
197
198         g_rec_mutex_init (&client->priv->prop_mutex);
199         client->priv->backend_property_cache = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
200
201         g_rec_mutex_init (&client->priv->ops_mutex);
202         client->priv->last_opid = 0;
203         client->priv->ops = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_object_unref);
204 }
205
206 static void
207 client_dispose (GObject *object)
208 {
209         EClient *client;
210
211         client = E_CLIENT (object);
212
213         e_client_cancel_all (client);
214
215         /* Chain up to parent's dispose() method. */
216         G_OBJECT_CLASS (e_client_parent_class)->dispose (object);
217 }
218
219 static void
220 client_finalize (GObject *object)
221 {
222         EClient *client;
223         EClientPrivate *priv;
224
225         client = E_CLIENT (object);
226
227         priv = client->priv;
228
229         g_rec_mutex_lock (&priv->prop_mutex);
230
231         if (priv->source) {
232                 g_object_unref (priv->source);
233                 priv->source = NULL;
234         }
235
236         if (priv->uri) {
237                 g_free (priv->uri);
238                 priv->uri = NULL;
239         }
240
241         if (priv->capabilities) {
242                 g_slist_foreach (priv->capabilities, (GFunc) g_free, NULL);
243                 g_slist_free (priv->capabilities);
244                 priv->capabilities = NULL;
245         }
246
247         if (priv->backend_property_cache) {
248                 g_hash_table_destroy (priv->backend_property_cache);
249                 priv->backend_property_cache = NULL;
250         }
251
252         if (priv->ops) {
253                 g_hash_table_destroy (priv->ops);
254                 priv->ops = NULL;
255         }
256
257         g_rec_mutex_unlock (&priv->prop_mutex);
258         g_rec_mutex_clear (&priv->prop_mutex);
259         g_rec_mutex_clear (&priv->ops_mutex);
260
261         /* Chain up to parent's finalize() method. */
262         G_OBJECT_CLASS (e_client_parent_class)->finalize (object);
263 }
264
265 static void
266 client_set_property (GObject *object,
267                      guint property_id,
268                      const GValue *value,
269                      GParamSpec *pspec)
270 {
271         switch (property_id) {
272                 case PROP_SOURCE:
273                         client_set_source (E_CLIENT (object), g_value_get_object (value));
274                         return;
275
276                 case PROP_ONLINE:
277                         e_client_set_online (E_CLIENT (object), g_value_get_boolean (value));
278                         return;
279         }
280
281         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
282 }
283
284 static void
285 client_get_property (GObject *object,
286                      guint property_id,
287                      GValue *value,
288                      GParamSpec *pspec)
289 {
290         switch (property_id) {
291                 case PROP_SOURCE:
292                         g_value_set_object (value, e_client_get_source (E_CLIENT (object)));
293                         return;
294
295                 case PROP_CAPABILITIES:
296                         g_value_set_pointer (value, (gpointer) e_client_get_capabilities (E_CLIENT (object)));
297                         return;
298
299                 case PROP_READONLY:
300                         g_value_set_boolean (value, e_client_is_readonly (E_CLIENT (object)));
301                         return;
302
303                 case PROP_ONLINE:
304                         g_value_set_boolean (value, e_client_is_online (E_CLIENT (object)));
305                         return;
306
307                 case PROP_OPENED:
308                         g_value_set_boolean (value, e_client_is_opened (E_CLIENT (object)));
309                         return;
310         }
311
312         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
313 }
314
315 static void
316 client_remove_thread (GSimpleAsyncResult *simple,
317                       GObject *object,
318                       GCancellable *cancellable)
319 {
320         GError *error = NULL;
321
322         e_client_remove_sync (E_CLIENT (object), cancellable, &error);
323
324         if (error != NULL)
325                 g_simple_async_result_take_error (simple, error);
326 }
327
328 static void
329 client_remove (EClient *client,
330                GCancellable *cancellable,
331                GAsyncReadyCallback callback,
332                gpointer user_data)
333 {
334         GSimpleAsyncResult *simple;
335
336         simple = g_simple_async_result_new (
337                 G_OBJECT (client), callback, user_data, client_remove);
338
339         g_simple_async_result_set_check_cancellable (simple, cancellable);
340
341         g_simple_async_result_run_in_thread (
342                 simple, client_remove_thread,
343                 G_PRIORITY_DEFAULT, cancellable);
344
345         g_object_unref (simple);
346 }
347
348 static gboolean
349 client_remove_finish (EClient *client,
350                       GAsyncResult *result,
351                       GError **error)
352 {
353         GSimpleAsyncResult *simple;
354
355         g_return_val_if_fail (
356                 g_simple_async_result_is_valid (
357                 result, G_OBJECT (client), client_remove), FALSE);
358
359         simple = G_SIMPLE_ASYNC_RESULT (result);
360
361         /* Assume success unless a GError is set. */
362         return !g_simple_async_result_propagate_error (simple, error);
363 }
364
365 static gboolean
366 client_remove_sync (EClient *client,
367                     GCancellable *cancellable,
368                     GError **error)
369 {
370         ESource *source;
371
372         source = e_client_get_source (client);
373
374         return e_source_remove_sync (source, cancellable, error);
375 }
376
377 static void
378 e_client_class_init (EClientClass *class)
379 {
380         GObjectClass *object_class;
381
382         g_type_class_add_private (class, sizeof (EClientPrivate));
383
384         object_class = G_OBJECT_CLASS (class);
385         object_class->set_property = client_set_property;
386         object_class->get_property = client_get_property;
387         object_class->dispose = client_dispose;
388         object_class->finalize = client_finalize;
389
390         class->remove = client_remove;
391         class->remove_finish = client_remove_finish;
392         class->remove_sync = client_remove_sync;
393
394         g_object_class_install_property (
395                 object_class,
396                 PROP_SOURCE,
397                 g_param_spec_object (
398                         "source",
399                         NULL,
400                         NULL,
401                         E_TYPE_SOURCE,
402                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
403
404         g_object_class_install_property (
405                 object_class,
406                 PROP_CAPABILITIES,
407                 g_param_spec_pointer (
408                         "capabilities",
409                         NULL,
410                         NULL,
411                         G_PARAM_READABLE));
412
413         g_object_class_install_property (
414                 object_class,
415                 PROP_READONLY,
416                 g_param_spec_boolean (
417                         "readonly",
418                         NULL,
419                         NULL,
420                         FALSE,
421                         G_PARAM_READABLE));
422
423         g_object_class_install_property (
424                 object_class,
425                 PROP_ONLINE,
426                 g_param_spec_boolean (
427                         "online",
428                         NULL,
429                         NULL,
430                         FALSE,
431                         G_PARAM_READWRITE));
432
433         g_object_class_install_property (
434                 object_class,
435                 PROP_OPENED,
436                 g_param_spec_boolean (
437                         "opened",
438                         NULL,
439                         NULL,
440                         FALSE,
441                         G_PARAM_READABLE));
442
443         signals[OPENED] = g_signal_new (
444                 "opened",
445                 G_OBJECT_CLASS_TYPE (class),
446                 G_SIGNAL_RUN_LAST,
447                 G_STRUCT_OFFSET (EClientClass, opened),
448                 NULL, NULL,
449                 g_cclosure_marshal_VOID__BOXED,
450                 G_TYPE_NONE, 1,
451                 G_TYPE_ERROR);
452
453         signals[BACKEND_ERROR] = g_signal_new (
454                 "backend-error",
455                 G_OBJECT_CLASS_TYPE (class),
456                 G_SIGNAL_RUN_FIRST,
457                 G_STRUCT_OFFSET (EClientClass, backend_error),
458                 NULL, NULL,
459                 g_cclosure_marshal_VOID__STRING,
460                 G_TYPE_NONE, 1,
461                 G_TYPE_STRING);
462
463         signals[BACKEND_DIED] = g_signal_new (
464                 "backend-died",
465                 G_OBJECT_CLASS_TYPE (class),
466                 G_SIGNAL_RUN_LAST,
467                 G_STRUCT_OFFSET (EClientClass, backend_died),
468                 NULL, NULL,
469                 g_cclosure_marshal_VOID__VOID,
470                 G_TYPE_NONE, 0);
471
472         signals[BACKEND_PROPERTY_CHANGED] = g_signal_new (
473                 "backend-property-changed",
474                 G_OBJECT_CLASS_TYPE (class),
475                 G_SIGNAL_RUN_LAST,
476                 G_STRUCT_OFFSET (EClientClass, backend_property_changed),
477                 NULL, NULL,
478                 e_gdbus_marshallers_VOID__STRING_STRING,
479                 G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_STRING);
480 }
481
482 static void
483 client_set_source (EClient *client,
484                    ESource *source)
485 {
486         g_return_if_fail (E_IS_CLIENT (client));
487         g_return_if_fail (E_IS_SOURCE (source));
488
489         g_object_ref (source);
490
491         if (client->priv->source)
492                 g_object_unref (client->priv->source);
493
494         client->priv->source = source;
495 }
496
497 /**
498  * e_client_get_source:
499  * @client: an #EClient
500  *
501  * Get the #ESource that this client has assigned.
502  *
503  * Returns: (transfer none): The source.
504  *
505  * Since: 3.2
506  **/
507 ESource *
508 e_client_get_source (EClient *client)
509 {
510         g_return_val_if_fail (E_IS_CLIENT (client), NULL);
511
512         return client->priv->source;
513 }
514
515 static void
516 client_ensure_capabilities (EClient *client)
517 {
518         gchar *capabilities;
519
520         g_return_if_fail (E_IS_CLIENT (client));
521
522         if (client->priv->capabilities_retrieved || client->priv->capabilities)
523                 return;
524
525         g_rec_mutex_lock (&client->priv->prop_mutex);
526
527         capabilities = NULL;
528         e_client_retrieve_capabilities_sync (client, &capabilities, NULL, NULL);
529         /* e_client_set_capabilities is called inside the previous function */
530         g_free (capabilities);
531
532         client->priv->capabilities_retrieved = TRUE;
533
534         g_rec_mutex_unlock (&client->priv->prop_mutex);
535 }
536
537 /**
538  * e_client_get_capabilities:
539  * @client: an #EClient
540  *
541  * Get list of strings with capabilities advertised by a backend.
542  * This list, together with inner strings, is owned by the @client.
543  * To check for individual capabilities use e_client_check_capability().
544  *
545  * Returns: (element-type utf8) (transfer none): #GSList of const strings
546  *          of capabilities
547  *
548  * Since: 3.2
549  **/
550 const GSList *
551 e_client_get_capabilities (EClient *client)
552 {
553         g_return_val_if_fail (E_IS_CLIENT (client), NULL);
554
555         client_ensure_capabilities (client);
556
557         return client->priv->capabilities;
558 }
559
560 /**
561  * e_client_check_capability:
562  * @client: an #EClient
563  * @capability: a capability
564  *
565  * Check if backend supports particular capability.
566  * To get all capabilities use e_client_get_capabilities().
567  *
568  * Returns: #GSList of const strings of capabilities
569  *
570  * Since: 3.2
571  **/
572 gboolean
573 e_client_check_capability (EClient *client,
574                            const gchar *capability)
575 {
576         GSList *iter;
577
578         g_return_val_if_fail (E_IS_CLIENT (client), FALSE);
579         g_return_val_if_fail (capability, FALSE);
580
581         g_rec_mutex_lock (&client->priv->prop_mutex);
582
583         client_ensure_capabilities (client);
584
585         for (iter = client->priv->capabilities; iter; iter = g_slist_next (iter)) {
586                 const gchar *cap = iter->data;
587
588                 if (cap && g_ascii_strcasecmp (cap, capability) == 0) {
589                         g_rec_mutex_unlock (&client->priv->prop_mutex);
590                         return TRUE;
591                 }
592         }
593
594         g_rec_mutex_unlock (&client->priv->prop_mutex);
595
596         return FALSE;
597 }
598
599 /**
600  * e_client_check_refresh_supported:
601  * @client: A client.
602  *
603  * Checks whether a client supports explicit refreshing
604  * (see e_client_refresh()).
605  *
606  * Returns: TRUE if the client supports refreshing, FALSE otherwise.
607  *
608  * Since: 3.2
609  **/
610 gboolean
611 e_client_check_refresh_supported (EClient *client)
612 {
613         g_return_val_if_fail (E_IS_CLIENT (client), FALSE);
614
615         return e_client_check_capability (client, "refresh-supported");
616 }
617
618 /* capabilities - comma-separated list of capabilities; can be NULL to unset */
619 void
620 e_client_set_capabilities (EClient *client,
621                            const gchar *capabilities)
622 {
623         g_return_if_fail (E_IS_CLIENT (client));
624
625         g_rec_mutex_lock (&client->priv->prop_mutex);
626
627         if (!capabilities)
628                 client->priv->capabilities_retrieved = FALSE;
629
630         g_slist_foreach (client->priv->capabilities, (GFunc) g_free, NULL);
631         g_slist_free (client->priv->capabilities);
632         client->priv->capabilities = e_client_util_parse_comma_strings (capabilities);
633
634         g_rec_mutex_unlock (&client->priv->prop_mutex);
635
636         g_object_notify (G_OBJECT (client), "capabilities");
637 }
638
639 /**
640  * e_client_is_readonly:
641  * @client: an #EClient
642  *
643  * Check if this @client is read-only.
644  *
645  * Returns: %TRUE if this @client is read-only, otherwise %FALSE.
646  *
647  * Since: 3.2
648  **/
649 gboolean
650 e_client_is_readonly (EClient *client)
651 {
652         g_return_val_if_fail (E_IS_CLIENT (client), TRUE);
653
654         return client->priv->readonly;
655 }
656
657 void
658 e_client_set_readonly (EClient *client,
659                        gboolean readonly)
660 {
661         g_return_if_fail (E_IS_CLIENT (client));
662
663         g_rec_mutex_lock (&client->priv->prop_mutex);
664         if (client->priv->readonly == readonly) {
665                 g_rec_mutex_unlock (&client->priv->prop_mutex);
666                 return;
667         }
668
669         client->priv->readonly = readonly;
670
671         g_rec_mutex_unlock (&client->priv->prop_mutex);
672
673         g_object_notify (G_OBJECT (client), "readonly");
674 }
675
676 /**
677  * e_client_is_online:
678  * @client: an #EClient
679  *
680  * Check if this @client is connected.
681  *
682  * Returns: %TRUE if this @client is connected, otherwise %FALSE.
683  *
684  * Since: 3.2
685  **/
686 gboolean
687 e_client_is_online (EClient *client)
688 {
689         g_return_val_if_fail (E_IS_CLIENT (client), FALSE);
690
691         return client->priv->online;
692 }
693
694 void
695 e_client_set_online (EClient *client,
696                      gboolean is_online)
697 {
698         g_return_if_fail (E_IS_CLIENT (client));
699
700         /* newly connected/disconnected => make sure capabilities will be correct */
701         e_client_set_capabilities (client, NULL);
702
703         g_rec_mutex_lock (&client->priv->prop_mutex);
704         if (client->priv->online == is_online) {
705                 g_rec_mutex_unlock (&client->priv->prop_mutex);
706                 return;
707         }
708
709         client->priv->online = is_online;
710
711         g_rec_mutex_unlock (&client->priv->prop_mutex);
712
713         g_object_notify (G_OBJECT (client), "online");
714 }
715
716 /**
717  * e_client_is_opened:
718  * @client: an #EClient
719  *
720  * Check if this @client is fully opened. This includes
721  * everything from e_client_open() call up to the authentication,
722  * if required by a backend. Client cannot do any other operation
723  * during the opening phase except of authenticate or cancel it.
724  * Every other operation results in an %E_CLIENT_ERROR_BUSY error.
725  *
726  * Returns: %TRUE if this @client is fully opened, otherwise %FALSE.
727  *
728  * Since: 3.2.
729  **/
730 gboolean
731 e_client_is_opened (EClient *client)
732 {
733         g_return_val_if_fail (E_IS_CLIENT (client), FALSE);
734
735         return client->priv->opened;
736 }
737
738 /*
739  * client_cancel_op:
740  * @client: an #EClient
741  * @opid: asynchronous operation ID
742  *
743  * Cancels particular asynchronous operation. The @opid is returned from
744  * an e_client_register_op(). The function does nothing if the asynchronous
745  * operation doesn't exist any more.
746  *
747  * Since: 3.2
748  */
749 static void
750 client_cancel_op (EClient *client,
751                   guint32 opid)
752 {
753         GCancellable *cancellable;
754
755         g_return_if_fail (E_IS_CLIENT (client));
756         g_return_if_fail (client->priv->ops != NULL);
757
758         g_rec_mutex_lock (&client->priv->ops_mutex);
759
760         cancellable = g_hash_table_lookup (client->priv->ops, GINT_TO_POINTER (opid));
761         if (cancellable)
762                 g_cancellable_cancel (cancellable);
763
764         g_rec_mutex_unlock (&client->priv->ops_mutex);
765 }
766
767 static void
768 gather_opids_cb (gpointer opid,
769                  gpointer cancellable,
770                  gpointer ids_list)
771 {
772         GSList **ids = ids_list;
773
774         g_return_if_fail (ids_list != NULL);
775
776         *ids = g_slist_prepend (*ids, opid);
777 }
778
779 static void
780 cancel_op_cb (gpointer opid,
781               gpointer client)
782 {
783         client_cancel_op (client, GPOINTER_TO_INT (opid));
784 }
785
786 /**
787  * e_client_cancel_all:
788  * @client: an #EClient
789  *
790  * Cancels all pending operations started on @client.
791  *
792  * Since: 3.2
793  **/
794 void
795 e_client_cancel_all (EClient *client)
796 {
797         GSList *opids = NULL;
798
799         g_return_if_fail (E_IS_CLIENT (client));
800         g_return_if_fail (client->priv->ops != NULL);
801
802         g_rec_mutex_lock (&client->priv->ops_mutex);
803
804         g_hash_table_foreach (client->priv->ops, gather_opids_cb, &opids);
805
806         g_slist_foreach (opids, cancel_op_cb, client);
807         g_slist_free (opids);
808
809         g_rec_mutex_unlock (&client->priv->ops_mutex);
810 }
811
812 guint32
813 e_client_register_op (EClient *client,
814                       GCancellable *cancellable)
815 {
816         guint32 opid;
817
818         g_return_val_if_fail (E_IS_CLIENT (client), 0);
819         g_return_val_if_fail (client->priv->ops != NULL, 0);
820         g_return_val_if_fail (cancellable != NULL, 0);
821
822         g_rec_mutex_lock (&client->priv->ops_mutex);
823
824         client->priv->last_opid++;
825         if (!client->priv->last_opid)
826                 client->priv->last_opid++;
827
828         while (g_hash_table_lookup (client->priv->ops, GINT_TO_POINTER (client->priv->last_opid)))
829                 client->priv->last_opid++;
830
831         g_return_val_if_fail (client->priv->last_opid != 0, 0);
832
833         opid = client->priv->last_opid;
834         g_hash_table_insert (client->priv->ops, GINT_TO_POINTER (opid), g_object_ref (cancellable));
835
836         g_rec_mutex_unlock (&client->priv->ops_mutex);
837
838         return opid;
839 }
840
841 void
842 e_client_unregister_op (EClient *client,
843                         guint32 opid)
844 {
845         g_return_if_fail (E_IS_CLIENT (client));
846         g_return_if_fail (client->priv->ops != NULL);
847
848         g_rec_mutex_lock (&client->priv->ops_mutex);
849         g_hash_table_remove (client->priv->ops, GINT_TO_POINTER (opid));
850         g_rec_mutex_unlock (&client->priv->ops_mutex);
851 }
852
853 void
854 e_client_emit_opened (EClient *client,
855                       const GError *dbus_error)
856 {
857         GError *local_error = NULL;
858
859         g_return_if_fail (E_IS_CLIENT (client));
860
861         client->priv->opened = dbus_error == NULL;
862
863         if (dbus_error) {
864                 local_error = g_error_copy (dbus_error);
865                 e_client_unwrap_dbus_error (client, local_error, &local_error);
866         }
867
868         g_object_notify (G_OBJECT (client), "opened");
869         g_signal_emit (client, signals[OPENED], 0, local_error);
870
871         if (local_error)
872                 g_error_free (local_error);
873 }
874
875 void
876 e_client_emit_backend_error (EClient *client,
877                              const gchar *error_msg)
878 {
879         g_return_if_fail (E_IS_CLIENT (client));
880         g_return_if_fail (error_msg != NULL);
881
882         g_signal_emit (client, signals[BACKEND_ERROR], 0, error_msg);
883 }
884
885 void
886 e_client_emit_backend_died (EClient *client)
887 {
888         g_return_if_fail (E_IS_CLIENT (client));
889
890         g_signal_emit (client, signals[BACKEND_DIED], 0);
891 }
892
893 void
894 e_client_emit_backend_property_changed (EClient *client,
895                                         const gchar *prop_name,
896                                         const gchar *prop_value)
897 {
898         g_return_if_fail (E_IS_CLIENT (client));
899         g_return_if_fail (prop_name != NULL);
900         g_return_if_fail (*prop_name);
901         g_return_if_fail (prop_value != NULL);
902
903         e_client_update_backend_property_cache (client, prop_name, prop_value);
904
905         g_signal_emit (client, signals[BACKEND_PROPERTY_CHANGED], 0, prop_name, prop_value);
906 }
907
908 void
909 e_client_update_backend_property_cache (EClient *client,
910                                         const gchar *prop_name,
911                                         const gchar *prop_value)
912 {
913         g_return_if_fail (E_IS_CLIENT (client));
914         g_return_if_fail (prop_name != NULL);
915         g_return_if_fail (*prop_name);
916         g_return_if_fail (prop_value != NULL);
917
918         g_rec_mutex_lock (&client->priv->prop_mutex);
919
920         if (client->priv->backend_property_cache)
921                 g_hash_table_insert (client->priv->backend_property_cache, g_strdup (prop_name), g_strdup (prop_value));
922
923         g_rec_mutex_unlock (&client->priv->prop_mutex);
924 }
925
926 gchar *
927 e_client_get_backend_property_from_cache (EClient *client,
928                                           const gchar *prop_name)
929 {
930         gchar *prop_value = NULL;
931
932         g_return_val_if_fail (E_IS_CLIENT (client), NULL);
933         g_return_val_if_fail (prop_name != NULL, NULL);
934         g_return_val_if_fail (*prop_name, NULL);
935
936         g_rec_mutex_lock (&client->priv->prop_mutex);
937
938         if (client->priv->backend_property_cache)
939                 prop_value = g_strdup (g_hash_table_lookup (client->priv->backend_property_cache, prop_name));
940
941         g_rec_mutex_unlock (&client->priv->prop_mutex);
942
943         return prop_value;
944 }
945
946 /**
947  * e_client_retrieve_capabilities:
948  * @client: an #EClient
949  * @cancellable: a #GCancellable; can be %NULL
950  * @callback: callback to call when a result is ready
951  * @user_data: user data for the @callback
952  *
953  * Initiates retrieval of capabilities on the @client. This is usually
954  * required only once, after the @client is opened. The returned value
955  * is cached and any subsequent call of e_client_get_capabilities() and
956  * e_client_check_capability() is using the cached value.
957  * The call is finished by e_client_retrieve_capabilities_finish()
958  * from the @callback.
959  *
960  * Since: 3.2
961  **/
962 void
963 e_client_retrieve_capabilities (EClient *client,
964                                 GCancellable *cancellable,
965                                 GAsyncReadyCallback callback,
966                                 gpointer user_data)
967 {
968         EClientClass *class;
969
970         g_return_if_fail (E_IS_CLIENT (client));
971         g_return_if_fail (callback != NULL);
972
973         class = E_CLIENT_GET_CLASS (client);
974         g_return_if_fail (class != NULL);
975         g_return_if_fail (class->retrieve_capabilities != NULL);
976
977         class->retrieve_capabilities (client, cancellable, callback, user_data);
978 }
979
980 /**
981  * e_client_retrieve_capabilities_finish:
982  * @client: an #EClient
983  * @result: a #GAsyncResult
984  * @capabilities: (out): Comma-separated list of capabilities of the @client
985  * @error: (out): a #GError to set an error, if any
986  *
987  * Finishes previous call of e_client_retrieve_capabilities().
988  * Returned value of @capabilities should be freed with g_free(),
989  * when no longer needed.
990  *
991  * Returns: %TRUE if successful, %FALSE otherwise.
992  *
993  * Since: 3.2
994  **/
995 gboolean
996 e_client_retrieve_capabilities_finish (EClient *client,
997                                        GAsyncResult *result,
998                                        gchar **capabilities,
999                                        GError **error)
1000 {
1001         EClientClass *class;
1002         gboolean res;
1003
1004         g_return_val_if_fail (E_IS_CLIENT (client), FALSE);
1005         g_return_val_if_fail (capabilities != NULL, FALSE);
1006
1007         class = E_CLIENT_GET_CLASS (client);
1008         g_return_val_if_fail (class != NULL, FALSE);
1009         g_return_val_if_fail (class->retrieve_capabilities_finish != NULL, FALSE);
1010
1011         *capabilities = NULL;
1012         res = class->retrieve_capabilities_finish (client, result, capabilities, error);
1013
1014         e_client_set_capabilities (client, res ? *capabilities : NULL);
1015
1016         if (error && *error)
1017                 e_client_unwrap_dbus_error (client, *error, error);
1018
1019         return res;
1020 }
1021
1022 /**
1023  * e_client_retrieve_capabilities_sync:
1024  * @client: an #EClient
1025  * @capabilities: (out): Comma-separated list of capabilities of the @client
1026  * @cancellable: a #GCancellable; can be %NULL
1027  * @error: (out): a #GError to set an error, if any
1028  *
1029  * Initiates retrieval of capabilities on the @client. This is usually
1030  * required only once, after the @client is opened. The returned value
1031  * is cached and any subsequent call of e_client_get_capabilities() and
1032  * e_client_check_capability() is using the cached value. Returned value
1033  * of @capabilities should be freed with g_free(), when no longer needed.
1034  *
1035  * Returns: %TRUE if successful, %FALSE otherwise.
1036  *
1037  * Since: 3.2
1038  **/
1039 gboolean
1040 e_client_retrieve_capabilities_sync (EClient *client,
1041                                      gchar **capabilities,
1042                                      GCancellable *cancellable,
1043                                      GError **error)
1044 {
1045         EClientClass *class;
1046         gboolean res = FALSE;
1047
1048         g_return_val_if_fail (E_IS_CLIENT (client), FALSE);
1049         g_return_val_if_fail (capabilities != NULL, FALSE);
1050
1051         class = E_CLIENT_GET_CLASS (client);
1052         g_return_val_if_fail (class != NULL, FALSE);
1053         g_return_val_if_fail (class->retrieve_capabilities_sync != NULL, FALSE);
1054
1055         *capabilities = NULL;
1056         res = class->retrieve_capabilities_sync (client, capabilities, cancellable, error);
1057
1058         e_client_set_capabilities (client, res ? *capabilities : NULL);
1059
1060         if (error && *error)
1061                 e_client_unwrap_dbus_error (client, *error, error);
1062
1063         return res;
1064 }
1065
1066 /**
1067  * e_client_get_backend_property:
1068  * @client: an #EClient
1069  * @prop_name: property name, whose value to retrieve; cannot be %NULL
1070  * @cancellable: a #GCancellable; can be %NULL
1071  * @callback: callback to call when a result is ready
1072  * @user_data: user data for the @callback
1073  *
1074  * Queries @client's backend for a property of name @prop_name.
1075  * The call is finished by e_client_get_backend_property_finish()
1076  * from the @callback.
1077  *
1078  * Since: 3.2
1079  **/
1080 void
1081 e_client_get_backend_property (EClient *client,
1082                                const gchar *prop_name,
1083                                GCancellable *cancellable,
1084                                GAsyncReadyCallback callback,
1085                                gpointer user_data)
1086 {
1087         EClientClass *class;
1088
1089         g_return_if_fail (callback != NULL);
1090         g_return_if_fail (E_IS_CLIENT (client));
1091         g_return_if_fail (prop_name != NULL);
1092
1093         class = E_CLIENT_GET_CLASS (client);
1094         g_return_if_fail (class != NULL);
1095         g_return_if_fail (class->get_backend_property != NULL);
1096
1097         class->get_backend_property (client, prop_name, cancellable, callback, user_data);
1098 }
1099
1100 /**
1101  * e_client_get_backend_property_finish:
1102  * @client: an #EClient
1103  * @result: a #GAsyncResult
1104  * @prop_value: (out): Retrieved backend property value; cannot be %NULL
1105  * @error: (out): a #GError to set an error, if any
1106  *
1107  * Finishes previous call of e_client_get_backend_property().
1108  *
1109  * Returns: %TRUE if successful, %FALSE otherwise.
1110  *
1111  * Since: 3.2
1112  **/
1113 gboolean
1114 e_client_get_backend_property_finish (EClient *client,
1115                                       GAsyncResult *result,
1116                                       gchar **prop_value,
1117                                       GError **error)
1118 {
1119         EClientClass *class;
1120         gboolean res;
1121
1122         g_return_val_if_fail (E_IS_CLIENT (client), FALSE);
1123         g_return_val_if_fail (prop_value != NULL, FALSE);
1124
1125         class = E_CLIENT_GET_CLASS (client);
1126         g_return_val_if_fail (class != NULL, FALSE);
1127         g_return_val_if_fail (class->get_backend_property_finish != NULL, FALSE);
1128
1129         res = class->get_backend_property_finish (client, result, prop_value, error);
1130
1131         if (error && *error)
1132                 e_client_unwrap_dbus_error (client, *error, error);
1133
1134         return res;
1135 }
1136
1137 /**
1138  * e_client_get_backend_property_sync:
1139  * @client: an #EClient
1140  * @prop_name: property name, whose value to retrieve; cannot be %NULL
1141  * @prop_value: (out): Retrieved backend property value; cannot be %NULL
1142  * @cancellable: a #GCancellable; can be %NULL
1143  * @error: (out): a #GError to set an error, if any
1144  *
1145  * Queries @client's backend for a property of name @prop_name.
1146  *
1147  * Returns: %TRUE if successful, %FALSE otherwise.
1148  *
1149  * Since: 3.2
1150  **/
1151 gboolean
1152 e_client_get_backend_property_sync (EClient *client,
1153                                     const gchar *prop_name,
1154                                     gchar **prop_value,
1155                                     GCancellable *cancellable,
1156                                     GError **error)
1157 {
1158         EClientClass *class;
1159         gboolean res;
1160
1161         g_return_val_if_fail (E_IS_CLIENT (client), FALSE);
1162         g_return_val_if_fail (prop_name != NULL, FALSE);
1163         g_return_val_if_fail (prop_value != NULL, FALSE);
1164
1165         class = E_CLIENT_GET_CLASS (client);
1166         g_return_val_if_fail (class != NULL, FALSE);
1167         g_return_val_if_fail (class->get_backend_property_sync != NULL, FALSE);
1168
1169         res = class->get_backend_property_sync (client, prop_name, prop_value, cancellable, error);
1170
1171         if (error && *error)
1172                 e_client_unwrap_dbus_error (client, *error, error);
1173
1174         return res;
1175 }
1176
1177 /**
1178  * e_client_set_backend_property:
1179  * @client: an #EClient
1180  * @prop_name: property name, whose value to change; cannot be %NULL
1181  * @prop_value: property value, to set; cannot be %NULL
1182  * @cancellable: a #GCancellable; can be %NULL
1183  * @callback: callback to call when a result is ready
1184  * @user_data: user data for the @callback
1185  *
1186  * Sets @client's backend property of name @prop_name
1187  * to value @prop_value. The call is finished
1188  * by e_client_set_backend_property_finish() from the @callback.
1189  *
1190  * Since: 3.2
1191  **/
1192 void
1193 e_client_set_backend_property (EClient *client,
1194                                const gchar *prop_name,
1195                                const gchar *prop_value,
1196                                GCancellable *cancellable,
1197                                GAsyncReadyCallback callback,
1198                                gpointer user_data)
1199 {
1200         EClientClass *class;
1201
1202         g_return_if_fail (callback != NULL);
1203         g_return_if_fail (E_IS_CLIENT (client));
1204         g_return_if_fail (prop_name != NULL);
1205         g_return_if_fail (prop_value != NULL);
1206
1207         class = E_CLIENT_GET_CLASS (client);
1208         g_return_if_fail (class != NULL);
1209         g_return_if_fail (class->set_backend_property != NULL);
1210
1211         class->set_backend_property (client, prop_name, prop_value, cancellable, callback, user_data);
1212 }
1213
1214 /**
1215  * e_client_set_backend_property_finish:
1216  * @client: an #EClient
1217  * @result: a #GAsyncResult
1218  * @error: (out): a #GError to set an error, if any
1219  *
1220  * Finishes previous call of e_client_set_backend_property().
1221  *
1222  * Returns: %TRUE if successful, %FALSE otherwise.
1223  *
1224  * Since: 3.2
1225  **/
1226 gboolean
1227 e_client_set_backend_property_finish (EClient *client,
1228                                       GAsyncResult *result,
1229                                       GError **error)
1230 {
1231         EClientClass *class;
1232         gboolean res;
1233
1234         g_return_val_if_fail (E_IS_CLIENT (client), FALSE);
1235
1236         class = E_CLIENT_GET_CLASS (client);
1237         g_return_val_if_fail (class != NULL, FALSE);
1238         g_return_val_if_fail (class->set_backend_property_finish != NULL, FALSE);
1239
1240         res = class->set_backend_property_finish (client, result, error);
1241
1242         if (error && *error)
1243                 e_client_unwrap_dbus_error (client, *error, error);
1244
1245         return res;
1246 }
1247
1248 /**
1249  * e_client_set_backend_property_sync:
1250  * @client: an #EClient
1251  * @prop_name: property name, whose value to change; cannot be %NULL
1252  * @prop_value: property value, to set; cannot be %NULL
1253  * @cancellable: a #GCancellable; can be %NULL
1254  * @error: (out): a #GError to set an error, if any
1255  *
1256  * Sets @client's backend property of name @prop_name
1257  * to value @prop_value.
1258  *
1259  * Returns: %TRUE if successful, %FALSE otherwise.
1260  *
1261  * Since: 3.2
1262  **/
1263 gboolean
1264 e_client_set_backend_property_sync (EClient *client,
1265                                     const gchar *prop_name,
1266                                     const gchar *prop_value,
1267                                     GCancellable *cancellable,
1268                                     GError **error)
1269 {
1270         EClientClass *class;
1271         gboolean res;
1272
1273         g_return_val_if_fail (E_IS_CLIENT (client), FALSE);
1274         g_return_val_if_fail (prop_name != NULL, FALSE);
1275         g_return_val_if_fail (prop_value != NULL, FALSE);
1276
1277         class = E_CLIENT_GET_CLASS (client);
1278         g_return_val_if_fail (class != NULL, FALSE);
1279         g_return_val_if_fail (class->set_backend_property_sync != NULL, FALSE);
1280
1281         res = class->set_backend_property_sync (client, prop_name, prop_value, cancellable, error);
1282
1283         if (error && *error)
1284                 e_client_unwrap_dbus_error (client, *error, error);
1285
1286         return res;
1287 }
1288
1289 /**
1290  * e_client_open:
1291  * @client: an #EClient
1292  * @only_if_exists: if %TRUE, fail if this book doesn't already exist, otherwise create it first
1293  * @cancellable: a #GCancellable; can be %NULL
1294  * @callback: callback to call when a result is ready
1295  * @user_data: user data for the @callback
1296  *
1297  * Opens the @client, making it ready for queries and other operations.
1298  * The call is finished by e_client_open_finish() from the @callback.
1299  *
1300  * Since: 3.2
1301  **/
1302 void
1303 e_client_open (EClient *client,
1304                gboolean only_if_exists,
1305                GCancellable *cancellable,
1306                GAsyncReadyCallback callback,
1307                gpointer user_data)
1308 {
1309         EClientClass *class;
1310
1311         g_return_if_fail (callback != NULL);
1312         g_return_if_fail (E_IS_CLIENT (client));
1313
1314         class = E_CLIENT_GET_CLASS (client);
1315         g_return_if_fail (class != NULL);
1316         g_return_if_fail (class->open != NULL);
1317
1318         class->open (client, only_if_exists, cancellable, callback, user_data);
1319 }
1320
1321 /**
1322  * e_client_open_finish:
1323  * @client: an #EClient
1324  * @result: a #GAsyncResult
1325  * @error: (out): a #GError to set an error, if any
1326  *
1327  * Finishes previous call of e_client_open().
1328  *
1329  * Returns: %TRUE if successful, %FALSE otherwise.
1330  *
1331  * Since: 3.2
1332  **/
1333 gboolean
1334 e_client_open_finish (EClient *client,
1335                       GAsyncResult *result,
1336                       GError **error)
1337 {
1338         EClientClass *class;
1339         gboolean res;
1340
1341         g_return_val_if_fail (E_IS_CLIENT (client), FALSE);
1342
1343         class = E_CLIENT_GET_CLASS (client);
1344         g_return_val_if_fail (class != NULL, FALSE);
1345         g_return_val_if_fail (class->open_finish != NULL, FALSE);
1346
1347         res = class->open_finish (client, result, error);
1348
1349         if (error && *error)
1350                 e_client_unwrap_dbus_error (client, *error, error);
1351
1352         return res;
1353 }
1354
1355 /**
1356  * e_client_open_sync:
1357  * @client: an #EClient
1358  * @only_if_exists: if %TRUE, fail if this book doesn't already exist, otherwise create it first
1359  * @cancellable: a #GCancellable; can be %NULL
1360  * @error: (out): a #GError to set an error, if any
1361  *
1362  * Opens the @client, making it ready for queries and other operations.
1363  *
1364  * Returns: %TRUE if successful, %FALSE otherwise.
1365  *
1366  * Since: 3.2
1367  **/
1368 gboolean
1369 e_client_open_sync (EClient *client,
1370                     gboolean only_if_exists,
1371                     GCancellable *cancellable,
1372                     GError **error)
1373 {
1374         EClientClass *class;
1375         gboolean res;
1376
1377         class = E_CLIENT_GET_CLASS (client);
1378         g_return_val_if_fail (class != NULL, FALSE);
1379         g_return_val_if_fail (class->open_sync != NULL, FALSE);
1380
1381         res = class->open_sync (client, only_if_exists, cancellable, error);
1382
1383         if (error && *error)
1384                 e_client_unwrap_dbus_error (client, *error, error);
1385
1386         return res;
1387 }
1388
1389 /**
1390  * e_client_remove:
1391  * @client: an #EClient
1392  * @cancellable: a #GCancellable; can be %NULL
1393  * @callback: callback to call when a result is ready
1394  * @user_data: user data for the @callback
1395  *
1396  * Removes the backing data for this #EClient. For example, with the file
1397  * backend this deletes the database file. You cannot get it back!
1398  * The call is finished by e_client_remove_finish() from the @callback.
1399  *
1400  * Since: 3.2
1401  *
1402  * Deprecated: 3.6: Use e_source_remove() instead.
1403  **/
1404 void
1405 e_client_remove (EClient *client,
1406                  GCancellable *cancellable,
1407                  GAsyncReadyCallback callback,
1408                  gpointer user_data)
1409 {
1410         EClientClass *class;
1411
1412         g_return_if_fail (E_IS_CLIENT (client));
1413         g_return_if_fail (callback != NULL);
1414
1415         class = E_CLIENT_GET_CLASS (client);
1416         g_return_if_fail (class != NULL);
1417         g_return_if_fail (class->remove != NULL);
1418
1419         class->remove (client, cancellable, callback, user_data);
1420 }
1421
1422 /**
1423  * e_client_remove_finish:
1424  * @client: an #EClient
1425  * @result: a #GAsyncResult
1426  * @error: (out): a #GError to set an error, if any
1427  *
1428  * Finishes previous call of e_client_remove().
1429  *
1430  * Returns: %TRUE if successful, %FALSE otherwise.
1431  *
1432  * Since: 3.2
1433  *
1434  * Deprecated: 3.6: Use e_source_remove_finish() instead.
1435  **/
1436 gboolean
1437 e_client_remove_finish (EClient *client,
1438                         GAsyncResult *result,
1439                         GError **error)
1440 {
1441         EClientClass *class;
1442         gboolean res;
1443
1444         g_return_val_if_fail (E_IS_CLIENT (client), FALSE);
1445
1446         class = E_CLIENT_GET_CLASS (client);
1447         g_return_val_if_fail (class != NULL, FALSE);
1448         g_return_val_if_fail (class->remove_finish != NULL, FALSE);
1449
1450         res = class->remove_finish (client, result, error);
1451
1452         if (error && *error)
1453                 e_client_unwrap_dbus_error (client, *error, error);
1454
1455         return res;
1456 }
1457
1458 /**
1459  * e_client_remove_sync:
1460  * @client: an #EClient
1461  * @cancellable: a #GCancellable; can be %NULL
1462  * @error: (out): a #GError to set an error, if any
1463  *
1464  * Removes the backing data for this #EClient. For example, with the file
1465  * backend this deletes the database file. You cannot get it back!
1466  *
1467  * Returns: %TRUE if successful, %FALSE otherwise.
1468  *
1469  * Since: 3.2
1470  *
1471  * Deprecated: 3.6: Use e_source_remove_sync() instead.
1472  **/
1473 gboolean
1474 e_client_remove_sync (EClient *client,
1475                       GCancellable *cancellable,
1476                       GError **error)
1477 {
1478         EClientClass *class;
1479         gboolean res;
1480
1481         class = E_CLIENT_GET_CLASS (client);
1482         g_return_val_if_fail (class != NULL, FALSE);
1483         g_return_val_if_fail (class->remove_sync != NULL, FALSE);
1484
1485         res = class->remove_sync (client, cancellable, error);
1486
1487         if (error && *error)
1488                 e_client_unwrap_dbus_error (client, *error, error);
1489
1490         return res;
1491 }
1492
1493 /**
1494  * e_client_refresh:
1495  * @client: an #EClient
1496  * @cancellable: a #GCancellable; can be %NULL
1497  * @callback: callback to call when a result is ready
1498  * @user_data: user data for the @callback
1499  *
1500  * Initiates refresh on the @client. Finishing the method doesn't mean
1501  * that the refresh is done, backend only notifies whether it started
1502  * refreshing or not. Use e_client_check_refresh_supported() to check
1503  * whether the backend supports this method.
1504  * The call is finished by e_client_refresh_finish() from the @callback.
1505  *
1506  * Since: 3.2
1507  **/
1508 void
1509 e_client_refresh (EClient *client,
1510                   GCancellable *cancellable,
1511                   GAsyncReadyCallback callback,
1512                   gpointer user_data)
1513 {
1514         EClientClass *class;
1515
1516         g_return_if_fail (E_IS_CLIENT (client));
1517         g_return_if_fail (callback != NULL);
1518
1519         class = E_CLIENT_GET_CLASS (client);
1520         g_return_if_fail (class != NULL);
1521         g_return_if_fail (class->refresh != NULL);
1522
1523         class->refresh (client, cancellable, callback, user_data);
1524 }
1525
1526 /**
1527  * e_client_refresh_finish:
1528  * @client: an #EClient
1529  * @result: a #GAsyncResult
1530  * @error: (out): a #GError to set an error, if any
1531  *
1532  * Finishes previous call of e_client_refresh().
1533  *
1534  * Returns: %TRUE if successful, %FALSE otherwise.
1535  *
1536  * Since: 3.2
1537  **/
1538 gboolean
1539 e_client_refresh_finish (EClient *client,
1540                          GAsyncResult *result,
1541                          GError **error)
1542 {
1543         EClientClass *class;
1544         gboolean res;
1545
1546         g_return_val_if_fail (E_IS_CLIENT (client), FALSE);
1547
1548         class = E_CLIENT_GET_CLASS (client);
1549         g_return_val_if_fail (class != NULL, FALSE);
1550         g_return_val_if_fail (class->refresh_finish != NULL, FALSE);
1551
1552         res = class->refresh_finish (client, result, error);
1553
1554         if (error && *error)
1555                 e_client_unwrap_dbus_error (client, *error, error);
1556
1557         return res;
1558 }
1559
1560 /**
1561  * e_client_refresh_sync:
1562  * @client: an #EClient
1563  * @cancellable: a #GCancellable; can be %NULL
1564  * @error: (out): a #GError to set an error, if any
1565  *
1566  * Initiates refresh on the @client. Finishing the method doesn't mean
1567  * that the refresh is done, backend only notifies whether it started
1568  * refreshing or not. Use e_client_check_refresh_supported() to check
1569  * whether the backend supports this method.
1570  *
1571  * Returns: %TRUE if successful, %FALSE otherwise.
1572  *
1573  * Since: 3.2
1574  **/
1575 gboolean
1576 e_client_refresh_sync (EClient *client,
1577                        GCancellable *cancellable,
1578                        GError **error)
1579 {
1580         EClientClass *class;
1581         gboolean res;
1582
1583         class = E_CLIENT_GET_CLASS (client);
1584         g_return_val_if_fail (class != NULL, FALSE);
1585         g_return_val_if_fail (class->refresh_sync != NULL, FALSE);
1586
1587         res = class->refresh_sync (client, cancellable, error);
1588
1589         if (error && *error)
1590                 e_client_unwrap_dbus_error (client, *error, error);
1591
1592         return res;
1593 }
1594
1595 /**
1596  * e_client_util_slist_to_strv:
1597  * @strings: (element-type utf8): a #GSList of strings (const gchar *)
1598  *
1599  * Convert a list of strings into a %NULL-terminated array of strings.
1600  *
1601  * Returns: (transfer full): Newly allocated %NULL-terminated array of strings.
1602  * The returned pointer should be freed with g_strfreev().
1603  *
1604  * Note: Paired function for this is e_client_util_strv_to_slist().
1605  *
1606  * Since: 3.2
1607  *
1608  * Deprecated: 3.8: Use e_util_slist_to_strv() instead.
1609  **/
1610 gchar **
1611 e_client_util_slist_to_strv (const GSList *strings)
1612 {
1613         return e_util_slist_to_strv (strings);
1614 }
1615
1616 /**
1617  * e_client_util_strv_to_slist:
1618  * @strv: a %NULL-terminated array of strings (const gchar *)
1619  *
1620  * Convert a %NULL-terminated array of strings to a list of strings.
1621  *
1622  * Returns: (transfer full) (element-type utf8): Newly allocated #GSList of
1623  * newly allocated strings. The returned pointer should be freed with
1624  * e_client_util_free_string_slist().
1625  *
1626  * Note: Paired function for this is e_client_util_slist_to_strv().
1627  *
1628  * Since: 3.2
1629  *
1630  * Deprecated: 3.8: Use e_util_strv_to_slist() instead.
1631  **/
1632 GSList *
1633 e_client_util_strv_to_slist (const gchar * const *strv)
1634 {
1635         return e_util_strv_to_slist (strv);
1636 }
1637
1638 /**
1639  * e_client_util_copy_string_slist:
1640  * @copy_to: (element-type utf8) (allow-none): Where to copy; may be %NULL
1641  * @strings: (element-type utf8): #GSList of strings to be copied
1642  *
1643  * Copies the #GSList of strings to the end of @copy_to.
1644  *
1645  * Returns: (transfer full) (element-type utf8): New head of @copy_to.
1646  * The returned pointer can be freed with e_client_util_free_string_slist().
1647  *
1648  * Since: 3.2
1649  *
1650  * Deprecated: 3.8: Use e_util_copy_string_slist() instead.
1651  **/
1652 GSList *
1653 e_client_util_copy_string_slist (GSList *copy_to,
1654                                  const GSList *strings)
1655 {
1656         return e_util_copy_string_slist (copy_to, strings);
1657 }
1658
1659 /**
1660  * e_client_util_copy_object_slist:
1661  * @copy_to: (element-type GObject) (allow-none): Where to copy; may be %NULL
1662  * @objects: (element-type GObject): #GSList of #GObject<!-- -->s to be copied
1663  *
1664  * Copies a #GSList of #GObject<!-- -->s to the end of @copy_to.
1665  *
1666  * Returns: (transfer full) (element-type GObject): New head of @copy_to.
1667  * The returned pointer can be freed with e_client_util_free_object_slist().
1668  *
1669  * Since: 3.2
1670  *
1671  * Deprecated: 3.8: Use e_util_copy_object_slist() instead.
1672  **/
1673 GSList *
1674 e_client_util_copy_object_slist (GSList *copy_to,
1675                                  const GSList *objects)
1676 {
1677         return e_util_copy_object_slist (copy_to, objects);
1678 }
1679
1680 /**
1681  * e_client_util_free_string_slist:
1682  * @strings: (element-type utf8): a #GSList of strings (gchar *)
1683  *
1684  * Frees memory previously allocated by e_client_util_strv_to_slist().
1685  *
1686  * Since: 3.2
1687  **/
1688 void
1689 e_client_util_free_string_slist (GSList *strings)
1690 {
1691         e_util_free_string_slist (strings);
1692 }
1693
1694 /**
1695  * e_client_util_free_object_slist:
1696  * @objects: (element-type GObject): a #GSList of #GObject<!-- -->s
1697  *
1698  * Calls g_object_unref() on each member of @objects and then frees @objects
1699  * itself.
1700  *
1701  * Since: 3.2
1702  **/
1703 void
1704 e_client_util_free_object_slist (GSList *objects)
1705 {
1706         e_util_free_object_slist (objects);
1707 }
1708
1709 /**
1710  * e_client_util_parse_comma_strings:
1711  * @strings: string of comma-separated values
1712  *
1713  * Parses comma-separated list of values into #GSList.
1714  *
1715  * Returns: (transfer full) (element-type utf8): Newly allocated #GSList of
1716  * newly allocated strings corresponding to values parsed from @strings.
1717  * Free the returned pointer with e_client_util_free_string_slist().
1718  *
1719  * Since: 3.2
1720  **/
1721 GSList *
1722 e_client_util_parse_comma_strings (const gchar *strings)
1723 {
1724         GSList *strs_slist = NULL;
1725         gchar **strs_strv = NULL;
1726         gint ii;
1727
1728         if (!strings || !*strings)
1729                 return NULL;
1730
1731         strs_strv = g_strsplit (strings, ",", -1);
1732         g_return_val_if_fail (strs_strv != NULL, NULL);
1733
1734         for (ii = 0; strs_strv && strs_strv[ii]; ii++) {
1735                 gchar *str = g_strstrip (strs_strv[ii]);
1736
1737                 if (str && *str)
1738                         strs_slist = g_slist_prepend (strs_slist, g_strdup (str));
1739         }
1740
1741         g_strfreev (strs_strv);
1742
1743         return g_slist_reverse (strs_slist);
1744 }
1745
1746 void
1747 e_client_finish_async_without_dbus (EClient *client,
1748                                     GCancellable *cancellable,
1749                                     GAsyncReadyCallback callback,
1750                                     gpointer user_data,
1751                                     gpointer source_tag,
1752                                     gpointer op_res,
1753                                     GDestroyNotify destroy_op_res)
1754 {
1755         GCancellable *use_cancellable;
1756         GSimpleAsyncResult *simple;
1757         guint32 opid;
1758
1759         g_return_if_fail (E_IS_CLIENT (client));
1760         g_return_if_fail (callback != NULL);
1761         g_return_if_fail (source_tag != NULL);
1762
1763         use_cancellable = cancellable;
1764         if (!use_cancellable)
1765                 use_cancellable = g_cancellable_new ();
1766
1767         opid = e_client_register_op (client, use_cancellable);
1768         g_return_if_fail (opid > 0);
1769
1770         simple = g_simple_async_result_new (
1771                 G_OBJECT (client), callback, user_data, source_tag);
1772
1773         g_simple_async_result_set_check_cancellable (simple, cancellable);
1774
1775         g_simple_async_result_set_op_res_gpointer (
1776                 simple, op_res, destroy_op_res);
1777
1778         g_simple_async_result_complete_in_idle (simple);
1779
1780         g_object_unref (simple);
1781
1782         if (use_cancellable != cancellable)
1783                 g_object_unref (use_cancellable);
1784 }
1785
1786 GDBusProxy *
1787 e_client_get_dbus_proxy (EClient *client)
1788 {
1789         EClientClass *class;
1790
1791         g_return_val_if_fail (E_IS_CLIENT (client), NULL);
1792
1793         class = E_CLIENT_GET_CLASS (client);
1794         g_return_val_if_fail (class != NULL, NULL);
1795         g_return_val_if_fail (class->get_dbus_proxy != NULL, NULL);
1796
1797         return class->get_dbus_proxy (client);
1798 }
1799
1800 /**
1801  * e_client_unwrap_dbus_error:
1802  * @client: an #EClient
1803  * @dbus_error: a #GError returned bu D-Bus
1804  * @out_error: a #GError variable where to store the result
1805  *
1806  * Unwraps D-Bus error to local error. @dbus_error is automatically freed.
1807  * @dbus_erorr and @out_error can point to the same variable.
1808  *
1809  * Since: 3.2
1810  **/
1811 void
1812 e_client_unwrap_dbus_error (EClient *client,
1813                             GError *dbus_error,
1814                             GError **out_error)
1815 {
1816         EClientClass *class;
1817
1818         g_return_if_fail (E_IS_CLIENT (client));
1819
1820         class = E_CLIENT_GET_CLASS (client);
1821         g_return_if_fail (class != NULL);
1822         g_return_if_fail (class->unwrap_dbus_error != NULL);
1823
1824         if (!dbus_error || !out_error) {
1825                 if (dbus_error)
1826                         g_error_free (dbus_error);
1827         } else {
1828                 class->unwrap_dbus_error (client, dbus_error, out_error);
1829         }
1830 }
1831
1832 /**
1833  * e_client_util_unwrap_dbus_error:
1834  * @dbus_error: DBus #GError to unwrap
1835  * @client_error: (out): Resulting #GError; can be %NULL
1836  * @known_errors: List of known errors against which try to match
1837  * @known_errors_count: How many items are stored in @known_errors
1838  * @known_errors_domain: Error domain for @known_errors
1839  * @fail_when_none_matched: Whether to fail when none of @known_errors matches
1840  *
1841  * The function takes a @dbus_error and tries to find a match in @known_errors
1842  * for it, if it is a G_IO_ERROR, G_IO_ERROR_DBUS_ERROR. If it is anything else
1843  * then the @dbus_error is moved to @client_error.
1844  *
1845  * The @fail_when_none_matched influences behaviour. If it's %TRUE, and none of
1846  * @known_errors matches, or this is not a G_IO_ERROR_DBUS_ERROR, then %FALSE
1847  * is returned and the @client_error is left without change. Otherwise, the
1848  * @fail_when_none_matched is %FALSE, the error is always processed and will
1849  * result in E_CLIENT_ERROR, E_CLIENT_ERROR_OTHER_ERROR if none of @known_error
1850  * matches.
1851  *
1852  * Returns: Whether was @dbus_error processed into @client_error.
1853  *
1854  * Note: The @dbus_error is automatically freed if returned %TRUE.
1855  *
1856  * Since: 3.2
1857  **/
1858 gboolean
1859 e_client_util_unwrap_dbus_error (GError *dbus_error,
1860                                  GError **client_error,
1861                                  const EClientErrorsList *known_errors,
1862                                  guint known_errors_count,
1863                                  GQuark known_errors_domain,
1864                                  gboolean fail_when_none_matched)
1865 {
1866         if (!client_error) {
1867                 if (dbus_error)
1868                         g_error_free (dbus_error);
1869                 return TRUE;
1870         }
1871
1872         if (!dbus_error) {
1873                 *client_error = NULL;
1874                 return TRUE;
1875         }
1876
1877         if (dbus_error->domain == known_errors_domain) {
1878                 *client_error = dbus_error;
1879                 return TRUE;
1880         }
1881
1882         if (known_errors) {
1883                 if (g_error_matches (dbus_error, G_IO_ERROR, G_IO_ERROR_DBUS_ERROR)) {
1884                         gchar *name;
1885                         gint ii;
1886
1887                         name = g_dbus_error_get_remote_error (dbus_error);
1888
1889                         for (ii = 0; ii < known_errors_count; ii++) {
1890                                 if (g_ascii_strcasecmp (known_errors[ii].name, name) == 0) {
1891                                         g_free (name);
1892
1893                                         g_dbus_error_strip_remote_error (dbus_error);
1894                                         *client_error = g_error_new_literal (known_errors_domain, known_errors[ii].err_code, dbus_error->message);
1895                                         g_error_free (dbus_error);
1896                                         return TRUE;
1897                                 }
1898                         }
1899
1900                         g_free (name);
1901                 }
1902         }
1903
1904         if (fail_when_none_matched)
1905                 return FALSE;
1906
1907         if (g_error_matches (dbus_error, G_IO_ERROR, G_IO_ERROR_DBUS_ERROR)) {
1908                 g_dbus_error_strip_remote_error (dbus_error);
1909                 *client_error = g_error_new_literal (E_CLIENT_ERROR, E_CLIENT_ERROR_OTHER_ERROR, dbus_error->message);
1910                 g_error_free (dbus_error);
1911         } else {
1912                 g_dbus_error_strip_remote_error (dbus_error);
1913                 *client_error = dbus_error;
1914         }
1915
1916         return TRUE;
1917 }
1918
1919 typedef struct _EClientAsyncOpData
1920 {
1921         EClient *client;
1922         guint32 opid;
1923
1924         gpointer source_tag;
1925         gchar *res_op_data; /* optional string to set on a GAsyncResult object as "res-op-data" user data */
1926         GAsyncReadyCallback callback;
1927         gpointer user_data;
1928
1929         gboolean result; /* result of the finish function call */
1930
1931         /* only one can be non-NULL, and the type is telling which 'out' value is valid */
1932         EClientProxyFinishVoidFunc finish_void;
1933         EClientProxyFinishBooleanFunc finish_boolean;
1934         EClientProxyFinishStringFunc finish_string;
1935         EClientProxyFinishStrvFunc finish_strv;
1936         EClientProxyFinishUintFunc finish_uint;
1937
1938         union {
1939                 gboolean val_boolean;
1940                 gchar *val_string;
1941                 gchar **val_strv;
1942                 guint val_uint;
1943         } out;
1944 } EClientAsyncOpData;
1945
1946 static void
1947 async_data_free (EClientAsyncOpData *async_data)
1948 {
1949         g_return_if_fail (async_data != NULL);
1950         g_return_if_fail (async_data->client != NULL);
1951
1952         e_client_unregister_op (async_data->client, async_data->opid);
1953
1954         if (async_data->finish_string)
1955                 g_free (async_data->out.val_string);
1956         else if (async_data->finish_strv)
1957                 g_strfreev (async_data->out.val_strv);
1958
1959         g_object_unref (async_data->client);
1960         g_free (async_data->res_op_data);
1961         g_free (async_data);
1962 }
1963
1964 static gboolean
1965 complete_async_op_in_idle_cb (gpointer user_data)
1966 {
1967         GSimpleAsyncResult *simple = user_data;
1968         gint run_main_depth;
1969
1970         g_return_val_if_fail (simple != NULL, FALSE);
1971
1972         run_main_depth = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (simple), "run-main-depth"));
1973         if (run_main_depth < 1)
1974                 run_main_depth = 1;
1975
1976         /* do not receive in higher level than was initially run */
1977         if (g_main_depth () > run_main_depth) {
1978                 return TRUE;
1979         }
1980
1981         g_simple_async_result_complete (simple);
1982         g_object_unref (simple);
1983
1984         return FALSE;
1985 }
1986
1987 static void
1988 finish_async_op (EClientAsyncOpData *async_data,
1989                  const GError *error,
1990                  gboolean in_idle)
1991 {
1992         GSimpleAsyncResult *simple;
1993
1994         g_return_if_fail (async_data != NULL);
1995         g_return_if_fail (async_data->source_tag != NULL);
1996         g_return_if_fail (async_data->client != NULL);
1997
1998         simple = g_simple_async_result_new (G_OBJECT (async_data->client), async_data->callback, async_data->user_data, async_data->source_tag);
1999         g_simple_async_result_set_op_res_gpointer (simple, async_data, (GDestroyNotify) async_data_free);
2000
2001         if (async_data->res_op_data)
2002                 g_object_set_data_full (G_OBJECT (simple), "res-op-data", g_strdup (async_data->res_op_data), g_free);
2003
2004         if (error != NULL)
2005                 g_simple_async_result_set_from_error (simple, error);
2006
2007         if (in_idle) {
2008                 g_object_set_data (G_OBJECT (simple), "run-main-depth", GINT_TO_POINTER (g_main_depth ()));
2009                 g_idle_add (complete_async_op_in_idle_cb, simple);
2010         } else {
2011                 g_simple_async_result_complete (simple);
2012                 g_object_unref (simple);
2013         }
2014 }
2015
2016 static void
2017 async_result_ready_cb (GObject *source_object,
2018                        GAsyncResult *result,
2019                        gpointer user_data)
2020 {
2021         GError *error = NULL;
2022         EClientAsyncOpData *async_data;
2023         EClient *client;
2024
2025         g_return_if_fail (result != NULL);
2026         g_return_if_fail (source_object != NULL);
2027
2028         async_data = user_data;
2029         g_return_if_fail (async_data != NULL);
2030         g_return_if_fail (async_data->client != NULL);
2031
2032         client = async_data->client;
2033         g_return_if_fail (e_client_get_dbus_proxy (client) == G_DBUS_PROXY (source_object));
2034
2035         if (async_data->finish_void)
2036                 async_data->result = async_data->finish_void (G_DBUS_PROXY (source_object), result, &error);
2037         else if (async_data->finish_boolean)
2038                 async_data->result = async_data->finish_boolean (G_DBUS_PROXY (source_object), result, &async_data->out.val_boolean, &error);
2039         else if (async_data->finish_string)
2040                 async_data->result = async_data->finish_string (G_DBUS_PROXY (source_object), result, &async_data->out.val_string, &error);
2041         else if (async_data->finish_strv)
2042                 async_data->result = async_data->finish_strv (G_DBUS_PROXY (source_object), result, &async_data->out.val_strv, &error);
2043         else if (async_data->finish_uint)
2044                 async_data->result = async_data->finish_uint (G_DBUS_PROXY (source_object), result, &async_data->out.val_uint, &error);
2045         else
2046                 g_warning ("%s: Do not know how to finish async operation", G_STRFUNC);
2047
2048         finish_async_op (async_data, error, FALSE);
2049
2050         if (error != NULL)
2051                 g_error_free (error);
2052 }
2053
2054 static EClientAsyncOpData *
2055 prepare_async_data (EClient *client,
2056                     GCancellable *cancellable,
2057                     GAsyncReadyCallback callback,
2058                     gpointer user_data,
2059                     gpointer source_tag,
2060                     gboolean error_report_only,
2061                     EClientProxyFinishVoidFunc finish_void,
2062                     EClientProxyFinishBooleanFunc finish_boolean,
2063                     EClientProxyFinishStringFunc finish_string,
2064                     EClientProxyFinishStrvFunc finish_strv,
2065                     EClientProxyFinishUintFunc finish_uint,
2066                     GDBusProxy **proxy,
2067                     GCancellable **out_cancellable)
2068 {
2069         EClientAsyncOpData *async_data;
2070         GCancellable *use_cancellable;
2071         guint32 opid;
2072
2073         g_return_val_if_fail (client != NULL, NULL);
2074         g_return_val_if_fail (callback != NULL, NULL);
2075         g_return_val_if_fail (source_tag != NULL, NULL);
2076
2077         if (!error_report_only) {
2078                 g_return_val_if_fail (proxy != NULL, NULL);
2079                 g_return_val_if_fail (out_cancellable != NULL, NULL);
2080                 g_return_val_if_fail (finish_void || finish_boolean || finish_string || finish_strv || finish_uint, NULL);
2081
2082                 if (finish_void) {
2083                         g_return_val_if_fail (finish_boolean == NULL, NULL);
2084                         g_return_val_if_fail (finish_string == NULL, NULL);
2085                         g_return_val_if_fail (finish_strv == NULL, NULL);
2086                         g_return_val_if_fail (finish_uint == NULL, NULL);
2087                 }
2088
2089                 if (finish_boolean) {
2090                         g_return_val_if_fail (finish_void == NULL, NULL);
2091                         g_return_val_if_fail (finish_string == NULL, NULL);
2092                         g_return_val_if_fail (finish_strv == NULL, NULL);
2093                         g_return_val_if_fail (finish_uint == NULL, NULL);
2094                 }
2095
2096                 if (finish_string) {
2097                         g_return_val_if_fail (finish_void == NULL, NULL);
2098                         g_return_val_if_fail (finish_boolean == NULL, NULL);
2099                         g_return_val_if_fail (finish_strv == NULL, NULL);
2100                         g_return_val_if_fail (finish_uint == NULL, NULL);
2101                 }
2102
2103                 if (finish_strv) {
2104                         g_return_val_if_fail (finish_void == NULL, NULL);
2105                         g_return_val_if_fail (finish_boolean == NULL, NULL);
2106                         g_return_val_if_fail (finish_string == NULL, NULL);
2107                         g_return_val_if_fail (finish_uint == NULL, NULL);
2108                 }
2109
2110                 if (finish_uint) {
2111                         g_return_val_if_fail (finish_void == NULL, NULL);
2112                         g_return_val_if_fail (finish_boolean == NULL, NULL);
2113                         g_return_val_if_fail (finish_string == NULL, NULL);
2114                         g_return_val_if_fail (finish_strv == NULL, NULL);
2115                 }
2116
2117                 *proxy = e_client_get_dbus_proxy (client);
2118                 if (!*proxy)
2119                         return NULL;
2120         }
2121
2122         use_cancellable = cancellable;
2123         if (!use_cancellable)
2124                 use_cancellable = g_cancellable_new ();
2125
2126         opid = e_client_register_op (client, use_cancellable);
2127         async_data = g_new0 (EClientAsyncOpData, 1);
2128         async_data->client = g_object_ref (client);
2129         async_data->opid = opid;
2130         async_data->source_tag = source_tag;
2131         async_data->callback = callback;
2132         async_data->user_data = user_data;
2133         async_data->finish_void = finish_void;
2134         async_data->finish_boolean = finish_boolean;
2135         async_data->finish_string = finish_string;
2136         async_data->finish_strv = finish_strv;
2137         async_data->finish_uint = finish_uint;
2138
2139         /* EClient from e_client_register_op() took ownership of the use_cancellable */
2140         if (use_cancellable != cancellable)
2141                 g_object_unref (use_cancellable);
2142
2143         if (out_cancellable)
2144                 *out_cancellable = use_cancellable;
2145
2146         return async_data;
2147 }
2148
2149 void
2150 e_client_proxy_return_async_error (EClient *client,
2151                                    const GError *error,
2152                                    GAsyncReadyCallback callback,
2153                                    gpointer user_data,
2154                                    gpointer source_tag)
2155 {
2156         EClientAsyncOpData *async_data;
2157
2158         g_return_if_fail (E_IS_CLIENT (client));
2159         g_return_if_fail (error != NULL);
2160         g_return_if_fail (callback != NULL);
2161
2162         async_data = prepare_async_data (client, NULL, callback, user_data, source_tag, TRUE, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
2163         g_return_if_fail (async_data != NULL);
2164
2165         finish_async_op (async_data, error, TRUE);
2166 }
2167
2168 void
2169 e_client_proxy_call_void (EClient *client,
2170                           GCancellable *cancellable,
2171                           GAsyncReadyCallback callback,
2172                           gpointer user_data,
2173                           gpointer source_tag,
2174                           void (*func) (GDBusProxy *proxy,
2175                                         GCancellable *cancellable,
2176                                         GAsyncReadyCallback callback,
2177                                         gpointer user_data),
2178                           EClientProxyFinishVoidFunc finish_void,
2179                           EClientProxyFinishBooleanFunc finish_boolean,
2180                           EClientProxyFinishStringFunc finish_string,
2181                           EClientProxyFinishStrvFunc finish_strv,
2182                           EClientProxyFinishUintFunc finish_uint)
2183 {
2184         EClientAsyncOpData *async_data;
2185         GDBusProxy *proxy = NULL;
2186
2187         g_return_if_fail (E_IS_CLIENT (client));
2188         g_return_if_fail (callback != NULL);
2189         g_return_if_fail (source_tag != NULL);
2190         e_client_return_async_if_fail (func != NULL, client, callback, user_data, source_tag);
2191
2192         async_data = prepare_async_data (client, cancellable, callback, user_data, source_tag, FALSE, finish_void, finish_boolean, finish_string, finish_strv, finish_uint, &proxy, &cancellable);
2193         e_client_return_async_if_fail (async_data != NULL, client, callback, user_data, source_tag);
2194
2195         func (proxy, cancellable, async_result_ready_cb, async_data);
2196 }
2197
2198 void
2199 e_client_proxy_call_boolean (EClient *client,
2200                              gboolean in_boolean,
2201                              GCancellable *cancellable,
2202                              GAsyncReadyCallback callback,
2203                              gpointer user_data,
2204                              gpointer source_tag,
2205                              void (*func) (GDBusProxy *proxy,
2206                                            gboolean in_boolean,
2207                                            GCancellable *cancellable,
2208                                            GAsyncReadyCallback callback,
2209                                            gpointer user_data),
2210                              EClientProxyFinishVoidFunc finish_void,
2211                              EClientProxyFinishBooleanFunc finish_boolean,
2212                              EClientProxyFinishStringFunc finish_string,
2213                              EClientProxyFinishStrvFunc finish_strv,
2214                              EClientProxyFinishUintFunc finish_uint)
2215 {
2216         EClientAsyncOpData *async_data;
2217         GDBusProxy *proxy = NULL;
2218
2219         g_return_if_fail (E_IS_CLIENT (client));
2220         g_return_if_fail (callback != NULL);
2221         g_return_if_fail (source_tag != NULL);
2222         e_client_return_async_if_fail (func != NULL, client, callback, user_data, source_tag);
2223
2224         async_data = prepare_async_data (client, cancellable, callback, user_data, source_tag, FALSE, finish_void, finish_boolean, finish_string, finish_strv, finish_uint, &proxy, &cancellable);
2225         e_client_return_async_if_fail (async_data != NULL, client, callback, user_data, source_tag);
2226
2227         func (proxy, in_boolean, cancellable, async_result_ready_cb, async_data);
2228 }
2229
2230 void
2231 e_client_proxy_call_string (EClient *client,
2232                             const gchar *in_string,
2233                             GCancellable *cancellable,
2234                             GAsyncReadyCallback callback,
2235                             gpointer user_data,
2236                             gpointer source_tag,
2237                             void (*func) (GDBusProxy *proxy,
2238                                           const gchar *in_string,
2239                                           GCancellable *cancellable,
2240                                           GAsyncReadyCallback callback,
2241                                           gpointer user_data),
2242                             EClientProxyFinishVoidFunc finish_void,
2243                             EClientProxyFinishBooleanFunc finish_boolean,
2244                             EClientProxyFinishStringFunc finish_string,
2245                             EClientProxyFinishStrvFunc finish_strv,
2246                             EClientProxyFinishUintFunc finish_uint)
2247 {
2248         EClientAsyncOpData *async_data;
2249         GDBusProxy *proxy = NULL;
2250
2251         g_return_if_fail (E_IS_CLIENT (client));
2252         g_return_if_fail (callback != NULL);
2253         g_return_if_fail (source_tag != NULL);
2254         e_client_return_async_if_fail (func != NULL, client, callback, user_data, source_tag);
2255         e_client_return_async_if_fail (in_string != NULL, client, callback, user_data, source_tag);
2256
2257         async_data = prepare_async_data (client, cancellable, callback, user_data, source_tag, FALSE, finish_void, finish_boolean, finish_string, finish_strv, finish_uint, &proxy, &cancellable);
2258         e_client_return_async_if_fail (async_data != NULL, client, callback, user_data, source_tag);
2259
2260         func (proxy, in_string, cancellable, async_result_ready_cb, async_data);
2261 }
2262
2263 void
2264 e_client_proxy_call_string_with_res_op_data (EClient *client,
2265                                              const gchar *in_string,
2266                                              GCancellable *cancellable,
2267                                              GAsyncReadyCallback callback,
2268                                              gpointer user_data,
2269                                              gpointer source_tag,
2270                                              const gchar *res_op_data,
2271                                              void (*func) (GDBusProxy *proxy,
2272                                                            const gchar *in_string,
2273                                                            GCancellable *cancellable,
2274                                                            GAsyncReadyCallback callback,
2275                                                            gpointer user_data),
2276                                              EClientProxyFinishVoidFunc finish_void,
2277                                              EClientProxyFinishBooleanFunc finish_boolean,
2278                                              EClientProxyFinishStringFunc finish_string,
2279                                              EClientProxyFinishStrvFunc finish_strv,
2280                                              EClientProxyFinishUintFunc finish_uint)
2281 {
2282         EClientAsyncOpData *async_data;
2283         GDBusProxy *proxy = NULL;
2284
2285         g_return_if_fail (E_IS_CLIENT (client));
2286         g_return_if_fail (callback != NULL);
2287         g_return_if_fail (source_tag != NULL);
2288         e_client_return_async_if_fail (func != NULL, client, callback, user_data, source_tag);
2289         e_client_return_async_if_fail (in_string != NULL, client, callback, user_data, source_tag);
2290
2291         async_data = prepare_async_data (client, cancellable, callback, user_data, source_tag, FALSE, finish_void, finish_boolean, finish_string, finish_strv, finish_uint, &proxy, &cancellable);
2292         e_client_return_async_if_fail (async_data != NULL, client, callback, user_data, source_tag);
2293
2294         async_data->res_op_data = g_strdup (res_op_data);
2295
2296         func (proxy, in_string, cancellable, async_result_ready_cb, async_data);
2297 }
2298
2299 void
2300 e_client_proxy_call_strv (EClient *client,
2301                           const gchar * const *in_strv,
2302                           GCancellable *cancellable,
2303                           GAsyncReadyCallback callback,
2304                           gpointer user_data,
2305                           gpointer source_tag,
2306                           void (*func) (GDBusProxy *proxy,
2307                                         const gchar * const * in_strv,
2308                                         GCancellable *cancellable,
2309                                         GAsyncReadyCallback callback,
2310                                         gpointer user_data),
2311                           EClientProxyFinishVoidFunc finish_void,
2312                           EClientProxyFinishBooleanFunc finish_boolean,
2313                           EClientProxyFinishStringFunc finish_string,
2314                           EClientProxyFinishStrvFunc finish_strv,
2315                           EClientProxyFinishUintFunc finish_uint)
2316 {
2317         EClientAsyncOpData *async_data;
2318         GDBusProxy *proxy = NULL;
2319
2320         g_return_if_fail (E_IS_CLIENT (client));
2321         g_return_if_fail (callback != NULL);
2322         g_return_if_fail (source_tag != NULL);
2323         e_client_return_async_if_fail (func != NULL, client, callback, user_data, source_tag);
2324         e_client_return_async_if_fail (in_strv != NULL, client, callback, user_data, source_tag);
2325
2326         async_data = prepare_async_data (client, cancellable, callback, user_data, source_tag, FALSE, finish_void, finish_boolean, finish_string, finish_strv, finish_uint, &proxy, &cancellable);
2327         e_client_return_async_if_fail (async_data != NULL, client, callback, user_data, source_tag);
2328
2329         func (proxy, in_strv, cancellable, async_result_ready_cb, async_data);
2330 }
2331
2332 void
2333 e_client_proxy_call_uint (EClient *client,
2334                           guint in_uint,
2335                           GCancellable *cancellable,
2336                           GAsyncReadyCallback callback,
2337                           gpointer user_data,
2338                           gpointer source_tag,
2339                           void (*func) (GDBusProxy *proxy,
2340                                         guint in_uint,
2341                                         GCancellable *cancellable,
2342                                         GAsyncReadyCallback callback,
2343                                         gpointer user_data),
2344                           EClientProxyFinishVoidFunc finish_void,
2345                           EClientProxyFinishBooleanFunc finish_boolean,
2346                           EClientProxyFinishStringFunc finish_string,
2347                           EClientProxyFinishStrvFunc finish_strv,
2348                           EClientProxyFinishUintFunc finish_uint)
2349 {
2350         EClientAsyncOpData *async_data;
2351         GDBusProxy *proxy = NULL;
2352
2353         g_return_if_fail (E_IS_CLIENT (client));
2354         g_return_if_fail (callback != NULL);
2355         g_return_if_fail (source_tag != NULL);
2356         e_client_return_async_if_fail (func != NULL, client, callback, user_data, source_tag);
2357
2358         async_data = prepare_async_data (client, cancellable, callback, user_data, source_tag, FALSE, finish_void, finish_boolean, finish_string, finish_strv, finish_uint, &proxy, &cancellable);
2359         e_client_return_async_if_fail (async_data != NULL, client, callback, user_data, source_tag);
2360
2361         func (proxy, in_uint, cancellable, async_result_ready_cb, async_data);
2362 }
2363
2364 gboolean
2365 e_client_proxy_call_finish_void (EClient *client,
2366                                  GAsyncResult *result,
2367                                  GError **error,
2368                                  gpointer source_tag)
2369 {
2370         GSimpleAsyncResult *simple;
2371         GError *local_error = NULL;
2372         EClientAsyncOpData *async_data;
2373
2374         g_return_val_if_fail (E_IS_CLIENT (client), FALSE);
2375         g_return_val_if_fail (result != NULL, FALSE);
2376         g_return_val_if_fail (source_tag != NULL, FALSE);
2377         g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (client), source_tag), FALSE);
2378
2379         simple = G_SIMPLE_ASYNC_RESULT (result);
2380
2381         if (g_simple_async_result_propagate_error (simple, &local_error)) {
2382                 e_client_unwrap_dbus_error (client, local_error, error);
2383                 return FALSE;
2384         }
2385
2386         async_data = g_simple_async_result_get_op_res_gpointer (simple);
2387         g_return_val_if_fail (async_data != NULL, FALSE);
2388
2389         return async_data->result;
2390 }
2391
2392 gboolean
2393 e_client_proxy_call_finish_boolean (EClient *client,
2394                                     GAsyncResult *result,
2395                                     gboolean *out_boolean,
2396                                     GError **error,
2397                                     gpointer source_tag)
2398 {
2399         GSimpleAsyncResult *simple;
2400         GError *local_error = NULL;
2401         EClientAsyncOpData *async_data;
2402
2403         g_return_val_if_fail (E_IS_CLIENT (client), FALSE);
2404         g_return_val_if_fail (result != NULL, FALSE);
2405         g_return_val_if_fail (source_tag != NULL, FALSE);
2406         g_return_val_if_fail (out_boolean != NULL, FALSE);
2407         g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (client), source_tag), FALSE);
2408
2409         simple = G_SIMPLE_ASYNC_RESULT (result);
2410
2411         if (g_simple_async_result_propagate_error (simple, &local_error)) {
2412                 e_client_unwrap_dbus_error (client, local_error, error);
2413                 return FALSE;
2414         }
2415
2416         async_data = g_simple_async_result_get_op_res_gpointer (simple);
2417         g_return_val_if_fail (async_data != NULL, FALSE);
2418
2419         *out_boolean = async_data->out.val_boolean;
2420
2421         return async_data->result;
2422 }
2423
2424 gboolean
2425 e_client_proxy_call_finish_string (EClient *client,
2426                                    GAsyncResult *result,
2427                                    gchar **out_string,
2428                                    GError **error,
2429                                    gpointer source_tag)
2430 {
2431         GSimpleAsyncResult *simple;
2432         GError *local_error = NULL;
2433         EClientAsyncOpData *async_data;
2434
2435         g_return_val_if_fail (E_IS_CLIENT (client), FALSE);
2436         g_return_val_if_fail (result != NULL, FALSE);
2437         g_return_val_if_fail (source_tag != NULL, FALSE);
2438         g_return_val_if_fail (out_string != NULL, FALSE);
2439         g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (client), source_tag), FALSE);
2440
2441         simple = G_SIMPLE_ASYNC_RESULT (result);
2442
2443         if (g_simple_async_result_propagate_error (simple, &local_error)) {
2444                 e_client_unwrap_dbus_error (client, local_error, error);
2445                 return FALSE;
2446         }
2447
2448         async_data = g_simple_async_result_get_op_res_gpointer (simple);
2449         g_return_val_if_fail (async_data != NULL, FALSE);
2450
2451         *out_string = async_data->out.val_string;
2452         async_data->out.val_string = NULL;
2453
2454         return async_data->result;
2455 }
2456
2457 gboolean
2458 e_client_proxy_call_finish_strv (EClient *client,
2459                                  GAsyncResult *result,
2460                                  gchar ***out_strv,
2461                                  GError **error,
2462                                  gpointer source_tag)
2463 {
2464         GSimpleAsyncResult *simple;
2465         GError *local_error = NULL;
2466         EClientAsyncOpData *async_data;
2467
2468         g_return_val_if_fail (E_IS_CLIENT (client), FALSE);
2469         g_return_val_if_fail (result != NULL, FALSE);
2470         g_return_val_if_fail (source_tag != NULL, FALSE);
2471         g_return_val_if_fail (out_strv != NULL, FALSE);
2472         g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (client), source_tag), FALSE);
2473
2474         simple = G_SIMPLE_ASYNC_RESULT (result);
2475
2476         if (g_simple_async_result_propagate_error (simple, &local_error)) {
2477                 e_client_unwrap_dbus_error (client, local_error, error);
2478                 return FALSE;
2479         }
2480
2481         async_data = g_simple_async_result_get_op_res_gpointer (simple);
2482         g_return_val_if_fail (async_data != NULL, FALSE);
2483
2484         *out_strv = async_data->out.val_strv;
2485         async_data->out.val_strv = NULL;
2486
2487         return async_data->result;
2488 }
2489
2490 gboolean
2491 e_client_proxy_call_finish_uint (EClient *client,
2492                                  GAsyncResult *result,
2493                                  guint *out_uint,
2494                                  GError **error,
2495                                  gpointer source_tag)
2496 {
2497         GSimpleAsyncResult *simple;
2498         GError *local_error = NULL;
2499         EClientAsyncOpData *async_data;
2500
2501         g_return_val_if_fail (E_IS_CLIENT (client), FALSE);
2502         g_return_val_if_fail (result != NULL, FALSE);
2503         g_return_val_if_fail (source_tag != NULL, FALSE);
2504         g_return_val_if_fail (out_uint != NULL, FALSE);
2505         g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (client), source_tag), FALSE);
2506
2507         simple = G_SIMPLE_ASYNC_RESULT (result);
2508
2509         if (g_simple_async_result_propagate_error (simple, &local_error)) {
2510                 e_client_unwrap_dbus_error (client, local_error, error);
2511                 return FALSE;
2512         }
2513
2514         async_data = g_simple_async_result_get_op_res_gpointer (simple);
2515         g_return_val_if_fail (async_data != NULL, FALSE);
2516
2517         *out_uint = async_data->out.val_uint;
2518
2519         return async_data->result;
2520 }
2521
2522 #define SYNC_CALL_TEMPLATE(_out_test,_the_call)                 \
2523         GDBusProxy *proxy;                                      \
2524         GCancellable *use_cancellable;                          \
2525         guint32 opid;                                           \
2526         gboolean result;                                        \
2527         GError *local_error = NULL;                             \
2528                                                                 \
2529         g_return_val_if_fail (E_IS_CLIENT (client), FALSE);     \
2530         g_return_val_if_fail (func != NULL, FALSE);             \
2531         g_return_val_if_fail (_out_test != NULL, FALSE);        \
2532                                                                 \
2533         proxy = e_client_get_dbus_proxy (client);               \
2534         g_return_val_if_fail (proxy != NULL, FALSE);            \
2535                                                                 \
2536         use_cancellable = cancellable;                          \
2537         if (!use_cancellable)                                   \
2538                 use_cancellable = g_cancellable_new ();         \
2539                                                                 \
2540         g_object_ref (client);                                  \
2541         opid = e_client_register_op (client, use_cancellable);  \
2542                                                                 \
2543         result = func _the_call;                                \
2544                                                                 \
2545         e_client_unregister_op (client, opid);                  \
2546         g_object_unref (client);                                \
2547                                                                 \
2548         if (use_cancellable != cancellable)                     \
2549                 g_object_unref (use_cancellable);               \
2550                                                                 \
2551         e_client_unwrap_dbus_error (client, local_error, error);\
2552                                                                 \
2553         return result;
2554
2555 gboolean
2556 e_client_proxy_call_sync_void__void (EClient *client,
2557                                      GCancellable *cancellable,
2558                                      GError **error,
2559                                      gboolean (*func) (GDBusProxy *proxy,
2560                                                        GCancellable *cancellable,
2561                                                        GError **error))
2562 {
2563         SYNC_CALL_TEMPLATE (client, (proxy, use_cancellable, &local_error))
2564 }
2565
2566 gboolean
2567 e_client_proxy_call_sync_void__boolean (EClient *client,
2568                                         gboolean *out_boolean,
2569                                         GCancellable *cancellable,
2570                                         GError **error,
2571                                         gboolean (*func) (GDBusProxy *proxy,
2572                                                           gboolean *out_boolean,
2573                                                           GCancellable *cancellable,
2574                                                           GError **error))
2575 {
2576         SYNC_CALL_TEMPLATE (out_boolean, (proxy, out_boolean, use_cancellable, &local_error))
2577 }
2578
2579 gboolean
2580 e_client_proxy_call_sync_void__string (EClient *client,
2581                                        gchar **out_string,
2582                                        GCancellable *cancellable,
2583                                        GError **error,
2584                                        gboolean (*func) (GDBusProxy *proxy,
2585                                                          gchar **out_string,
2586                                                          GCancellable *cancellable,
2587                                                          GError **error))
2588 {
2589         SYNC_CALL_TEMPLATE (out_string, (proxy, out_string, use_cancellable, &local_error))
2590 }
2591
2592 gboolean
2593 e_client_proxy_call_sync_void__strv (EClient *client,
2594                                      gchar ***out_strv,
2595                                      GCancellable *cancellable,
2596                                      GError **error,
2597                                      gboolean (*func) (GDBusProxy *proxy,
2598                                                        gchar ***out_strv,
2599                                                        GCancellable *cancellable,
2600                                                        GError **error))
2601 {
2602         SYNC_CALL_TEMPLATE (out_strv, (proxy, out_strv, use_cancellable, &local_error))
2603 }
2604
2605 gboolean
2606 e_client_proxy_call_sync_void__uint (EClient *client,
2607                                      guint *out_uint,
2608                                      GCancellable *cancellable,
2609                                      GError **error,
2610                                      gboolean (*func) (GDBusProxy *proxy,
2611                                                        guint *out_uint,
2612                                                        GCancellable *cancellable,
2613                                                        GError **error))
2614 {
2615         SYNC_CALL_TEMPLATE (out_uint, (proxy, out_uint, use_cancellable, &local_error))
2616 }
2617
2618 gboolean
2619 e_client_proxy_call_sync_boolean__void (EClient *client,
2620                                         gboolean in_boolean,
2621                                         GCancellable *cancellable,
2622                                         GError **error,
2623                                         gboolean (*func) (GDBusProxy *proxy,
2624                                                           gboolean in_boolean,
2625                                                           GCancellable *cancellable,
2626                                                           GError **error))
2627 {
2628         SYNC_CALL_TEMPLATE (client, (proxy, in_boolean, use_cancellable, &local_error))
2629 }
2630
2631 gboolean
2632 e_client_proxy_call_sync_boolean__boolean (EClient *client,
2633                                            gboolean in_boolean,
2634                                            gboolean *out_boolean,
2635                                            GCancellable *cancellable,
2636                                            GError **error,
2637                                            gboolean (*func) (GDBusProxy *proxy,
2638                                                              gboolean in_boolean,
2639                                                              gboolean *out_boolean,
2640                                                              GCancellable *cancellable,
2641                                                              GError **error))
2642 {
2643         SYNC_CALL_TEMPLATE (out_boolean, (proxy, in_boolean, out_boolean, use_cancellable, &local_error))
2644 }
2645
2646 gboolean
2647 e_client_proxy_call_sync_boolean__string (EClient *client,
2648                                           gboolean in_boolean,
2649                                           gchar **out_string,
2650                                           GCancellable *cancellable,
2651                                           GError **error,
2652                                           gboolean (*func) (GDBusProxy *proxy,
2653                                                             gboolean in_boolean,
2654                                                             gchar **out_string,
2655                                                             GCancellable *cancellable,
2656                                                             GError **error))
2657 {
2658         SYNC_CALL_TEMPLATE (out_string, (proxy, in_boolean, out_string, use_cancellable, &local_error))
2659 }
2660
2661 gboolean
2662 e_client_proxy_call_sync_boolean__strv (EClient *client,
2663                                         gboolean in_boolean,
2664                                         gchar ***out_strv,
2665                                         GCancellable *cancellable,
2666                                         GError **error,
2667                                         gboolean (*func) (GDBusProxy *proxy,
2668                                                           gboolean in_boolean,
2669                                                           gchar ***out_strv,
2670                                                           GCancellable *cancellable,
2671                                                           GError **error))
2672 {
2673         SYNC_CALL_TEMPLATE (out_strv, (proxy, in_boolean, out_strv, use_cancellable, &local_error))
2674 }
2675
2676 gboolean
2677 e_client_proxy_call_sync_boolean__uint (EClient *client,
2678                                         gboolean in_boolean,
2679                                         guint *out_uint,
2680                                         GCancellable *cancellable,
2681                                         GError **error,
2682                                         gboolean (*func) (GDBusProxy *proxy,
2683                                                           gboolean in_boolean,
2684                                                           guint *out_uint,
2685                                                           GCancellable *cancellable,
2686                                                           GError **error))
2687 {
2688         SYNC_CALL_TEMPLATE (out_uint, (proxy, in_boolean, out_uint, use_cancellable, &local_error))
2689 }
2690
2691 gboolean
2692 e_client_proxy_call_sync_string__void (EClient *client,
2693                                        const gchar *in_string,
2694                                        GCancellable *cancellable,
2695                                        GError **error,
2696                                        gboolean (*func) (GDBusProxy *proxy,
2697                                                          const gchar *in_string,
2698                                                          GCancellable *cancellable,
2699                                                          GError **error))
2700 {
2701         SYNC_CALL_TEMPLATE (client, (proxy, in_string, use_cancellable, &local_error))
2702 }
2703
2704 gboolean
2705 e_client_proxy_call_sync_string__boolean (EClient *client,
2706                                           const gchar *in_string,
2707                                           gboolean *out_boolean,
2708                                           GCancellable *cancellable,
2709                                           GError **error,
2710                                           gboolean (*func) (GDBusProxy *proxy,
2711                                                             const gchar *in_string,
2712                                                             gboolean *out_boolean,
2713                                                             GCancellable *cancellable,
2714                                                             GError **error))
2715 {
2716         SYNC_CALL_TEMPLATE (out_boolean, (proxy, in_string, out_boolean, use_cancellable, &local_error))
2717 }
2718
2719 gboolean
2720 e_client_proxy_call_sync_string__string (EClient *client,
2721                                          const gchar *in_string,
2722                                          gchar **out_string,
2723                                          GCancellable *cancellable,
2724                                          GError **error,
2725                                          gboolean (*func) (GDBusProxy *proxy,
2726                                                            const gchar *in_string,
2727                                                            gchar **out_string,
2728                                                            GCancellable *cancellable,
2729                                                            GError **error))
2730 {
2731         SYNC_CALL_TEMPLATE (out_string, (proxy, in_string, out_string, use_cancellable, &local_error))
2732 }
2733
2734 gboolean
2735 e_client_proxy_call_sync_string__strv (EClient *client,
2736                                        const gchar *in_string,
2737                                        gchar ***out_strv,
2738                                        GCancellable *cancellable,
2739                                        GError **error,
2740                                        gboolean (*func) (GDBusProxy *proxy,
2741                                                          const gchar *in_string,
2742                                                          gchar ***out_strv,
2743                                                          GCancellable *cancellable,
2744                                                          GError **error))
2745 {
2746         SYNC_CALL_TEMPLATE (out_strv, (proxy, in_string, out_strv, use_cancellable, &local_error))
2747 }
2748
2749 gboolean
2750 e_client_proxy_call_sync_string__uint (EClient *client,
2751                                        const gchar *in_string,
2752                                        guint *out_uint,
2753                                        GCancellable *cancellable,
2754                                        GError **error,
2755                                        gboolean (*func) (GDBusProxy *proxy,
2756                                                          const gchar *in_string,
2757                                                          guint *out_uint,
2758                                                          GCancellable *cancellable,
2759                                                          GError **error))
2760 {
2761         SYNC_CALL_TEMPLATE (out_uint, (proxy, in_string, out_uint, use_cancellable, &local_error))
2762 }
2763
2764 gboolean
2765 e_client_proxy_call_sync_strv__void (EClient *client,
2766                                      const gchar * const *in_strv,
2767                                      GCancellable *cancellable,
2768                                      GError **error,
2769                                      gboolean (*func) (GDBusProxy *proxy,
2770                                                        const gchar * const *in_strv,
2771                                                        GCancellable *cancellable,
2772                                                        GError **error))
2773 {
2774         SYNC_CALL_TEMPLATE (client, (proxy, in_strv, use_cancellable, &local_error))
2775 }
2776
2777 gboolean
2778 e_client_proxy_call_sync_strv__boolean (EClient *client,
2779                                         const gchar * const *in_strv,
2780                                         gboolean *out_boolean,
2781                                         GCancellable *cancellable,
2782                                         GError **error,
2783                                         gboolean (*func) (GDBusProxy *proxy,
2784                                                           const gchar * const *in_strv,
2785                                                           gboolean *out_boolean,
2786                                                           GCancellable *cancellable,
2787                                                           GError **error))
2788 {
2789         SYNC_CALL_TEMPLATE (out_boolean, (proxy, in_strv, out_boolean, use_cancellable, &local_error))
2790 }
2791
2792 gboolean
2793 e_client_proxy_call_sync_strv__string (EClient *client,
2794                                        const gchar * const *in_strv,
2795                                        gchar **out_string,
2796                                        GCancellable *cancellable,
2797                                        GError **error,
2798                                        gboolean (*func) (GDBusProxy *proxy,
2799                                                          const gchar * const *in_strv,
2800                                                          gchar **out_string,
2801                                                          GCancellable *cancellable,
2802                                                          GError **error))
2803 {
2804         SYNC_CALL_TEMPLATE (out_string, (proxy, in_strv, out_string, use_cancellable, &local_error))
2805 }
2806
2807 gboolean
2808 e_client_proxy_call_sync_strv__strv (EClient *client,
2809                                      const gchar * const *in_strv,
2810                                      gchar ***out_strv,
2811                                      GCancellable *cancellable,
2812                                      GError **error,
2813                                      gboolean (*func) (GDBusProxy *proxy,
2814                                                        const gchar * const *in_strv,
2815                                                        gchar ***out_strv,
2816                                                        GCancellable *cancellable,
2817                                                        GError **error))
2818 {
2819         SYNC_CALL_TEMPLATE (out_strv, (proxy, in_strv, out_strv, use_cancellable, &local_error))
2820 }
2821
2822 gboolean
2823 e_client_proxy_call_sync_strv__uint (EClient *client,
2824                                      const gchar * const *in_strv,
2825                                      guint *out_uint,
2826                                      GCancellable *cancellable,
2827                                      GError **error,
2828                                      gboolean (*func) (GDBusProxy *proxy,
2829                                                        const gchar * const *in_strv,
2830                                                        guint *out_uint,
2831                                                        GCancellable *cancellable,
2832                                                        GError **error))
2833 {
2834         SYNC_CALL_TEMPLATE (out_uint, (proxy, in_strv, out_uint, use_cancellable, &local_error))
2835 }
2836
2837 gboolean
2838 e_client_proxy_call_sync_uint__void (EClient *client,
2839                                      guint in_uint,
2840                                      GCancellable *cancellable,
2841                                      GError **error,
2842                                      gboolean (*func) (GDBusProxy *proxy,
2843                                                        guint in_uint,
2844                                                        GCancellable *cancellable,
2845                                                        GError **error))
2846 {
2847         SYNC_CALL_TEMPLATE (client, (proxy, in_uint, use_cancellable, &local_error))
2848 }
2849
2850 gboolean
2851 e_client_proxy_call_sync_uint__boolean (EClient *client,
2852                                         guint in_uint,
2853                                         gboolean *out_boolean,
2854                                         GCancellable *cancellable,
2855                                         GError **error,
2856                                         gboolean (*func) (GDBusProxy *proxy,
2857                                                           guint in_uint,
2858                                                           gboolean *out_boolean,
2859                                                           GCancellable *cancellable,
2860                                                           GError **error))
2861 {
2862         SYNC_CALL_TEMPLATE (out_boolean, (proxy, in_uint, out_boolean, use_cancellable, &local_error))
2863 }
2864
2865 gboolean
2866 e_client_proxy_call_sync_uint__string (EClient *client,
2867                                        guint in_uint,
2868                                        gchar **out_string,
2869                                        GCancellable *cancellable,
2870                                        GError **error,
2871                                        gboolean (*func) (GDBusProxy *proxy,
2872                                                          guint in_uint,
2873                                                          gchar **out_string,
2874                                                          GCancellable *cancellable,
2875                                                          GError **error))
2876 {
2877         SYNC_CALL_TEMPLATE (out_string, (proxy, in_uint, out_string, use_cancellable, &local_error))
2878 }
2879
2880 gboolean
2881 e_client_proxy_call_sync_uint__strv (EClient *client,
2882                                      guint in_uint,
2883                                      gchar ***out_strv,
2884                                      GCancellable *cancellable,
2885                                      GError **error,
2886                                      gboolean (*func) (GDBusProxy *proxy,
2887                                                        guint in_uint,
2888                                                        gchar ***out_strv,
2889                                                        GCancellable *cancellable,
2890                                                        GError **error))
2891 {
2892         SYNC_CALL_TEMPLATE (out_strv, (proxy, in_uint, out_strv, use_cancellable, &local_error))
2893 }
2894
2895 gboolean
2896 e_client_proxy_call_sync_uint__uint (EClient *client,
2897                                      guint in_uint,
2898                                      guint *out_uint,
2899                                      GCancellable *cancellable,
2900                                      GError **error,
2901                                      gboolean (*func) (GDBusProxy *proxy,
2902                                                        guint in_uint,
2903                                                        guint *out_uint,
2904                                                        GCancellable *cancellable,
2905                                                        GError **error))
2906 {
2907         SYNC_CALL_TEMPLATE (out_uint, (proxy, in_uint, out_uint, use_cancellable, &local_error))
2908 }
2909
2910 #undef SYNC_CALL_TEMPLATE