/*
* e-book-client.c
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with the program; if not, see
*
*
* Copyright (C) 2011 Red Hat, Inc. (www.redhat.com)
*
*/
#ifdef HAVE_CONFIG_H
#include
#endif
#include
#include
#include
#include
#include "e-book-client.h"
#include "e-contact.h"
#include "e-name-western.h"
#include "e-book-client-view-private.h"
#include "e-gdbus-book.h"
#include "e-gdbus-book-factory.h"
#include "e-gdbus-book-view.h"
#define E_BOOK_CLIENT_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE \
((obj), E_TYPE_BOOK_CLIENT, EBookClientPrivate))
struct _EBookClientPrivate {
/* GDBus data */
GDBusProxy *gdbus_book;
guint gone_signal_id;
};
G_DEFINE_TYPE (EBookClient, e_book_client, E_TYPE_CLIENT)
/*
* Well-known book backend properties:
* @BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS: Retrieves comma-separated list
* of required fields by the backend. Use e_client_util_parse_comma_strings()
* to parse returned string value into a #GSList. These fields are required
* to be filled in for all contacts.
* @BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS: Retrieves comma-separated list
* of supported fields by the backend. Use e_client_util_parse_comma_strings()
* to parse returned string value into a #GSList. These fields can be
* stored for contacts.
* @BOOK_BACKEND_PROPERTY_SUPPORTED_AUTH_METHODS: Retrieves comma-separated list
* of supported authentication methods by the backend.
* Use e_client_util_parse_comma_strings() to parse returned string value
* into a #GSList.
*
* See also: @CLIENT_BACKEND_PROPERTY_OPENED, @CLIENT_BACKEND_PROPERTY_OPENING,
* @CLIENT_BACKEND_PROPERTY_ONLINE, @CLIENT_BACKEND_PROPERTY_READONLY
* @CLIENT_BACKEND_PROPERTY_CACHE_DIR, @CLIENT_BACKEND_PROPERTY_CAPABILITIES
*/
GQuark
e_book_client_error_quark (void)
{
static GQuark q = 0;
if (q == 0)
q = g_quark_from_static_string ("e-book-client-error-quark");
return q;
}
/**
* e_book_client_error_to_string:
*
* FIXME: Document me.
*
* Since: 3.2
**/
const gchar *
e_book_client_error_to_string (EBookClientError code)
{
switch (code) {
case E_BOOK_CLIENT_ERROR_NO_SUCH_BOOK:
return _("No such book");
case E_BOOK_CLIENT_ERROR_CONTACT_NOT_FOUND:
return _("Contact not found");
case E_BOOK_CLIENT_ERROR_CONTACT_ID_ALREADY_EXISTS:
return _("Contact ID already exists");
case E_BOOK_CLIENT_ERROR_NO_SUCH_SOURCE:
return _("No such source");
case E_BOOK_CLIENT_ERROR_NO_SPACE:
return _("No space");
}
return _("Unknown error");
}
/**
* e_book_client_error_create:
* @code: an #EBookClientError code to create
* @custom_msg: custom message to use for the error; can be %NULL
*
* Returns: a new #GError containing an E_BOOK_CLIENT_ERROR of the given
* @code. If the @custom_msg is NULL, then the error message is
* the one returned from e_book_client_error_to_string() for the @code,
* otherwise the given message is used.
*
* Returned pointer should be freed with g_error_free().
*
* Since: 3.2
**/
GError *
e_book_client_error_create (EBookClientError code,
const gchar *custom_msg)
{
return g_error_new_literal (E_BOOK_CLIENT_ERROR, code, custom_msg ? custom_msg : e_book_client_error_to_string (code));
}
/*
* If the specified GError is a remote error, then create a new error
* representing the remote error. If the error is anything else, then
* leave it alone.
*/
static gboolean
unwrap_dbus_error (GError *error,
GError **client_error)
{
#define err(a,b) "org.gnome.evolution.dataserver.AddressBook." a, b
static EClientErrorsList book_errors[] = {
{ err ("Success", -1) },
{ err ("ContactNotFound", E_BOOK_CLIENT_ERROR_CONTACT_NOT_FOUND) },
{ err ("ContactIDAlreadyExists", E_BOOK_CLIENT_ERROR_CONTACT_ID_ALREADY_EXISTS) },
{ err ("NoSuchBook", E_BOOK_CLIENT_ERROR_NO_SUCH_BOOK) },
{ err ("BookRemoved", E_BOOK_CLIENT_ERROR_NO_SUCH_SOURCE) },
{ err ("NoSpace", E_BOOK_CLIENT_ERROR_NO_SPACE) }
}, cl_errors[] = {
{ err ("Busy", E_CLIENT_ERROR_BUSY) },
{ err ("RepositoryOffline", E_CLIENT_ERROR_REPOSITORY_OFFLINE) },
{ err ("OfflineUnavailable", E_CLIENT_ERROR_OFFLINE_UNAVAILABLE) },
{ err ("PermissionDenied", E_CLIENT_ERROR_PERMISSION_DENIED) },
{ err ("AuthenticationFailed", E_CLIENT_ERROR_AUTHENTICATION_FAILED) },
{ err ("AuthenticationRequired", E_CLIENT_ERROR_AUTHENTICATION_REQUIRED) },
{ err ("CouldNotCancel", E_CLIENT_ERROR_COULD_NOT_CANCEL) },
{ err ("InvalidArg", E_CLIENT_ERROR_INVALID_ARG) },
{ err ("NotSupported", E_CLIENT_ERROR_NOT_SUPPORTED) },
{ err ("UnsupportedAuthenticationMethod", E_CLIENT_ERROR_UNSUPPORTED_AUTHENTICATION_METHOD) },
{ err ("TLSNotAvailable", E_CLIENT_ERROR_TLS_NOT_AVAILABLE) },
{ err ("SearchSizeLimitExceeded", E_CLIENT_ERROR_SEARCH_SIZE_LIMIT_EXCEEDED) },
{ err ("SearchTimeLimitExceeded", E_CLIENT_ERROR_SEARCH_TIME_LIMIT_EXCEEDED) },
{ err ("InvalidQuery", E_CLIENT_ERROR_INVALID_QUERY) },
{ err ("QueryRefused", E_CLIENT_ERROR_QUERY_REFUSED) },
{ err ("NotOpened", E_CLIENT_ERROR_NOT_OPENED) },
{ err ("UnsupportedField", E_CLIENT_ERROR_OTHER_ERROR) },
{ err ("InvalidServerVersion", E_CLIENT_ERROR_OTHER_ERROR) },
{ err ("OtherError", E_CLIENT_ERROR_OTHER_ERROR) }
};
#undef err
if (error == NULL)
return TRUE;
if (!e_client_util_unwrap_dbus_error (error, client_error, book_errors, G_N_ELEMENTS (book_errors), E_BOOK_CLIENT_ERROR, TRUE))
e_client_util_unwrap_dbus_error (error, client_error, cl_errors, G_N_ELEMENTS (cl_errors), E_CLIENT_ERROR, FALSE);
return FALSE;
}
static void
set_proxy_gone_error (GError **error)
{
/* do not translate this string, it should ideally never happen */
g_set_error_literal (error, E_CLIENT_ERROR, E_CLIENT_ERROR_DBUS_ERROR, "D-Bus book proxy gone");
}
static guint active_book_clients = 0, book_connection_closed_id = 0;
static EGdbusBookFactory *book_factory_proxy = NULL;
static GStaticRecMutex book_factory_proxy_lock = G_STATIC_REC_MUTEX_INIT;
#define LOCK_FACTORY() g_static_rec_mutex_lock (&book_factory_proxy_lock)
#define UNLOCK_FACTORY() g_static_rec_mutex_unlock (&book_factory_proxy_lock)
static void gdbus_book_factory_proxy_closed_cb (GDBusConnection *connection, gboolean remote_peer_vanished, GError *error, gpointer user_data);
static void
gdbus_book_factory_proxy_disconnect (GDBusConnection *connection)
{
LOCK_FACTORY ();
if (!connection && book_factory_proxy)
connection = g_dbus_proxy_get_connection (G_DBUS_PROXY (book_factory_proxy));
if (connection && book_connection_closed_id) {
g_dbus_connection_signal_unsubscribe (connection, book_connection_closed_id);
g_signal_handlers_disconnect_by_func (connection, gdbus_book_factory_proxy_closed_cb, NULL);
}
if (book_factory_proxy)
g_object_unref (book_factory_proxy);
book_connection_closed_id = 0;
book_factory_proxy = NULL;
UNLOCK_FACTORY ();
}
static void
gdbus_book_factory_proxy_closed_cb (GDBusConnection *connection,
gboolean remote_peer_vanished,
GError *error,
gpointer user_data)
{
GError *err = NULL;
LOCK_FACTORY ();
gdbus_book_factory_proxy_disconnect (connection);
if (error)
unwrap_dbus_error (g_error_copy (error), &err);
if (err) {
g_debug ("GDBus connection is closed%s: %s", remote_peer_vanished ? ", remote peer vanished" : "", err->message);
g_error_free (err);
} else if (active_book_clients) {
g_debug ("GDBus connection is closed%s", remote_peer_vanished ? ", remote peer vanished" : "");
}
UNLOCK_FACTORY ();
}
static void
gdbus_book_factory_connection_gone_cb (GDBusConnection *connection,
const gchar *sender_name,
const gchar *object_path,
const gchar *interface_name,
const gchar *signal_name,
GVariant *parameters,
gpointer user_data)
{
/* signal subscription takes care of correct parameters,
* thus just do what is to be done here */
gdbus_book_factory_proxy_closed_cb (connection, TRUE, NULL, user_data);
}
static gboolean
gdbus_book_factory_activate (GError **error)
{
GDBusConnection *connection;
LOCK_FACTORY ();
if (G_LIKELY (book_factory_proxy)) {
UNLOCK_FACTORY ();
return TRUE;
}
book_factory_proxy = e_gdbus_book_factory_proxy_new_for_bus_sync (
G_BUS_TYPE_SESSION,
G_DBUS_PROXY_FLAGS_NONE,
ADDRESS_BOOK_DBUS_SERVICE_NAME,
"/org/gnome/evolution/dataserver/AddressBookFactory",
NULL,
error);
if (!book_factory_proxy) {
UNLOCK_FACTORY ();
return FALSE;
}
connection = g_dbus_proxy_get_connection (G_DBUS_PROXY (book_factory_proxy));
book_connection_closed_id = g_dbus_connection_signal_subscribe (
connection,
NULL, /* sender */
"org.freedesktop.DBus", /* interface */
"NameOwnerChanged", /* member */
"/org/freedesktop/DBus", /* object_path */
"org.gnome.evolution.dataserver.AddressBook", /* arg0 */
G_DBUS_SIGNAL_FLAGS_NONE,
gdbus_book_factory_connection_gone_cb, NULL, NULL);
g_signal_connect (connection, "closed", G_CALLBACK (gdbus_book_factory_proxy_closed_cb), NULL);
UNLOCK_FACTORY ();
return TRUE;
}
static void gdbus_book_client_disconnect (EBookClient *client);
/*
* Called when the addressbook server dies.
*/
static void
gdbus_book_client_closed_cb (GDBusConnection *connection,
gboolean remote_peer_vanished,
GError *error,
EBookClient *client)
{
GError *err = NULL;
g_assert (E_IS_BOOK_CLIENT (client));
if (error)
unwrap_dbus_error (g_error_copy (error), &err);
if (err) {
g_debug (G_STRLOC ": EBookClient GDBus connection is closed%s: %s", remote_peer_vanished ? ", remote peer vanished" : "", err->message);
g_error_free (err);
} else {
g_debug (G_STRLOC ": EBookClient GDBus connection is closed%s", remote_peer_vanished ? ", remote peer vanished" : "");
}
gdbus_book_client_disconnect (client);
e_client_emit_backend_died (E_CLIENT (client));
}
static void
gdbus_book_client_connection_gone_cb (GDBusConnection *connection,
const gchar *sender_name,
const gchar *object_path,
const gchar *interface_name,
const gchar *signal_name,
GVariant *parameters,
gpointer user_data)
{
/* signal subscription takes care of correct parameters,
* thus just do what is to be done here */
gdbus_book_client_closed_cb (connection, TRUE, NULL, user_data);
}
static void
gdbus_book_client_disconnect (EBookClient *client)
{
g_return_if_fail (E_IS_BOOK_CLIENT (client));
/* Ensure that everything relevant is NULL */
LOCK_FACTORY ();
if (client->priv->gdbus_book) {
GDBusConnection *connection = g_dbus_proxy_get_connection (G_DBUS_PROXY (client->priv->gdbus_book));
g_signal_handlers_disconnect_by_func (connection, gdbus_book_client_closed_cb, client);
g_dbus_connection_signal_unsubscribe (connection, client->priv->gone_signal_id);
client->priv->gone_signal_id = 0;
e_gdbus_book_call_close_sync (client->priv->gdbus_book, NULL, NULL);
g_object_unref (client->priv->gdbus_book);
client->priv->gdbus_book = NULL;
}
UNLOCK_FACTORY ();
}
static void
backend_error_cb (EGdbusBook *object,
const gchar *message,
EBookClient *client)
{
g_return_if_fail (E_IS_BOOK_CLIENT (client));
g_return_if_fail (message != NULL);
e_client_emit_backend_error (E_CLIENT (client), message);
}
static void
readonly_cb (EGdbusBook *object,
gboolean readonly,
EBookClient *client)
{
g_return_if_fail (E_IS_BOOK_CLIENT (client));
e_client_set_readonly (E_CLIENT (client), readonly);
}
static void
online_cb (EGdbusBook *object,
gboolean is_online,
EBookClient *client)
{
g_return_if_fail (E_IS_BOOK_CLIENT (client));
e_client_set_online (E_CLIENT (client), is_online);
}
static void
opened_cb (EGdbusBook *object,
const gchar * const *error_strv,
EBookClient *client)
{
GError *error = NULL;
g_return_if_fail (E_IS_BOOK_CLIENT (client));
g_return_if_fail (error_strv != NULL);
g_return_if_fail (e_gdbus_templates_decode_error (error_strv, &error));
e_client_emit_opened (E_CLIENT (client), error);
if (error)
g_error_free (error);
}
static void
backend_property_changed_cb (EGdbusBook *object,
const gchar * const *name_value_strv,
EBookClient *client)
{
gchar *prop_name = NULL, *prop_value = NULL;
g_return_if_fail (E_IS_BOOK_CLIENT (client));
g_return_if_fail (name_value_strv != NULL);
g_return_if_fail (e_gdbus_templates_decode_two_strings (name_value_strv, &prop_name, &prop_value));
g_return_if_fail (prop_name != NULL);
g_return_if_fail (*prop_name);
g_return_if_fail (prop_value != NULL);
e_client_emit_backend_property_changed (E_CLIENT (client), prop_name, prop_value);
g_free (prop_name);
g_free (prop_value);
}
/*
* Converts a GSList of EContact objects into a NULL-terminated array of
* valid UTF-8 vcard strings, suitable for sending over DBus.
*/
static gchar **
contact_slist_to_utf8_vcard_array (GSList *contacts)
{
gchar **array;
const GSList *l;
gint i = 0;
array = g_new0 (gchar *, g_slist_length (contacts) + 1);
for (l = contacts; l != NULL; l = l->next) {
gchar *vcard = e_vcard_to_string (E_VCARD (l->data), EVC_FORMAT_VCARD_30);
array[i++] = e_util_utf8_make_valid (vcard);
g_free (vcard);
}
return array;
}
/**
* e_book_client_new:
* @source: An #ESource pointer
* @error: A #GError pointer
*
* Creates a new #EBookClient corresponding to the given source. There are
* only two operations that are valid on this book at this point:
* e_client_open(), and e_client_remove().
*
* Returns: a new but unopened #EBookClient.
*
* Since: 3.2
**/
EBookClient *
e_book_client_new (ESource *source,
GError **error)
{
EBookClient *client;
GError *err = NULL;
GDBusConnection *connection;
const gchar *uid;
gchar *path = NULL;
g_return_val_if_fail (source != NULL, NULL);
g_return_val_if_fail (E_IS_SOURCE (source), NULL);
LOCK_FACTORY ();
if (!gdbus_book_factory_activate (&err)) {
UNLOCK_FACTORY ();
if (err) {
unwrap_dbus_error (err, &err);
g_warning ("%s: Failed to run book factory: %s", G_STRFUNC, err->message);
g_propagate_error (error, err);
} else {
g_warning ("%s: Failed to run book factory: Unknown error", G_STRFUNC);
g_set_error_literal (error, E_CLIENT_ERROR, E_CLIENT_ERROR_DBUS_ERROR, _("Failed to run book factory"));
}
return NULL;
}
uid = e_source_get_uid (source);
client = g_object_new (E_TYPE_BOOK_CLIENT, "source", source, NULL);
UNLOCK_FACTORY ();
if (!e_gdbus_book_factory_call_get_book_sync (G_DBUS_PROXY (book_factory_proxy), uid, &path, NULL, &err)) {
unwrap_dbus_error (err, &err);
g_warning ("%s: Cannot get book from factory: %s", G_STRFUNC, err ? err->message : "[no error]");
if (err)
g_propagate_error (error, err);
g_object_unref (client);
return NULL;
}
client->priv->gdbus_book = G_DBUS_PROXY (
e_gdbus_book_proxy_new_sync (g_dbus_proxy_get_connection (G_DBUS_PROXY (book_factory_proxy)),
G_DBUS_PROXY_FLAGS_NONE,
ADDRESS_BOOK_DBUS_SERVICE_NAME,
path,
NULL,
&err));
if (!client->priv->gdbus_book) {
g_free (path);
unwrap_dbus_error (err, &err);
g_warning ("%s: Cannot create cal proxy: %s", G_STRFUNC, err ? err->message : "Unknown error");
if (err)
g_propagate_error (error, err);
g_object_unref (client);
return NULL;
}
g_free (path);
connection = g_dbus_proxy_get_connection (G_DBUS_PROXY (client->priv->gdbus_book));
client->priv->gone_signal_id = g_dbus_connection_signal_subscribe (
connection,
"org.freedesktop.DBus", /* sender */
"org.freedesktop.DBus", /* interface */
"NameOwnerChanged", /* member */
"/org/freedesktop/DBus", /* object_path */
"org.gnome.evolution.dataserver.AddressBook", /* arg0 */
G_DBUS_SIGNAL_FLAGS_NONE,
gdbus_book_client_connection_gone_cb, client, NULL);
g_signal_connect (connection, "closed", G_CALLBACK (gdbus_book_client_closed_cb), client);
g_signal_connect (client->priv->gdbus_book, "backend_error", G_CALLBACK (backend_error_cb), client);
g_signal_connect (client->priv->gdbus_book, "readonly", G_CALLBACK (readonly_cb), client);
g_signal_connect (client->priv->gdbus_book, "online", G_CALLBACK (online_cb), client);
g_signal_connect (client->priv->gdbus_book, "opened", G_CALLBACK (opened_cb), client);
g_signal_connect (client->priv->gdbus_book, "backend-property-changed", G_CALLBACK (backend_property_changed_cb), client);
return client;
}
#define SELF_UID_PATH_ID "org.gnome.evolution-data-server.addressbook"
#define SELF_UID_KEY "self-contact-uid"
static EContact *
make_me_card (void)
{
GString *vcard;
const gchar *s;
EContact *contact;
vcard = g_string_new ("BEGIN:VCARD\nVERSION:3.0\n");
s = g_get_user_name ();
if (s)
g_string_append_printf (vcard, "NICKNAME:%s\n", s);
s = g_get_real_name ();
if (s && strcmp (s, "Unknown") != 0) {
ENameWestern *western;
g_string_append_printf (vcard, "FN:%s\n", s);
western = e_name_western_parse (s);
g_string_append_printf (
vcard, "N:%s;%s;%s;%s;%s\n",
western->last ? western->last : "",
western->first ? western->first : "",
western->middle ? western->middle : "",
western->prefix ? western->prefix : "",
western->suffix ? western->suffix : "");
e_name_western_free (western);
}
g_string_append (vcard, "END:VCARD");
contact = e_contact_new_from_vcard (vcard->str);
g_string_free (vcard, TRUE);
return contact;
}
/**
* e_book_client_get_self:
* @registry: an #ESourceRegistry
* @contact: (out): an #EContact pointer to set
* @client: (out): an #EBookClient pointer to set
* @error: a #GError to set on failure
*
* Get the #EContact referring to the user of the address book
* and set it in @contact and @client.
*
* Returns: %TRUE if successful, otherwise %FALSE.
*
* Since: 3.2
**/
gboolean
e_book_client_get_self (ESourceRegistry *registry,
EContact **contact,
EBookClient **client,
GError **error)
{
ESource *source;
GError *local_error = NULL;
GSettings *settings;
gchar *uid;
g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), FALSE);
g_return_val_if_fail (contact != NULL, FALSE);
g_return_val_if_fail (E_IS_BOOK_CLIENT (client), FALSE);
source = e_source_registry_ref_builtin_address_book (registry);
*client = e_book_client_new (source, &local_error);
g_object_unref (source);
if (!*client) {
g_propagate_error (error, local_error);
return FALSE;
}
if (!e_client_open_sync (E_CLIENT (*client), FALSE, NULL, &local_error)) {
g_object_unref (*client);
*client = NULL;
g_propagate_error (error, local_error);
return FALSE;
}
settings = g_settings_new (SELF_UID_PATH_ID);
uid = g_settings_get_string (settings, SELF_UID_KEY);
g_object_unref (settings);
if (uid) {
gboolean got;
/* Don't care about errors because we'll create a new card on failure */
got = e_book_client_get_contact_sync (*client, uid, contact, NULL, NULL);
g_free (uid);
if (got)
return TRUE;
}
uid = NULL;
*contact = make_me_card ();
if (!e_book_client_add_contact_sync (*client, *contact, &uid, NULL, &local_error)) {
g_object_unref (*client);
*client = NULL;
g_object_unref (*contact);
*contact = NULL;
g_propagate_error (error, local_error);
return FALSE;
}
if (uid) {
e_contact_set (*contact, E_CONTACT_UID, uid);
g_free (uid);
}
e_book_client_set_self (*client, *contact, NULL);
return TRUE;
}
/**
* e_book_client_set_self:
* @client: an #EBookClient
* @contact: an #EContact
* @error: a #GError to set on failure
*
* Specify that @contact residing in @client is the #EContact that
* refers to the user of the address book.
*
* Returns: %TRUE if successful, %FALSE otherwise.
*
* Since: 3.2
**/
gboolean
e_book_client_set_self (EBookClient *client,
EContact *contact,
GError **error)
{
GSettings *settings;
g_return_val_if_fail (E_IS_BOOK_CLIENT (client), FALSE);
g_return_val_if_fail (contact != NULL, FALSE);
g_return_val_if_fail (e_contact_get_const (contact, E_CONTACT_UID) != NULL, FALSE);
settings = g_settings_new (SELF_UID_PATH_ID);
g_settings_set_string (settings, SELF_UID_KEY, e_contact_get_const (contact, E_CONTACT_UID));
g_object_unref (settings);
return TRUE;
}
/**
* e_book_client_is_self:
* @contact: an #EContact
*
* Check if @contact is the user of the address book.
*
* Returns: %TRUE if @contact is the user, %FALSE otherwise.
*
* Since: 3.2
**/
gboolean
e_book_client_is_self (EContact *contact)
{
static GSettings *settings;
static GMutex mutex;
gchar *uid;
gboolean is_self;
g_return_val_if_fail (contact && E_IS_CONTACT (contact), FALSE);
/*
* It would be nice to attach this instance to the EBookClient
* instance so that it can be free again later, but
* unfortunately the API doesn't allow that.
*/
g_mutex_lock (&mutex);
if (!settings)
settings = g_settings_new (SELF_UID_PATH_ID);
uid = g_settings_get_string (settings, SELF_UID_KEY);
g_mutex_unlock (&mutex);
is_self = uid && !g_strcmp0 (uid, e_contact_get_const (contact, E_CONTACT_UID));
g_free (uid);
return is_self;
}
static gboolean
book_client_get_backend_property_from_cache_finish (EClient *client,
GAsyncResult *result,
gchar **prop_value,
GError **error)
{
GSimpleAsyncResult *simple;
GError *local_error = NULL;
g_return_val_if_fail (E_IS_BOOK_CLIENT (client), FALSE);
g_return_val_if_fail (result != NULL, FALSE);
g_return_val_if_fail (prop_value != NULL, FALSE);
g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (client), book_client_get_backend_property_from_cache_finish), FALSE);
simple = G_SIMPLE_ASYNC_RESULT (result);
if (g_simple_async_result_propagate_error (simple, &local_error)) {
e_client_unwrap_dbus_error (client, local_error, error);
return FALSE;
}
*prop_value = g_strdup (g_simple_async_result_get_op_res_gpointer (simple));
return *prop_value != NULL;
}
static void
book_client_get_backend_property (EClient *client,
const gchar *prop_name,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
gchar *prop_value;
prop_value = e_client_get_backend_property_from_cache (client, prop_name);
if (prop_value) {
e_client_finish_async_without_dbus (client, cancellable, callback, user_data, book_client_get_backend_property_from_cache_finish, prop_value, g_free);
} else {
e_client_proxy_call_string_with_res_op_data (
client, prop_name, cancellable, callback, user_data, book_client_get_backend_property, prop_name,
e_gdbus_book_call_get_backend_property,
NULL, NULL, e_gdbus_book_call_get_backend_property_finish, NULL, NULL);
}
}
static gboolean
book_client_get_backend_property_finish (EClient *client,
GAsyncResult *result,
gchar **prop_value,
GError **error)
{
gchar *str = NULL;
gboolean res;
g_return_val_if_fail (prop_value != NULL, FALSE);
if (g_simple_async_result_get_source_tag (G_SIMPLE_ASYNC_RESULT (result)) == book_client_get_backend_property_from_cache_finish) {
res = book_client_get_backend_property_from_cache_finish (client, result, &str, error);
} else {
res = e_client_proxy_call_finish_string (client, result, &str, error, book_client_get_backend_property);
if (res && str) {
const gchar *prop_name = g_object_get_data (G_OBJECT (result), "res-op-data");
if (prop_name && *prop_name)
e_client_update_backend_property_cache (client, prop_name, str);
}
}
*prop_value = str;
return res;
}
static gboolean
book_client_get_backend_property_sync (EClient *client,
const gchar *prop_name,
gchar **prop_value,
GCancellable *cancellable,
GError **error)
{
EBookClient *book_client;
gchar *prop_val;
gboolean res;
g_return_val_if_fail (E_IS_BOOK_CLIENT (client), FALSE);
book_client = E_BOOK_CLIENT (client);
if (!book_client->priv->gdbus_book) {
set_proxy_gone_error (error);
return FALSE;
}
prop_val = e_client_get_backend_property_from_cache (client, prop_name);
if (prop_val) {
g_return_val_if_fail (prop_value != NULL, FALSE);
*prop_value = prop_val;
return TRUE;
}
res = e_client_proxy_call_sync_string__string (client, prop_name, prop_value, cancellable, error, e_gdbus_book_call_get_backend_property_sync);
if (res && prop_value)
e_client_update_backend_property_cache (client, prop_name, *prop_value);
return res;
}
static void
book_client_set_backend_property (EClient *client,
const gchar *prop_name,
const gchar *prop_value,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
gchar **prop_name_value;
prop_name_value = e_gdbus_book_encode_set_backend_property (prop_name, prop_value);
e_client_proxy_call_strv (
client, (const gchar * const *) prop_name_value, cancellable, callback, user_data, book_client_set_backend_property,
e_gdbus_book_call_set_backend_property,
e_gdbus_book_call_set_backend_property_finish, NULL, NULL, NULL, NULL);
g_strfreev (prop_name_value);
}
static gboolean
book_client_set_backend_property_finish (EClient *client,
GAsyncResult *result,
GError **error)
{
return e_client_proxy_call_finish_void (client, result, error, book_client_set_backend_property);
}
static gboolean
book_client_set_backend_property_sync (EClient *client,
const gchar *prop_name,
const gchar *prop_value,
GCancellable *cancellable,
GError **error)
{
EBookClient *book_client;
gboolean res;
gchar **prop_name_value;
g_return_val_if_fail (E_IS_BOOK_CLIENT (client), FALSE);
book_client = E_BOOK_CLIENT (client);
if (!book_client->priv->gdbus_book) {
set_proxy_gone_error (error);
return FALSE;
}
prop_name_value = e_gdbus_book_encode_set_backend_property (prop_name, prop_value);
res = e_client_proxy_call_sync_strv__void (client, (const gchar * const *) prop_name_value, cancellable, error, e_gdbus_book_call_set_backend_property_sync);
g_strfreev (prop_name_value);
return res;
}
static void
book_client_open (EClient *client,
gboolean only_if_exists,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
e_client_proxy_call_boolean (
client, only_if_exists, cancellable, callback, user_data, book_client_open,
e_gdbus_book_call_open,
e_gdbus_book_call_open_finish, NULL, NULL, NULL, NULL);
}
static gboolean
book_client_open_finish (EClient *client,
GAsyncResult *result,
GError **error)
{
return e_client_proxy_call_finish_void (client, result, error, book_client_open);
}
static gboolean
book_client_open_sync (EClient *client,
gboolean only_if_exists,
GCancellable *cancellable,
GError **error)
{
EBookClient *book_client;
g_return_val_if_fail (E_IS_BOOK_CLIENT (client), FALSE);
book_client = E_BOOK_CLIENT (client);
if (!book_client->priv->gdbus_book) {
set_proxy_gone_error (error);
return FALSE;
}
return e_client_proxy_call_sync_boolean__void (client, only_if_exists, cancellable, error, e_gdbus_book_call_open_sync);
}
static void
book_client_refresh (EClient *client,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
e_client_proxy_call_void (
client, cancellable, callback, user_data, book_client_refresh,
e_gdbus_book_call_refresh,
e_gdbus_book_call_refresh_finish, NULL, NULL, NULL, NULL);
}
static gboolean
book_client_refresh_finish (EClient *client,
GAsyncResult *result,
GError **error)
{
return e_client_proxy_call_finish_void (client, result, error, book_client_refresh);
}
static gboolean
book_client_refresh_sync (EClient *client,
GCancellable *cancellable,
GError **error)
{
EBookClient *book_client;
g_return_val_if_fail (E_IS_BOOK_CLIENT (client), FALSE);
book_client = E_BOOK_CLIENT (client);
if (!book_client->priv->gdbus_book) {
set_proxy_gone_error (error);
return FALSE;
}
return e_client_proxy_call_sync_void__void (client, cancellable, error, e_gdbus_book_call_refresh_sync);
}
/**
* e_book_client_add_contact:
* @client: an #EBookClient
* @contact: an #EContact
* @cancellable: a #GCancellable; can be %NULL
* @callback: callback to call when a result is ready
* @user_data: user data for the @callback
*
* Adds @contact to @client.
* The call is finished by e_book_client_add_contact_finish()
* from the @callback.
*
* Since: 3.2
**/
void
e_book_client_add_contact (EBookClient *client,
/* const */ EContact *contact,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
gchar *vcard, *gdbus_vcard = NULL;
const gchar *strv[2];
g_return_if_fail (contact != NULL);
g_return_if_fail (E_IS_CONTACT (contact));
vcard = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30);
strv[0] = e_util_ensure_gdbus_string (vcard, &gdbus_vcard);
strv[1] = NULL;
g_return_if_fail (strv[0] != NULL);
e_client_proxy_call_strv (
E_CLIENT (client), strv, cancellable, callback, user_data, e_book_client_add_contact,
e_gdbus_book_call_add_contacts,
NULL, NULL, NULL, e_gdbus_book_call_add_contacts_finish, NULL);
g_free (vcard);
g_free (gdbus_vcard);
}
/**
* e_book_client_add_contact_finish:
* @client: an #EBookClient
* @result: a #GAsyncResult
* @added_uid: (out): UID of a newly added contact; can be %NULL
* @error: (out): a #GError to set an error, if any
*
* Finishes previous call of e_book_client_add_contact() and
* sets @added_uid to a UID of a newly added contact.
* This string should be freed with g_free().
*
* Note: This is not modifying original #EContact.
*
* Returns: %TRUE if successful, %FALSE otherwise.
*
* Since: 3.2
**/
gboolean
e_book_client_add_contact_finish (EBookClient *client,
GAsyncResult *result,
gchar **added_uid,
GError **error)
{
gboolean res;
gchar **out_uids = NULL;
res = e_client_proxy_call_finish_strv (E_CLIENT (client), result, &out_uids, error, e_book_client_add_contact);
if (res && out_uids && added_uid) {
*added_uid = g_strdup (out_uids[0]);
} else {
if (added_uid)
*added_uid = NULL;
}
g_strfreev (out_uids);
return res;
}
/**
* e_book_client_add_contact_sync:
* @client: an #EBookClient
* @contact: an #EContact
* @added_uid: (out): UID of a newly added contact; can be %NULL
* @cancellable: a #GCancellable; can be %NULL
* @error: (out): a #GError to set an error, if any
*
* Adds @contact to @client and
* sets @added_uid to a UID of a newly added contact.
* This string should be freed with g_free().
*
* Note: This is not modifying original @contact, thus if it's needed,
* then use e_contact_set (contact, E_CONTACT_UID, new_uid).
*
* Returns: %TRUE if successful, %FALSE otherwise.
*
* Since: 3.2
**/
gboolean
e_book_client_add_contact_sync (EBookClient *client,
/* const */ EContact *contact,
gchar **added_uid,
GCancellable *cancellable,
GError **error)
{
gboolean res;
gchar *vcard, *gdbus_vcard = NULL, **out_uids = NULL;
const gchar *strv[2];
g_return_val_if_fail (E_IS_BOOK_CLIENT (client), FALSE);
if (!client->priv->gdbus_book) {
set_proxy_gone_error (error);
return FALSE;
}
vcard = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30);
strv[0] = e_util_ensure_gdbus_string (vcard, &gdbus_vcard);
strv[1] = NULL;
g_return_val_if_fail (strv[0] != NULL, FALSE);
res = e_client_proxy_call_sync_strv__strv (E_CLIENT (client), strv, &out_uids, cancellable, error, e_gdbus_book_call_add_contacts_sync);
if (res && out_uids && added_uid) {
*added_uid = g_strdup (out_uids[0]);
} else {
if (added_uid)
*added_uid = NULL;
}
g_strfreev (out_uids);
g_free (vcard);
g_free (gdbus_vcard);
return res;
}
/**
* e_book_client_add_contacts:
* @client: an #EBookClient
* @contacts: (element-type EContact): a #GSList of #EContact objects to add
* @cancellable: (allow-none): a #GCancellable; can be %NULL
* @callback: callback to call when a result is ready
* @user_data: user data for the @callback
*
* Adds @contacts to @client.
* The call is finished by e_book_client_add_contacts_finish()
* from the @callback.
*
* Since: 3.4
**/
void
e_book_client_add_contacts (EBookClient *client,
/* const */ GSList *contacts,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
gchar **array;
g_return_if_fail (contacts != NULL);
array = contact_slist_to_utf8_vcard_array (contacts);
e_client_proxy_call_strv (
E_CLIENT (client), (const gchar * const *) array, cancellable, callback, user_data, e_book_client_add_contacts,
e_gdbus_book_call_add_contacts,
NULL, NULL, NULL, e_gdbus_book_call_add_contacts_finish, NULL);
g_strfreev (array);
}
/**
* e_book_client_add_contacts_finish:
* @client: an #EBookClient
* @result: a #GAsyncResult
* @added_uids: (out) (element-type utf8) (allow-none): UIDs of newly added
* contacts; can be %NULL
* @error: (out): a #GError to set an error, if any
*
* Finishes previous call of e_book_client_add_contacts() and
* sets @added_uids to the UIDs of newly added contacts if successful.
* This #GSList should be freed with e_client_util_free_string_slist().
*
* If any of the contacts cannot be inserted, all of the insertions will be
* reverted and this method will return %FALSE.
*
* Note: This is not modifying original #EContact objects.
*
* Returns: %TRUE if successful, %FALSE otherwise.
*
* Since: 3.4
**/
gboolean
e_book_client_add_contacts_finish (EBookClient *client,
GAsyncResult *result,
GSList **added_uids,
GError **error)
{
gboolean res;
gchar **out_uids = NULL;
res = e_client_proxy_call_finish_strv (E_CLIENT (client), result, &out_uids, error, e_book_client_add_contacts);
if (res && out_uids && added_uids) {
*added_uids = e_client_util_strv_to_slist ((const gchar * const*) out_uids);
} else {
if (added_uids)
*added_uids = NULL;
}
g_strfreev (out_uids);
return res;
}
/**
* e_book_client_add_contacts_sync:
* @client: an #EBookClient
* @contacts: (element-type EContact): a #GSList of #EContact objects to add
* @added_uids: (out) (element-type utf8) (allow-none): UIDs of newly added
* contacts; can be %NULL
* @cancellable: a #GCancellable; can be %NULL
* @error: (out): a #GError to set an error, if any
*
* Adds @contacts to @client and
* sets @added_uids to the UIDs of newly added contacts if successful.
* This #GSList should be freed with e_client_util_free_string_slist().
*
* If any of the contacts cannot be inserted, all of the insertions will be
* reverted and this method will return %FALSE.
*
* Note: This is not modifying original @contacts, thus if it's needed,
* then use e_contact_set (contact, E_CONTACT_UID, new_uid).
*
* Returns: %TRUE if successful, %FALSE otherwise.
*
* Since: 3.4
**/
gboolean
e_book_client_add_contacts_sync (EBookClient *client,
/* const */ GSList *contacts,
GSList **added_uids,
GCancellable *cancellable,
GError **error)
{
gboolean res;
gchar **array, **out_uids = NULL;
g_return_val_if_fail (E_IS_BOOK_CLIENT (client), FALSE);
if (!client->priv->gdbus_book) {
set_proxy_gone_error (error);
return FALSE;
}
array = contact_slist_to_utf8_vcard_array (contacts);
res = e_client_proxy_call_sync_strv__strv (E_CLIENT (client), (const gchar * const *) array, &out_uids, cancellable, error, e_gdbus_book_call_add_contacts_sync);
if (res && out_uids && added_uids) {
*added_uids = e_client_util_strv_to_slist ((const gchar * const*) out_uids);
} else {
if (added_uids)
*added_uids = NULL;
}
g_strfreev (out_uids);
g_strfreev (array);
return res;
}
/**
* e_book_client_modify_contact:
* @client: an #EBookClient
* @contact: an #EContact
* @cancellable: a #GCancellable; can be %NULL
* @callback: callback to call when a result is ready
* @user_data: user data for the @callback
*
* Applies the changes made to @contact to the stored version in @client.
* The call is finished by e_book_client_modify_contact_finish()
* from the @callback.
*
* Since: 3.2
**/
void
e_book_client_modify_contact (EBookClient *client,
/* const */ EContact *contact,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
gchar *vcard, *gdbus_vcard = NULL;
const gchar *strv[2];
g_return_if_fail (contact != NULL);
g_return_if_fail (E_IS_CONTACT (contact));
vcard = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30);
strv[0] = e_util_ensure_gdbus_string (vcard, &gdbus_vcard);
strv[1] = NULL;
g_return_if_fail (strv[0] != NULL);
e_client_proxy_call_strv (
E_CLIENT (client), strv, cancellable, callback, user_data, e_book_client_modify_contact,
e_gdbus_book_call_modify_contacts,
e_gdbus_book_call_modify_contacts_finish, NULL, NULL, NULL, NULL);
g_free (vcard);
g_free (gdbus_vcard);
}
/**
* e_book_client_modify_contact_finish:
* @client: an #EBookClient
* @result: a #GAsyncResult
* @error: (out): a #GError to set an error, if any
*
* Finishes previous call of e_book_client_modify_contact().
*
* Returns: %TRUE if successful, %FALSE otherwise.
*
* Since: 3.2
**/
gboolean
e_book_client_modify_contact_finish (EBookClient *client,
GAsyncResult *result,
GError **error)
{
return e_client_proxy_call_finish_void (E_CLIENT (client), result, error, e_book_client_modify_contact);
}
/**
* e_book_client_modify_contact_sync:
* @client: an #EBookClient
* @contact: an #EContact
* @cancellable: a #GCancellable; can be %NULL
* @error: (out): a #GError to set an error, if any
*
* Applies the changes made to @contact to the stored version in @client.
*
* Returns: %TRUE if successful, %FALSE otherwise.
*
* Since: 3.2
**/
gboolean
e_book_client_modify_contact_sync (EBookClient *client,
/* const */ EContact *contact,
GCancellable *cancellable,
GError **error)
{
gboolean res;
gchar *vcard, *gdbus_vcard = NULL;
const gchar *strv[2];
g_return_val_if_fail (E_IS_BOOK_CLIENT (client), FALSE);
if (!client->priv->gdbus_book) {
set_proxy_gone_error (error);
return FALSE;
}
vcard = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30);
strv[0] = e_util_ensure_gdbus_string (vcard, &gdbus_vcard);
strv[1] = NULL;
g_return_val_if_fail (strv[0] != NULL, FALSE);
res = e_client_proxy_call_sync_strv__void (E_CLIENT (client), strv, cancellable, error, e_gdbus_book_call_modify_contacts_sync);
g_free (vcard);
g_free (gdbus_vcard);
return res;
}
/**
* e_book_client_modify_contacts:
* @client: an #EBookClient
* @contacts: (element-type EContact): a #GSList of #EContact objects
* @cancellable: (allow-none): a #GCancellable; can be %NULL
* @callback: callback to call when a result is ready
* @user_data: user data for the @callback
*
* Applies the changes made to @contacts to the stored versions in @client.
* The call is finished by e_book_client_modify_contacts_finish()
* from the @callback.
*
* Since: 3.4
**/
void
e_book_client_modify_contacts (EBookClient *client,
/* const */ GSList *contacts,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
gchar **array;
g_return_if_fail (contacts != NULL);
array = contact_slist_to_utf8_vcard_array (contacts);
e_client_proxy_call_strv (
E_CLIENT (client), (const gchar * const *) array, cancellable, callback, user_data, e_book_client_modify_contacts,
e_gdbus_book_call_modify_contacts,
e_gdbus_book_call_modify_contacts_finish, NULL, NULL, NULL, NULL);
g_strfreev (array);
}
/**
* e_book_client_modify_contacts_finish:
* @client: an #EBookClient
* @result: a #GAsyncResult
* @error: (out): a #GError to set an error, if any
*
* Finishes previous call of e_book_client_modify_contacts().
*
* Returns: %TRUE if successful, %FALSE otherwise.
*
* Since: 3.4
**/
gboolean
e_book_client_modify_contacts_finish (EBookClient *client,
GAsyncResult *result,
GError **error)
{
return e_client_proxy_call_finish_void (E_CLIENT (client), result, error, e_book_client_modify_contacts);
}
/**
* e_book_client_modify_contacts_sync:
* @client: an #EBookClient
* @contacts: (element-type EContact): a #GSList of #EContact objects
* @cancellable: (allow-none): a #GCancellable; can be %NULL
* @error: (out): a #GError to set an error, if any
*
* Applies the changes made to @contacts to the stored versions in @client.
*
* Returns: %TRUE if successful, %FALSE otherwise.
*
* Since: 3.4
**/
gboolean
e_book_client_modify_contacts_sync (EBookClient *client,
/* const */ GSList *contacts,
GCancellable *cancellable,
GError **error)
{
gboolean res;
gchar **array;
g_return_val_if_fail (E_IS_BOOK_CLIENT (client), FALSE);
g_return_val_if_fail (contacts != NULL, FALSE);
if (!client->priv->gdbus_book) {
set_proxy_gone_error (error);
return FALSE;
}
array = contact_slist_to_utf8_vcard_array (contacts);
res = e_client_proxy_call_sync_strv__void (E_CLIENT (client), (const gchar * const *) array, cancellable, error, e_gdbus_book_call_modify_contacts_sync);
g_strfreev (array);
return res;
}
/**
* e_book_client_remove_contact:
* @client: an #EBookClient
* @contact: an #EContact
* @cancellable: a #GCancellable; can be %NULL
* @callback: callback to call when a result is ready
* @user_data: user data for the @callback
*
* Removes @contact from the @client.
* The call is finished by e_book_client_remove_contact_finish()
* from the @callback.
*
* Since: 3.2
**/
void
e_book_client_remove_contact (EBookClient *client,
/* const */ EContact *contact,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
const gchar *uid, *safe_uid;
const gchar *strv[2];
gchar *gdbus_uid = NULL;
g_return_if_fail (contact != NULL);
g_return_if_fail (E_IS_CONTACT (contact));
uid = e_contact_get_const ( E_CONTACT (contact), E_CONTACT_UID);
g_return_if_fail (uid != NULL);
safe_uid = e_util_ensure_gdbus_string (uid, &gdbus_uid);
g_return_if_fail (safe_uid != NULL);
strv[0] = safe_uid;
strv[1] = NULL;
e_client_proxy_call_strv (
E_CLIENT (client), strv, cancellable, callback, user_data, e_book_client_remove_contact,
e_gdbus_book_call_remove_contacts,
e_gdbus_book_call_remove_contacts_finish, NULL, NULL, NULL, NULL);
g_free (gdbus_uid);
}
/**
* e_book_client_remove_contact_finish:
* @client: an #EBookClient
* @result: a #GAsyncResult
* @error: (out): a #GError to set an error, if any
*
* Finishes previous call of e_book_client_remove_contact().
*
* Returns: %TRUE if successful, %FALSE otherwise.
*
* Since: 3.2
**/
gboolean
e_book_client_remove_contact_finish (EBookClient *client,
GAsyncResult *result,
GError **error)
{
return e_client_proxy_call_finish_void (E_CLIENT (client), result, error, e_book_client_remove_contact);
}
/**
* e_book_client_remove_contact_sync:
* @client: an #EBookClient
* @contact: an #EContact
* @cancellable: a #GCancellable; can be %NULL
* @error: (out): a #GError to set an error, if any
*
* Removes @contact from the @client.
*
* Returns: %TRUE if successful, %FALSE otherwise.
*
* Since: 3.2
**/
gboolean
e_book_client_remove_contact_sync (EBookClient *client,
/* const */ EContact *contact,
GCancellable *cancellable,
GError **error)
{
gboolean res;
const gchar *strv[2];
const gchar *uid, *safe_uid;
gchar *gdbus_uid = NULL;
g_return_val_if_fail (E_IS_BOOK_CLIENT (client), FALSE);
g_return_val_if_fail (E_IS_CONTACT (contact), FALSE);
if (!client->priv->gdbus_book) {
set_proxy_gone_error (error);
return FALSE;
}
uid = e_contact_get_const (E_CONTACT (contact), E_CONTACT_UID);
g_return_val_if_fail (uid != NULL, FALSE);
safe_uid = e_util_ensure_gdbus_string (uid, &gdbus_uid);
g_return_val_if_fail (safe_uid != NULL, FALSE);
strv[0] = safe_uid;
strv[1] = NULL;
res = e_client_proxy_call_sync_strv__void (E_CLIENT (client), strv, cancellable, error, e_gdbus_book_call_remove_contacts_sync);
g_free (gdbus_uid);
return res;
}
/**
* e_book_client_remove_contact_by_uid:
* @client: an #EBookClient
* @uid: a UID of a contact to remove
* @cancellable: a #GCancellable; can be %NULL
* @callback: callback to call when a result is ready
* @user_data: user data for the @callback
*
* Removes contact with @uid from the @client.
* The call is finished by e_book_client_remove_contact_by_uid_finish()
* from the @callback.
*
* Since: 3.2
**/
void
e_book_client_remove_contact_by_uid (EBookClient *client,
const gchar *uid,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
const gchar *safe_uid;
gchar *gdbus_uid = NULL;
const gchar *strv[2];
g_return_if_fail (uid != NULL);
safe_uid = e_util_ensure_gdbus_string (uid, &gdbus_uid);
g_return_if_fail (safe_uid != NULL);
strv[0] = safe_uid;
strv[1] = NULL;
e_client_proxy_call_strv (
E_CLIENT (client), strv, cancellable, callback, user_data, e_book_client_remove_contact_by_uid,
e_gdbus_book_call_remove_contacts,
e_gdbus_book_call_remove_contacts_finish, NULL, NULL, NULL, NULL);
g_free (gdbus_uid);
}
/**
* e_book_client_remove_contact_by_uid_finish:
* @client: an #EBookClient
* @result: a #GAsyncResult
* @error: (out): a #GError to set an error, if any
*
* Finishes previous call of e_book_client_remove_contact_by_uid().
*
* Returns: %TRUE if successful, %FALSE otherwise.
*
* Since: 3.2
**/
gboolean
e_book_client_remove_contact_by_uid_finish (EBookClient *client,
GAsyncResult *result,
GError **error)
{
return e_client_proxy_call_finish_void (E_CLIENT (client), result, error, e_book_client_remove_contact_by_uid);
}
/**
* e_book_client_remove_contact_by_uid_sync:
* @client: an #EBookClient
* @uid: a UID of a contact to remove
* @cancellable: a #GCancellable; can be %NULL
* @error: (out): a #GError to set an error, if any
*
* Removes contact with @uid from the @client.
*
* Returns: %TRUE if successful, %FALSE otherwise.
*
* Since: 3.2
**/
gboolean
e_book_client_remove_contact_by_uid_sync (EBookClient *client,
const gchar *uid,
GCancellable *cancellable,
GError **error)
{
gboolean res;
const gchar *safe_uid;
gchar *gdbus_uid = NULL;
const gchar *strv[2];
g_return_val_if_fail (E_IS_BOOK_CLIENT (client), FALSE);
g_return_val_if_fail (uid != NULL, FALSE);
if (!client->priv->gdbus_book) {
set_proxy_gone_error (error);
return FALSE;
}
safe_uid = e_util_ensure_gdbus_string (uid, &gdbus_uid);
g_return_val_if_fail (safe_uid != NULL, FALSE);
strv[0] = safe_uid;
strv[1] = NULL;
res = e_client_proxy_call_sync_strv__void (E_CLIENT (client), strv, cancellable, error, e_gdbus_book_call_remove_contacts_sync);
g_free (gdbus_uid);
return res;
}
/**
* e_book_client_remove_contacts:
* @client: an #EBookClient
* @uids: (element-type utf8): a #GSList of UIDs to remove
* @cancellable: a #GCancellable; can be %NULL
* @callback: callback to call when a result is ready
* @user_data: user data for the @callback
*
* Removes the contacts with uids from the list @uids from @client. This is
* always more efficient than calling e_book_client_remove_contact() if you
* have more than one uid to remove, as some backends can implement it
* as a batch request.
* The call is finished by e_book_client_remove_contacts_finish()
* from the @callback.
*
* Since: 3.2
**/
void
e_book_client_remove_contacts (EBookClient *client,
const GSList *uids,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
gchar **strv;
g_return_if_fail (uids != NULL);
strv = e_client_util_slist_to_strv (uids);
g_return_if_fail (strv != NULL);
e_client_proxy_call_strv (
E_CLIENT (client), (const gchar * const *) strv, cancellable, callback, user_data, e_book_client_remove_contacts,
e_gdbus_book_call_remove_contacts,
e_gdbus_book_call_remove_contacts_finish, NULL, NULL, NULL, NULL);
g_strfreev (strv);
}
/**
* e_book_client_remove_contacts_finish:
* @client: an #EBookClient
* @result: a #GAsyncResult
* @error: (out): a #GError to set an error, if any
*
* Finishes previous call of e_book_client_remove_contacts().
*
* Returns: %TRUE if successful, %FALSE otherwise.
*
* Since: 3.2
**/
gboolean
e_book_client_remove_contacts_finish (EBookClient *client,
GAsyncResult *result,
GError **error)
{
return e_client_proxy_call_finish_void (E_CLIENT (client), result, error, e_book_client_remove_contacts);
}
/**
* e_book_client_remove_contacts_sync:
* @client: an #EBookClient
* @uids: (element-type utf8): a #GSList of UIDs to remove
* @cancellable: a #GCancellable; can be %NULL
* @error: (out): a #GError to set an error, if any
*
* Removes the contacts with uids from the list @uids from @client. This is
* always more efficient than calling e_book_client_remove_contact() if you
* have more than one uid to remove, as some backends can implement it
* as a batch request.
*
* Returns: %TRUE if successful, %FALSE otherwise.
*
* Since: 3.2
**/
gboolean
e_book_client_remove_contacts_sync (EBookClient *client,
const GSList *uids,
GCancellable *cancellable,
GError **error)
{
gboolean res;
gchar **strv;
g_return_val_if_fail (E_IS_BOOK_CLIENT (client), FALSE);
g_return_val_if_fail (uids != NULL, FALSE);
if (!client->priv->gdbus_book) {
set_proxy_gone_error (error);
return FALSE;
}
strv = e_client_util_slist_to_strv (uids);
g_return_val_if_fail (strv != NULL, FALSE);
res = e_client_proxy_call_sync_strv__void (E_CLIENT (client), (const gchar * const *) strv, cancellable, error, e_gdbus_book_call_remove_contacts_sync);
g_strfreev (strv);
return res;
}
/**
* e_book_client_get_contact:
* @client: an #EBookClient
* @uid: a unique string ID specifying the contact
* @cancellable: a #GCancellable; can be %NULL
* @callback: callback to call when a result is ready
* @user_data: user data for the @callback
*
* Receive #EContact from the @client for the gived @uid.
* The call is finished by e_book_client_get_contact_finish()
* from the @callback.
*
* Since: 3.2
**/
void
e_book_client_get_contact (EBookClient *client,
const gchar *uid,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
const gchar *safe_uid;
gchar *gdbus_uid = NULL;
g_return_if_fail (uid != NULL);
safe_uid = e_util_ensure_gdbus_string (uid, &gdbus_uid);
g_return_if_fail (safe_uid != NULL);
e_client_proxy_call_string (
E_CLIENT (client), safe_uid, cancellable, callback, user_data, e_book_client_get_contact,
e_gdbus_book_call_get_contact,
NULL, NULL, e_gdbus_book_call_get_contact_finish, NULL, NULL);
g_free (gdbus_uid);
}
/**
* e_book_client_get_contact_finish:
* @client: an #EBookClient
* @result: a #GAsyncResult
* @contact: (out): an #EContact for previously given uid
* @error: (out): a #GError to set an error, if any
*
* Finishes previous call of e_book_client_get_contact().
* If successful, then the @contact is set to newly allocated
* #EContact, which should be freed with g_object_unref().
*
* Returns: %TRUE if successful, %FALSE otherwise.
*
* Since: 3.2
**/
gboolean
e_book_client_get_contact_finish (EBookClient *client,
GAsyncResult *result,
EContact **contact,
GError **error)
{
gboolean res;
gchar *vcard = NULL;
g_return_val_if_fail (contact != NULL, FALSE);
res = e_client_proxy_call_finish_string (E_CLIENT (client), result, &vcard, error, e_book_client_get_contact);
if (vcard && res)
*contact = e_contact_new_from_vcard (vcard);
else
*contact = NULL;
g_free (vcard);
return res;
}
/**
* e_book_client_get_contact_sync:
* @client: an #EBookClient
* @uid: a unique string ID specifying the contact
* @contact: (out): an #EContact for given @uid
* @cancellable: a #GCancellable; can be %NULL
* @error: (out): a #GError to set an error, if any
*
* Receive #EContact from the @client for the gived @uid.
* If successful, then the @contact is set to newly allocated
* #EContact, which should be freed with g_object_unref().
*
* Returns: %TRUE if successful, %FALSE otherwise.
*
* Since: 3.2
**/
gboolean
e_book_client_get_contact_sync (EBookClient *client,
const gchar *uid,
EContact **contact,
GCancellable *cancellable,
GError **error)
{
gboolean res;
const gchar *safe_uid;
gchar *vcard = NULL, *gdbus_uid = NULL;
g_return_val_if_fail (E_IS_BOOK_CLIENT (client), FALSE);
g_return_val_if_fail (uid != NULL, FALSE);
g_return_val_if_fail (contact != NULL, FALSE);
if (!client->priv->gdbus_book) {
set_proxy_gone_error (error);
return FALSE;
}
safe_uid = e_util_ensure_gdbus_string (uid, &gdbus_uid);
g_return_val_if_fail (safe_uid != NULL, FALSE);
res = e_client_proxy_call_sync_string__string (E_CLIENT (client), safe_uid, &vcard, cancellable, error, e_gdbus_book_call_get_contact_sync);
if (vcard && res)
*contact = e_contact_new_from_vcard_with_uid (vcard, safe_uid);
else
*contact = NULL;
g_free (gdbus_uid);
g_free (vcard);
return res;
}
/**
* e_book_client_get_contacts:
* @client: an #EBookClient
* @sexp: an S-expression representing the query
* @cancellable: a #GCancellable; can be %NULL
* @callback: callback to call when a result is ready
* @user_data: user data for the @callback
*
* Query @client with @sexp, receiving a list of contacts which
* matched. The call is finished by e_book_client_get_contacts_finish()
* from the @callback.
*
* Note: @sexp can be obtained through #EBookQuery, by converting it
* to a string with e_book_query_to_string().
*
* Since: 3.2
**/
void
e_book_client_get_contacts (EBookClient *client,
const gchar *sexp,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
gchar *gdbus_sexp = NULL;
g_return_if_fail (sexp != NULL);
e_client_proxy_call_string (
E_CLIENT (client), e_util_ensure_gdbus_string (sexp, &gdbus_sexp), cancellable, callback, user_data, e_book_client_get_contacts,
e_gdbus_book_call_get_contact_list,
NULL, NULL, NULL, e_gdbus_book_call_get_contact_list_finish, NULL);
g_free (gdbus_sexp);
}
/**
* e_book_client_get_contacts_finish:
* @client: an #EBookClient
* @result: a #GAsyncResult
* @contacts: (element-type EContact) (out): a #GSList of matched #EContact-s
* @error: (out): a #GError to set an error, if any
*
* Finishes previous call of e_book_client_get_contacts().
* If successful, then the @contacts is set to newly allocated list of #EContact-s,
* which should be freed with e_client_util_free_object_slist().
*
* Returns: %TRUE if successful, %FALSE otherwise.
*
* Since: 3.2
**/
gboolean
e_book_client_get_contacts_finish (EBookClient *client,
GAsyncResult *result,
GSList **contacts,
GError **error)
{
gboolean res;
gchar **vcards = NULL;
g_return_val_if_fail (contacts != NULL, FALSE);
res = e_client_proxy_call_finish_strv (E_CLIENT (client), result, &vcards, error, e_book_client_get_contacts);
if (vcards && res) {
gint ii;
GSList *slist = NULL;
for (ii = 0; vcards[ii]; ii++) {
slist = g_slist_prepend (slist, e_contact_new_from_vcard (vcards[ii]));
}
*contacts = g_slist_reverse (slist);
} else {
*contacts = NULL;
}
g_strfreev (vcards);
return res;
}
/**
* e_book_client_get_contacts_sync:
* @client: an #EBookClient
* @sexp: an S-expression representing the query
* @contacts: (element-type EContact) (out): a #GSList of matched #EContact-s
* @cancellable: a #GCancellable; can be %NULL
* @error: (out): a #GError to set an error, if any
*
* Query @client with @sexp, receiving a list of contacts which matched.
* If successful, then the @contacts is set to newly allocated #GSList of
* #EContact-s, which should be freed with e_client_util_free_object_slist().
*
* Note: @sexp can be obtained through #EBookQuery, by converting it
* to a string with e_book_query_to_string().
*
* Returns: %TRUE if successful, %FALSE otherwise.
*
* Since: 3.2
**/
gboolean
e_book_client_get_contacts_sync (EBookClient *client,
const gchar *sexp,
GSList **contacts,
GCancellable *cancellable,
GError **error)
{
gboolean res;
gchar *gdbus_sexp = NULL;
gchar **vcards = NULL;
g_return_val_if_fail (E_IS_BOOK_CLIENT (client), FALSE);
g_return_val_if_fail (sexp != NULL, FALSE);
g_return_val_if_fail (contacts != NULL, FALSE);
if (!client->priv->gdbus_book) {
set_proxy_gone_error (error);
return FALSE;
}
res = e_client_proxy_call_sync_string__strv (E_CLIENT (client), e_util_ensure_gdbus_string (sexp, &gdbus_sexp), &vcards, cancellable, error, e_gdbus_book_call_get_contact_list_sync);
if (vcards && res) {
gint ii;
GSList *slist = NULL;
for (ii = 0; vcards[ii]; ii++) {
slist = g_slist_prepend (slist, e_contact_new_from_vcard (vcards[ii]));
}
*contacts = g_slist_reverse (slist);
} else {
*contacts = NULL;
}
g_free (gdbus_sexp);
g_strfreev (vcards);
return res;
}
/**
* e_book_client_get_contacts_uids:
* @client: an #EBookClient
* @sexp: an S-expression representing the query
* @cancellable: a #GCancellable; can be %NULL
* @callback: callback to call when a result is ready
* @user_data: user data for the @callback
*
* Query @client with @sexp, receiving a list of contacts UIDs which
* matched. The call is finished by e_book_client_get_contacts_uids_finish()
* from the @callback.
*
* Note: @sexp can be obtained through #EBookQuery, by converting it
* to a string with e_book_query_to_string().
*
* Since: 3.2
**/
void
e_book_client_get_contacts_uids (EBookClient *client,
const gchar *sexp,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
gchar *gdbus_sexp = NULL;
g_return_if_fail (sexp != NULL);
e_client_proxy_call_string (
E_CLIENT (client), e_util_ensure_gdbus_string (sexp, &gdbus_sexp), cancellable, callback, user_data, e_book_client_get_contacts_uids,
e_gdbus_book_call_get_contact_list_uids,
NULL, NULL, NULL, e_gdbus_book_call_get_contact_list_uids_finish, NULL);
g_free (gdbus_sexp);
}
/**
* e_book_client_get_contacts_uids_finish:
* @client: an #EBookClient
* @result: a #GAsyncResult
* @contacts_uids: (element-type utf8) (out): a #GSList of matched contacts UIDs stored as strings
* @error: (out): a #GError to set an error, if any
*
* Finishes previous call of e_book_client_get_contacts_uids().
* If successful, then the @contacts_uids is set to newly allocated list
* of UID strings, which should be freed with e_client_util_free_string_slist().
*
* Returns: %TRUE if successful, %FALSE otherwise.
*
* Since: 3.2
**/
gboolean
e_book_client_get_contacts_uids_finish (EBookClient *client,
GAsyncResult *result,
GSList **contacts_uids,
GError **error)
{
gboolean res;
gchar **uids = NULL;
g_return_val_if_fail (contacts_uids != NULL, FALSE);
res = e_client_proxy_call_finish_strv (E_CLIENT (client), result, &uids, error, e_book_client_get_contacts_uids);
if (uids && res) {
gint ii;
GSList *slist = NULL;
for (ii = 0; uids[ii]; ii++) {
slist = g_slist_prepend (slist, g_strdup (uids[ii]));
}
*contacts_uids = g_slist_reverse (slist);
} else {
*contacts_uids = NULL;
}
g_strfreev (uids);
return res;
}
/**
* e_book_client_get_contacts_uids_sync:
* @client: an #EBookClient
* @sexp: an S-expression representing the query
* @contacts_uids: (element-type utf8) (out): a #GSList of matched contacts UIDs stored as strings
* @cancellable: a #GCancellable; can be %NULL
* @error: (out): a #GError to set an error, if any
*
* Query @client with @sexp, receiving a list of contacts UIDs which matched.
* If successful, then the @contacts_uids is set to newly allocated list
* of UID strings, which should be freed with e_client_util_free_string_slist().
*
* Note: @sexp can be obtained through #EBookQuery, by converting it
* to a string with e_book_query_to_string().
*
* Returns: %TRUE if successful, %FALSE otherwise.
*
* Since: 3.2
**/
gboolean
e_book_client_get_contacts_uids_sync (EBookClient *client,
const gchar *sexp,
GSList **contacts_uids,
GCancellable *cancellable,
GError **error)
{
gboolean res;
gchar *gdbus_sexp = NULL;
gchar **uids = NULL;
g_return_val_if_fail (E_IS_BOOK_CLIENT (client), FALSE);
g_return_val_if_fail (sexp != NULL, FALSE);
g_return_val_if_fail (contacts_uids != NULL, FALSE);
if (!client->priv->gdbus_book) {
set_proxy_gone_error (error);
return FALSE;
}
res = e_client_proxy_call_sync_string__strv (E_CLIENT (client), e_util_ensure_gdbus_string (sexp, &gdbus_sexp), &uids, cancellable, error, e_gdbus_book_call_get_contact_list_uids_sync);
if (uids && res) {
gint ii;
GSList *slist = NULL;
for (ii = 0; uids[ii]; ii++) {
slist = g_slist_prepend (slist, g_strdup (uids[ii]));
}
*contacts_uids = g_slist_reverse (slist);
} else {
*contacts_uids = NULL;
}
g_free (gdbus_sexp);
g_strfreev (uids);
return res;
}
/**
* e_book_client_get_view:
* @client: an #EBookClient
* @sexp: an S-expression representing the query
* @cancellable: a #GCancellable; can be %NULL
* @callback: callback to call when a result is ready
* @user_data: user data for the @callback
*
* Query @client with @sexp, creating an #EBookClientView.
* The call is finished by e_book_client_get_view_finish()
* from the @callback.
*
* Note: @sexp can be obtained through #EBookQuery, by converting it
* to a string with e_book_query_to_string().
*
* Since: 3.2
**/
void
e_book_client_get_view (EBookClient *client,
const gchar *sexp,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
gchar *gdbus_sexp = NULL;
g_return_if_fail (sexp != NULL);
e_client_proxy_call_string (
E_CLIENT (client), e_util_ensure_gdbus_string (sexp, &gdbus_sexp), cancellable, callback, user_data, e_book_client_get_view,
e_gdbus_book_call_get_view,
NULL, NULL, e_gdbus_book_call_get_view_finish, NULL, NULL);
g_free (gdbus_sexp);
}
static gboolean
complete_get_view (EBookClient *client,
gboolean res,
gchar *view_path,
EBookClientView **view,
GError **error)
{
g_return_val_if_fail (view != NULL, FALSE);
if (view_path && res && book_factory_proxy) {
GError *local_error = NULL;
EGdbusBookView *gdbus_bookview;
gdbus_bookview = e_gdbus_book_view_proxy_new_sync (
g_dbus_proxy_get_connection (G_DBUS_PROXY (book_factory_proxy)),
G_DBUS_PROXY_FLAGS_NONE,
ADDRESS_BOOK_DBUS_SERVICE_NAME,
view_path,
NULL,
&local_error);
if (gdbus_bookview) {
*view = _e_book_client_view_new (client, gdbus_bookview);
g_object_unref (gdbus_bookview);
} else {
*view = NULL;
res = FALSE;
}
if (local_error)
unwrap_dbus_error (local_error, error);
} else {
*view = NULL;
res = FALSE;
}
if (!*view && error && !*error)
g_set_error_literal (error, E_CLIENT_ERROR, E_CLIENT_ERROR_DBUS_ERROR, _("Cannot get connection to view"));
g_free (view_path);
return res;
}
/**
* e_book_client_get_view_finish:
* @client: an #EBookClient
* @result: a #GAsyncResult
* @view: (out): an #EBookClientView
* @error: (out): a #GError to set an error, if any
*
* Finishes previous call of e_book_client_get_view().
* If successful, then the @view is set to newly allocated #EBookClientView,
* which should be freed with g_object_unref().
*
* Returns: %TRUE if successful, %FALSE otherwise.
*
* Since: 3.2
**/
gboolean
e_book_client_get_view_finish (EBookClient *client,
GAsyncResult *result,
EBookClientView **view,
GError **error)
{
gboolean res;
gchar *view_path = NULL;
g_return_val_if_fail (view != NULL, FALSE);
res = e_client_proxy_call_finish_string (E_CLIENT (client), result, &view_path, error, e_book_client_get_view);
return complete_get_view (client, res, view_path, view, error);
}
/**
* e_book_client_get_view_sync:
* @client: an #EBookClient
* @sexp: an S-expression representing the query
* @view: (out) an #EBookClientView
* @cancellable: a #GCancellable; can be %NULL
* @error: (out): a #GError to set an error, if any
*
* Query @client with @sexp, creating an #EBookClientView.
* If successful, then the @view is set to newly allocated #EBookClientView,
* which should be freed with g_object_unref().
*
* Note: @sexp can be obtained through #EBookQuery, by converting it
* to a string with e_book_query_to_string().
*
* Returns: %TRUE if successful, %FALSE otherwise.
*
* Since: 3.2
**/
gboolean
e_book_client_get_view_sync (EBookClient *client,
const gchar *sexp,
EBookClientView **view,
GCancellable *cancellable,
GError **error)
{
gboolean res;
gchar *gdbus_sexp = NULL;
gchar *view_path = NULL;
g_return_val_if_fail (E_IS_BOOK_CLIENT (client), FALSE);
g_return_val_if_fail (sexp != NULL, FALSE);
g_return_val_if_fail (view != NULL, FALSE);
if (!client->priv->gdbus_book) {
set_proxy_gone_error (error);
return FALSE;
}
res = e_client_proxy_call_sync_string__string (E_CLIENT (client), e_util_ensure_gdbus_string (sexp, &gdbus_sexp), &view_path, cancellable, error, e_gdbus_book_call_get_view_sync);
g_free (gdbus_sexp);
return complete_get_view (client, res, view_path, view, error);
}
static GDBusProxy *
book_client_get_dbus_proxy (EClient *client)
{
EBookClient *book_client;
g_return_val_if_fail (E_IS_CLIENT (client), NULL);
book_client = E_BOOK_CLIENT (client);
return book_client->priv->gdbus_book;
}
static void
book_client_unwrap_dbus_error (EClient *client,
GError *dbus_error,
GError **out_error)
{
unwrap_dbus_error (dbus_error, out_error);
}
static void
book_client_retrieve_capabilities (EClient *client,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
g_return_if_fail (E_IS_BOOK_CLIENT (client));
book_client_get_backend_property (client, CLIENT_BACKEND_PROPERTY_CAPABILITIES, cancellable, callback, user_data);
}
static gboolean
book_client_retrieve_capabilities_finish (EClient *client,
GAsyncResult *result,
gchar **capabilities,
GError **error)
{
g_return_val_if_fail (E_IS_BOOK_CLIENT (client), FALSE);
return book_client_get_backend_property_finish (client, result, capabilities, error);
}
static gboolean
book_client_retrieve_capabilities_sync (EClient *client,
gchar **capabilities,
GCancellable *cancellable,
GError **error)
{
g_return_val_if_fail (E_IS_BOOK_CLIENT (client), FALSE);
return book_client_get_backend_property_sync (client, CLIENT_BACKEND_PROPERTY_CAPABILITIES, capabilities, cancellable, error);
}
static void
e_book_client_init (EBookClient *client)
{
LOCK_FACTORY ();
active_book_clients++;
UNLOCK_FACTORY ();
client->priv = E_BOOK_CLIENT_GET_PRIVATE (client);
}
static void
book_client_dispose (GObject *object)
{
EClient *client;
client = E_CLIENT (object);
e_client_cancel_all (client);
gdbus_book_client_disconnect (E_BOOK_CLIENT (client));
/* Chain up to parent's dispose() method. */
G_OBJECT_CLASS (e_book_client_parent_class)->dispose (object);
}
static void
book_client_finalize (GObject *object)
{
/* Chain up to parent's finalize() method. */
G_OBJECT_CLASS (e_book_client_parent_class)->finalize (object);
LOCK_FACTORY ();
active_book_clients--;
if (!active_book_clients)
gdbus_book_factory_proxy_disconnect (NULL);
UNLOCK_FACTORY ();
}
static void
e_book_client_class_init (EBookClientClass *class)
{
GObjectClass *object_class;
EClientClass *client_class;
g_type_class_add_private (class, sizeof (EBookClientPrivate));
object_class = G_OBJECT_CLASS (class);
object_class->dispose = book_client_dispose;
object_class->finalize = book_client_finalize;
client_class = E_CLIENT_CLASS (class);
client_class->get_dbus_proxy = book_client_get_dbus_proxy;
client_class->unwrap_dbus_error = book_client_unwrap_dbus_error;
client_class->retrieve_capabilities = book_client_retrieve_capabilities;
client_class->retrieve_capabilities_finish = book_client_retrieve_capabilities_finish;
client_class->retrieve_capabilities_sync = book_client_retrieve_capabilities_sync;
client_class->get_backend_property = book_client_get_backend_property;
client_class->get_backend_property_finish = book_client_get_backend_property_finish;
client_class->get_backend_property_sync = book_client_get_backend_property_sync;
client_class->set_backend_property = book_client_set_backend_property;
client_class->set_backend_property_finish = book_client_set_backend_property_finish;
client_class->set_backend_property_sync = book_client_set_backend_property_sync;
client_class->open = book_client_open;
client_class->open_finish = book_client_open_finish;
client_class->open_sync = book_client_open_sync;
client_class->refresh = book_client_refresh;
client_class->refresh_finish = book_client_refresh_finish;
client_class->refresh_sync = book_client_refresh_sync;
}