[evolution-data-server/meego-eds] Implement e_book_get_contact_uids()



commit 1953f2ac00a5c41c6cfc653269d6e043ce1bafbf
Author: Christophe Dumez <christophe dumez intel com>
Date:   Wed Jun 1 09:52:16 2011 +0300

    Implement e_book_get_contact_uids()
    
    Add synchronous and asynchronous functions to retrieve only the
    uids of the contacts that match the query instead of the full
    contacts.

 addressbook/backends/file/e-book-backend-file.c |   94 ++++++++++
 addressbook/backends/vcf/e-book-backend-vcf.c   |   49 ++++++
 addressbook/libebook/e-book.c                   |  115 ++++++++++++
 addressbook/libebook/e-book.h                   |   10 +
 addressbook/libedata-book/e-book-backend-sexp.c |   29 +++-
 addressbook/libedata-book/e-book-backend-sexp.h |    1 +
 addressbook/libedata-book/e-book-backend-sync.c |   79 +++++++++
 addressbook/libedata-book/e-book-backend-sync.h |    4 +
 addressbook/libedata-book/e-book-backend.c      |   24 +++
 addressbook/libedata-book/e-book-backend.h      |    5 +
 addressbook/libedata-book/e-data-book.c         |   34 ++++
 addressbook/libedata-book/e-data-book.h         |    4 +
 addressbook/libegdbus/e-gdbus-egdbusbook.c      |  212 +++++++++++++++++++++++
 addressbook/libegdbus/e-gdbus-egdbusbook.h      |   30 ++++
 14 files changed, 689 insertions(+), 1 deletions(-)
---
diff --git a/addressbook/backends/file/e-book-backend-file.c b/addressbook/backends/file/e-book-backend-file.c
index cfd84e0..7c1d056 100644
--- a/addressbook/backends/file/e-book-backend-file.c
+++ b/addressbook/backends/file/e-book-backend-file.c
@@ -506,6 +506,99 @@ e_book_backend_file_get_contact_list (EBookBackendSync *backend,
 	*contacts = contact_list;
 }
 
+static void
+e_book_backend_file_get_contact_uid_list (EBookBackendSync *backend,
+				          EDataBook *book,
+				          guint32 opid,
+				          const gchar *query,
+				          GList **contact_uids,
+				          GError **perror)
+{
+	EBookBackendFile *bf = E_BOOK_BACKEND_FILE (backend);
+	DB             *db = bf->priv->file_db;
+	DBC            *dbc;
+	gint            db_error;
+	DBT  id_dbt, vcard_dbt;
+	EBookBackendSExp *card_sexp = NULL;
+	gboolean search_needed;
+	const gchar *search = query;
+	GList *uids = NULL;
+
+	d(printf ("e_book_backend_file_get_contact_uid_list (%s)\n", search));
+	if (e_book_backend_summary_is_summary_query (bf->priv->summary, search)) {
+
+		/* do a summary query */
+		GPtrArray *ids = e_book_backend_summary_search (bf->priv->summary, search);
+		gint i;
+
+		if (!ids) {
+			g_propagate_error (perror, EDB_ERROR (CONTACT_NOT_FOUND));
+			return;
+		}
+
+		for (i = 0; i < ids->len; i++) {
+			gchar *id = g_ptr_array_index (ids, i);
+			uids = g_list_prepend (uids, g_strdup (id));
+		}
+		g_ptr_array_free (ids, TRUE);
+	} else {
+		search_needed = TRUE;
+		if (!strcmp (search, "(contains \"x-evolution-any-field\" \"\")"))
+			search_needed = FALSE;
+
+		card_sexp = e_book_backend_sexp_new (search);
+		if (!card_sexp) {
+			g_propagate_error (perror, EDB_ERROR (INVALID_QUERY));
+			return;
+		}
+
+		db_error = db->cursor (db, NULL, &dbc, 0);
+
+		if (db_error != 0) {
+			g_warning (G_STRLOC ": db->cursor failed with %s", db_strerror (db_error));
+			/* XXX this needs to be some CouldNotOpen error */
+			db_error_to_gerror (db_error, perror);
+			return;
+		}
+
+		memset (&vcard_dbt, 0, sizeof (vcard_dbt));
+		vcard_dbt.flags = DB_DBT_MALLOC;
+		memset (&id_dbt, 0, sizeof (id_dbt));
+		db_error = dbc->c_get(dbc, &id_dbt, &vcard_dbt, DB_FIRST);
+
+		while (db_error == 0) {
+
+			/* don't include the version in the list of cards */
+			if (id_dbt.size != strlen(E_BOOK_BACKEND_FILE_VERSION_NAME) + 1
+			    || strcmp (id_dbt.data, E_BOOK_BACKEND_FILE_VERSION_NAME)) {
+
+				if ((!search_needed) || (card_sexp != NULL && e_book_backend_sexp_match_vcard  (card_sexp, vcard_dbt.data))) {
+					uids = g_list_prepend (uids, g_strdup (id_dbt.data));
+				}
+			}
+
+			free (vcard_dbt.data);
+			db_error = dbc->c_get(dbc, &id_dbt, &vcard_dbt, DB_NEXT);
+
+		}
+		g_object_unref (card_sexp);
+
+		if (db_error == DB_NOTFOUND) {
+			/* Success */
+		} else {
+			g_warning (G_STRLOC ": dbc->c_get failed with %s", db_strerror (db_error));
+			db_error_to_gerror (db_error, perror);
+		}
+
+		db_error = dbc->c_close(dbc);
+		if (db_error != 0) {
+			g_warning (G_STRLOC ": dbc->c_close failed with %s", db_strerror (db_error));
+		}
+	}
+
+	*contact_uids = g_list_reverse (uids);
+}
+
 typedef struct {
 	EBookBackendFile *bf;
 	GThread *thread;
@@ -1573,6 +1666,7 @@ e_book_backend_file_class_init (EBookBackendFileClass *klass)
 	sync_class->modify_contact_sync			= e_book_backend_file_modify_contact;
 	sync_class->get_contact_sync			= e_book_backend_file_get_contact;
 	sync_class->get_contact_list_sync		= e_book_backend_file_get_contact_list;
+	sync_class->get_contact_uid_list_sync		= e_book_backend_file_get_contact_uid_list;
 	sync_class->get_changes_sync			= e_book_backend_file_get_changes;
 	sync_class->authenticate_user_sync		= e_book_backend_file_authenticate_user;
 	sync_class->get_supported_auth_methods_sync	= e_book_backend_file_get_supported_auth_methods;
diff --git a/addressbook/backends/vcf/e-book-backend-vcf.c b/addressbook/backends/vcf/e-book-backend-vcf.c
index c2911b8..3b974c6 100644
--- a/addressbook/backends/vcf/e-book-backend-vcf.c
+++ b/addressbook/backends/vcf/e-book-backend-vcf.c
@@ -397,6 +397,30 @@ foreach_get_contact_compare (gchar *vcard_string, GetContactListClosure *closure
 }
 
 static void
+foreach_get_contact_uid_compare (gchar *vcard_string, GetContactListClosure *closure)
+{
+	gchar *uid = NULL;
+	if ((!closure->search_needed) || e_book_backend_sexp_match_vcard_ret_uid (closure->card_sexp, vcard_string, &uid)) {
+		if (!uid) {
+			/* Extract the UID for the vCard (inefficient) */
+			EVCard *card = e_vcard_new_from_string (vcard_string);
+			EVCardAttribute *attr;
+
+			if (!card)
+				return;
+
+			attr = e_vcard_get_attribute (card, EVC_UID);
+			if (attr)
+				uid = e_vcard_attribute_get_value (attr);
+
+			g_object_unref (card);
+		}
+		if (uid != NULL)
+			closure->list = g_list_append (closure->list, uid);
+	}
+}
+
+static void
 e_book_backend_vcf_get_contact_list (EBookBackendSync *backend,
 				     EDataBook *book,
 				     guint32 opid,
@@ -420,6 +444,30 @@ e_book_backend_vcf_get_contact_list (EBookBackendSync *backend,
 	*contacts = closure.list;
 }
 
+static void
+e_book_backend_vcf_get_contact_uid_list (EBookBackendSync *backend,
+					 EDataBook *book,
+					 guint32 opid,
+					 const gchar *query,
+					 GList **contact_ids,
+					 GError **perror)
+{
+	EBookBackendVCF *bvcf = E_BOOK_BACKEND_VCF (backend);
+	const gchar *search = query;
+	GetContactListClosure closure;
+
+	closure.bvcf = bvcf;
+	closure.search_needed = strcmp (search, "(contains \"x-evolution-any-field\" \"\")");
+	closure.card_sexp = e_book_backend_sexp_new (search);
+	closure.list = NULL;
+
+	g_list_foreach (bvcf->priv->contact_list, (GFunc)foreach_get_contact_uid_compare, &closure);
+
+	g_object_unref (closure.card_sexp);
+
+	*contact_ids = closure.list;
+}
+
 typedef struct {
 	EBookBackendVCF *bvcf;
 	EDataBookView *view;
@@ -754,6 +802,7 @@ e_book_backend_vcf_class_init (EBookBackendVCFClass *klass)
 	sync_class->modify_contact_sync        = e_book_backend_vcf_modify_contact;
 	sync_class->get_contact_sync           = e_book_backend_vcf_get_contact;
 	sync_class->get_contact_list_sync      = e_book_backend_vcf_get_contact_list;
+	sync_class->get_contact_uid_list_sync  = e_book_backend_vcf_get_contact_uid_list;
 	sync_class->authenticate_user_sync     = e_book_backend_vcf_authenticate_user;
 	sync_class->get_required_fields_sync   = e_book_backend_vcf_get_required_fields;
 	sync_class->get_supported_fields_sync  = e_book_backend_vcf_get_supported_fields;
diff --git a/addressbook/libebook/e-book.c b/addressbook/libebook/e-book.c
index b747bcc..10e85c0 100644
--- a/addressbook/libebook/e-book.c
+++ b/addressbook/libebook/e-book.c
@@ -2021,6 +2021,50 @@ e_book_get_contacts (EBook       *book,
 	}
 }
 
+/**
+ * e_book_get_contact_uids:
+ * @book: an #EBook
+ * @query: an #EBookQuery
+ * @contacts: a #GList pointer, will be set to the list of contact uids
+ * @error: a #GError to set on failure
+ *
+ * Query @book with @query, setting @uids to the list of uids of contacts which
+ * matched. On failed, @error will be set and %FALSE returned.
+ *
+ * Returns: %TRUE on success, %FALSE otherwise
+ **/
+gboolean
+e_book_get_contact_uids (EBook       *book,
+		         EBookQuery  *query,
+		         GList      **uids,
+		         GError     **error)
+{
+	GError *err = NULL;
+	gchar **list = NULL;
+	gchar *sexp;
+
+	e_return_error_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+	e_return_error_if_fail (book->priv->gdbus_book, E_BOOK_ERROR_REPOSITORY_OFFLINE);
+
+	sexp = e_book_query_to_string (query);
+
+	e_gdbus_book_call_get_contact_uid_list_sync (book->priv->gdbus_book, sexp, &list, NULL, &err);
+
+	g_free (sexp);
+
+	if (!err) {
+		GList *l = NULL;
+		gchar **i = list;
+		while (*i != NULL) {
+			l = g_list_prepend (l, *i++);
+		}
+		*uids = g_list_reverse (l);
+		return TRUE;
+	} else {
+		return unwrap_gerror (err, error);
+	}
+}
+
 static void
 get_contacts_reply (GObject *gdbus_book, GAsyncResult *res, gpointer user_data)
 {
@@ -2064,6 +2108,39 @@ get_contacts_reply (GObject *gdbus_book, GAsyncResult *res, gpointer user_data)
 	g_slice_free (AsyncData, data);
 }
 
+static void
+get_contact_uids_reply (GObject *gdbus_book, GAsyncResult *res, gpointer user_data)
+{
+	gchar **uids = NULL;
+	GError *err = NULL, *error = NULL;
+	AsyncData *data = user_data;
+	GList *list = NULL;
+	EBookListAsyncCallback excb = data->excallback;
+	
+	e_gdbus_book_call_get_contact_uid_list_finish (E_GDBUS_BOOK (gdbus_book), &uids, res, &error);
+
+	unwrap_gerror (error, &err);
+	
+	if (!error && uids) {
+		gchar **i = uids;
+
+		while (*i != NULL) {
+			list = g_list_prepend (list, *i++);
+		}
+
+		list = g_list_reverse (list);
+	}
+	
+	if (excb)
+		excb (data->book, err, list, data->closure);
+
+	if (err)
+		g_error_free (err);
+
+	g_object_unref (data->book);
+	g_slice_free (AsyncData, data);
+}
+
 #ifndef E_BOOK_DISABLE_DEPRECATED
 /**
  * e_book_async_get_contacts:
@@ -2146,6 +2223,44 @@ e_book_get_contacts_async (EBook                  *book,
 	return TRUE;
 }
 
+/**
+ * e_book_get_contact_uids_async:
+ * @book: an #EBook
+ * @query: an #EBookQuery
+ * @cb: a function to call when the operation finishes
+ * @closure: data to pass to callback function
+ *
+ * Query @book with @query.
+ *
+ * Returns: %FALSE on success, %TRUE otherwise
+ **/
+gboolean  
+e_book_get_contact_uids_async (EBook                 *book,
+			       EBookQuery            *query,
+			       EBookListAsyncCallback cb,
+			       gpointer               closure)
+{
+  	AsyncData *data;
+	gchar *sexp;
+
+	e_return_ex_async_error_val_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+	e_return_ex_async_error_val_if_fail (book->priv->gdbus_book, E_BOOK_ERROR_REPOSITORY_OFFLINE);
+	e_return_ex_async_error_val_if_fail (query, E_BOOK_ERROR_INVALID_ARG);
+
+	sexp = e_book_query_to_string (query);
+
+	data = g_slice_new0 (AsyncData);
+	data->book = g_object_ref (book);
+	data->excallback = cb;
+	data->closure = closure;
+
+	e_gdbus_book_call_get_contact_uid_list (book->priv->gdbus_book, sexp, NULL, get_contact_uids_reply, data);
+
+	g_free (sexp);
+
+	return TRUE;
+}
+
 static GList *
 parse_changes_array (GVariant *var_changes)
 {
diff --git a/addressbook/libebook/e-book.h b/addressbook/libebook/e-book.h
index 46e4971..c33fb51 100644
--- a/addressbook/libebook/e-book.h
+++ b/addressbook/libebook/e-book.h
@@ -346,6 +346,11 @@ gboolean e_book_get_contacts               (EBook       *book,
 					    GList      **contacts,
 					    GError     **error);
 
+gboolean e_book_get_contact_uids               (EBook       *book,
+					    EBookQuery  *query,
+					    GList      **uids,
+					    GError     **error);
+
 #ifndef E_BOOK_DISABLE_DEPRECATED
 guint     e_book_async_get_contacts        (EBook             *book,
 					    EBookQuery        *query,
@@ -358,6 +363,11 @@ gboolean  e_book_get_contacts_async     (EBook                 *book,
 					 EBookListAsyncCallback cb,
 					 gpointer               closure);
 
+gboolean  e_book_get_contact_uids_async     (EBook                 *book,
+					     EBookQuery            *query,
+					     EBookListAsyncCallback cb,
+					     gpointer               closure);
+
 /* Needed for syncing */
 gboolean e_book_get_changes                (EBook       *book,
 					    const gchar *changeid,
diff --git a/addressbook/libedata-book/e-book-backend-sexp.c b/addressbook/libedata-book/e-book-backend-sexp.c
index 42caefb..24a8ff6 100644
--- a/addressbook/libedata-book/e-book-backend-sexp.c
+++ b/addressbook/libedata-book/e-book-backend-sexp.c
@@ -910,7 +910,34 @@ e_book_backend_sexp_match_vcard (EBookBackendSExp *sexp, const gchar *vcard)
 	return retval;
 }
 
-
+/**
+ * e_book_backend_sexp_match_vcard:
+ * @sexp: an #EBookBackendSExp
+ * @vcard: a VCard string
+ * @uid: Pointer set to the uid of the contacts if it matches
+ *
+ * Checks if @vcard matches @sexp.
+ *
+ * Returns: %TRUE if the VCard matches, %FALSE otherwise.
+ **/
+gboolean
+e_book_backend_sexp_match_vcard_ret_uid (EBookBackendSExp *sexp, const gchar *vcard, gchar **uid)
+{
+	EContact *contact;
+	gboolean retval;
+
+	contact = e_contact_new_from_vcard (vcard);
+
+	retval = e_book_backend_sexp_match_contact (sexp, contact);
+	
+	if (retval == TRUE) {
+		*uid = e_contact_get (contact, E_CONTACT_UID);
+	}
+
+	g_object_unref(contact);
+
+	return retval;
+}
 
 /**
  * e_book_backend_sexp_new:
diff --git a/addressbook/libedata-book/e-book-backend-sexp.h b/addressbook/libedata-book/e-book-backend-sexp.h
index 42d6e93..60d4c8f 100644
--- a/addressbook/libedata-book/e-book-backend-sexp.h
+++ b/addressbook/libedata-book/e-book-backend-sexp.h
@@ -53,6 +53,7 @@ EBookBackendSExp *e_book_backend_sexp_new      (const gchar *text);
 GType               e_book_backend_sexp_get_type (void);
 
 gboolean            e_book_backend_sexp_match_vcard (EBookBackendSExp *sexp, const gchar *vcard);
+gboolean            e_book_backend_sexp_match_vcard_ret_uid (EBookBackendSExp *sexp, const gchar *vcard, gchar **uid);
 gboolean            e_book_backend_sexp_match_contact (EBookBackendSExp *sexp, EContact *contact);
 
 G_END_DECLS
diff --git a/addressbook/libedata-book/e-book-backend-sync.c b/addressbook/libedata-book/e-book-backend-sync.c
index 4492441..bda9a1d 100644
--- a/addressbook/libedata-book/e-book-backend-sync.c
+++ b/addressbook/libedata-book/e-book-backend-sync.c
@@ -207,6 +207,70 @@ e_book_backend_sync_get_contact_list (EBookBackendSync *backend,
 }
 
 /**
+ * e_book_backend_sync_get_contact_uid_list:
+ * @backend: an #EBookBackendSync
+ * @book: an #EDataBook
+ * @opid: the unique ID of the operation
+ * @query: an s-expression of the query to perform
+ * @contact_uids: a pointer to a location to store the resulting list of UID strings
+ * @error: #GError to set, when something fails
+ *
+ * Gets a list of contact uids from @book. The list and its elements must be freed
+ * by the caller.
+ **/
+void
+e_book_backend_sync_get_contact_uid_list (EBookBackendSync *backend,
+					  EDataBook *book,
+					  guint32 opid,
+					  const gchar *query,
+					  GList **contact_uids,
+					  GError **error)
+{
+	e_return_data_book_error_if_fail (E_IS_BOOK_BACKEND_SYNC (backend), E_DATA_BOOK_STATUS_INVALID_ARG);
+	e_return_data_book_error_if_fail (E_IS_DATA_BOOK (book), E_DATA_BOOK_STATUS_INVALID_ARG);
+	e_return_data_book_error_if_fail (query, E_DATA_BOOK_STATUS_INVALID_ARG);
+	e_return_data_book_error_if_fail (contact_uids, E_DATA_BOOK_STATUS_INVALID_ARG);
+
+	if (E_BOOK_BACKEND_SYNC_GET_CLASS (backend)->get_contact_uid_list_sync != NULL) {
+		(* E_BOOK_BACKEND_SYNC_GET_CLASS (backend)->get_contact_uid_list_sync) (backend, book, opid, query, contact_uids, error);
+	} else {
+		/* inefficient fallback code */
+		GList *vcards = NULL;
+		GError *local_error = NULL;
+
+		e_book_backend_sync_get_contact_list (backend, book, opid, query, &vcards, &local_error);
+
+		if (local_error) {
+			g_propagate_error (error, local_error);
+		} else {
+			GList *v;
+
+			*contact_uids = NULL;
+
+			for (v = vcards; v; v = v->next) {
+				EVCard *card = e_vcard_new_from_string (v->data);
+				EVCardAttribute *attr;
+
+				if (!card)
+					continue;
+
+				attr = e_vcard_get_attribute (card, EVC_UID);
+
+				if (attr)
+					*contact_uids = g_list_prepend (*contact_uids, e_vcard_attribute_get_value (attr));
+
+				g_object_unref (card);
+			}
+
+			*contact_uids = g_list_reverse (*contact_uids);
+		}
+
+		g_list_foreach (vcards, (GFunc) g_free, NULL);
+		g_list_free (vcards);
+	}
+}
+
+/**
  * e_book_backend_sync_get_changes:
  * @backend: an #EBookBackendSync
  * @book: an #EDataBook
@@ -446,6 +510,20 @@ _e_book_backend_get_contact_list (EBookBackend *backend,
 }
 
 static void
+_e_book_backend_get_contact_uid_list (EBookBackend *backend,
+				      EDataBook    *book,
+				      guint32       opid,
+				      const gchar   *query)
+{
+	GError *error = NULL;
+	GList *uids = NULL;
+
+	e_book_backend_sync_get_contact_uid_list (E_BOOK_BACKEND_SYNC (backend), book, opid, query, &uids, &error);
+
+	e_data_book_respond_get_contact_uid_list (book, opid, error, uids);
+}
+
+static void
 _e_book_backend_get_changes (EBookBackend *backend,
 			     EDataBook    *book,
 			     guint32       opid,
@@ -570,6 +648,7 @@ e_book_backend_sync_class_init (EBookBackendSyncClass *klass)
 	backend_class->modify_contact = _e_book_backend_modify_contact;
 	backend_class->get_contact = _e_book_backend_get_contact;
 	backend_class->get_contact_list = _e_book_backend_get_contact_list;
+	backend_class->get_contact_uid_list = _e_book_backend_get_contact_uid_list;
 	backend_class->get_changes = _e_book_backend_get_changes;
 	backend_class->authenticate_user = _e_book_backend_authenticate_user;
 	backend_class->get_required_fields = _e_book_backend_get_required_fields;
diff --git a/addressbook/libedata-book/e-book-backend-sync.h b/addressbook/libedata-book/e-book-backend-sync.h
index 16fb4fb..e092884 100644
--- a/addressbook/libedata-book/e-book-backend-sync.h
+++ b/addressbook/libedata-book/e-book-backend-sync.h
@@ -45,6 +45,9 @@ struct _EBookBackendSyncClass {
 	void (*get_contact_list_sync) (EBookBackendSync *backend, EDataBook *book,
 							 guint32 opid,
 							 const gchar *query, GList **contacts, GError **perror);
+	void (*get_contact_uid_list_sync) (EBookBackendSync *backend, EDataBook *book,
+							     guint32 opid,
+							     const gchar *query, GList **contact_uids, GError **perror);
 	void (*get_changes_sync) (EBookBackendSync *backend, EDataBook *book,
 						    guint32 opid,
 						    const gchar *change_id, GList **changes, GError **perror);
@@ -84,6 +87,7 @@ void e_book_backend_sync_remove_contacts (EBookBackendSync *backend, EDataBook *
 void e_book_backend_sync_modify_contact  (EBookBackendSync *backend, EDataBook *book, guint32 opid, const gchar *vcard, EContact **contact, GError **perror);
 void e_book_backend_sync_get_contact (EBookBackendSync *backend, EDataBook *book, guint32 opid, const gchar *id, gchar **vcard, GError **perror);
 void e_book_backend_sync_get_contact_list (EBookBackendSync *backend, EDataBook *book, guint32 opid, const gchar *query, GList **contacts, GError **perror);
+void e_book_backend_sync_get_contact_uid_list (EBookBackendSync *backend, EDataBook *book, guint32 opid, const gchar *query, GList **contacts, GError **perror);
 void e_book_backend_sync_get_changes (EBookBackendSync *backend, EDataBook *book, guint32 opid, const gchar *change_id, GList **changes, GError **perror);
 void e_book_backend_sync_authenticate_user (EBookBackendSync *backend, EDataBook *book, guint32 opid, const gchar *user, const gchar *passwd, const gchar *auth_method, GError **perror);
 
diff --git a/addressbook/libedata-book/e-book-backend.c b/addressbook/libedata-book/e-book-backend.c
index 4357905..7af0ae0 100644
--- a/addressbook/libedata-book/e-book-backend.c
+++ b/addressbook/libedata-book/e-book-backend.c
@@ -481,6 +481,30 @@ e_book_backend_get_contact_list (EBookBackend *backend,
 }
 
 /**
+ * e_book_backend_get_contact_uid_list:
+ * @backend: an #EBookBackend
+ * @book: an #EDataBook
+ * @opid: the ID to use for this operation
+ * @query: the s-expression to match
+ *
+ * Executes a 'get contact uid list' request specified by @opid on @book
+ * using @backend.
+ **/
+void
+e_book_backend_get_contact_uid_list (EBookBackend *backend,
+				     EDataBook    *book,
+				     guint32       opid,
+				     const gchar   *query)
+{
+	g_return_if_fail (E_IS_BOOK_BACKEND (backend));
+	g_return_if_fail (E_IS_DATA_BOOK (book));
+	g_return_if_fail (query);
+	g_return_if_fail (E_BOOK_BACKEND_GET_CLASS (backend)->get_contact_uid_list);
+
+	(* E_BOOK_BACKEND_GET_CLASS (backend)->get_contact_uid_list) (backend, book, opid, query);
+}
+
+/**
  * e_book_backend_start_book_view:
  * @backend: an #EBookBackend
  * @book_view: the #EDataBookView to start
diff --git a/addressbook/libedata-book/e-book-backend.h b/addressbook/libedata-book/e-book-backend.h
index 6d96b1a..9cebf95 100644
--- a/addressbook/libedata-book/e-book-backend.h
+++ b/addressbook/libedata-book/e-book-backend.h
@@ -59,6 +59,7 @@ struct _EBookBackendClass {
 	void (*modify_contact)  (EBookBackend *backend, EDataBook *book, guint32 opid, const gchar *vcard);
 	void (*get_contact) (EBookBackend *backend, EDataBook *book, guint32 opid, const gchar *id);
 	void (*get_contact_list) (EBookBackend *backend, EDataBook *book, guint32 opid, const gchar *query);
+	void (*get_contact_uid_list) (EBookBackend *backend, EDataBook *book, guint32 opid, const gchar *query);
 	void (*start_book_view) (EBookBackend *backend, EDataBookView *book_view);
 	void (*stop_book_view) (EBookBackend *backend, EDataBookView *book_view);
 	void (*get_changes) (EBookBackend *backend, EDataBook *book, guint32 opid, const gchar *change_id);
@@ -131,6 +132,10 @@ void        e_book_backend_get_contact_list         (EBookBackend             *b
 						     EDataBook                *book,
 						     guint32                   opid,
 						     const gchar               *query);
+void        e_book_backend_get_contact_uid_list     (EBookBackend             *backend,
+						     EDataBook                *book,
+						     guint32                   opid,
+						     const gchar               *query);
 void        e_book_backend_get_changes              (EBookBackend             *backend,
 						     EDataBook                *book,
 						     guint32                   opid,
diff --git a/addressbook/libedata-book/e-data-book.c b/addressbook/libedata-book/e-data-book.c
index 9d58510..a88502a 100644
--- a/addressbook/libedata-book/e-data-book.c
+++ b/addressbook/libedata-book/e-data-book.c
@@ -56,6 +56,7 @@ typedef enum {
 	OP_ADD_CONTACT,
 	OP_GET_CONTACT,
 	OP_GET_CONTACTS,
+	OP_GET_CONTACT_UIDS,
 	OP_MODIFY_CONTACT,
 	OP_REMOVE_CONTACTS,
 	OP_GET_CHANGES,
@@ -80,6 +81,7 @@ typedef struct {
 		/* OP_GET_CONTACT */
 		gchar *uid;
 		/* OP_GET_CONTACTS */
+		/* OP_GET_CONTACT_UIDS */
 		gchar *query;
 		/* OP_MODIFY_CONTACT */
 		gchar **vcards;
@@ -123,6 +125,10 @@ operation_thread (gpointer data, gpointer user_data)
 		e_book_backend_get_contact_list (backend, op->book, op->id, op->d.query);
 		g_free (op->d.query);
 		break;
+	case OP_GET_CONTACT_UIDS:
+		e_book_backend_get_contact_uid_list (backend, op->book, op->id, op->d.query);
+		g_free (op->d.query);
+		break;
 	case OP_MODIFY_CONTACT:
 		e_book_backend_modify_contact (backend, op->book, op->id, op->d.vcard);
 		g_free (op->d.vcard);
@@ -412,6 +418,33 @@ e_data_book_respond_get_contact_list (EDataBook *book, guint32 opid, GError *err
 }
 
 static gboolean
+impl_Book_getContactUidList (EGdbusBook *object, GDBusMethodInvocation *invocation, const gchar *query, EDataBook *book)
+{
+	OperationData *op;
+
+	if (query == NULL || query[0] == '\0') {
+		GError *error = e_data_book_create_error (E_DATA_BOOK_STATUS_INVALID_QUERY, NULL);
+		/* Translators: The '%s' is replaced with a detailed error message */
+		data_book_return_error (invocation, error, _("Empty query: %s"));
+		g_error_free (error);
+		return TRUE;
+	}
+
+	op = op_new (OP_GET_CONTACT_UIDS, book, invocation);
+	op->d.query = g_strdup (query);
+	g_thread_pool_push (op_pool, op, NULL);
+
+	return TRUE;
+}
+
+void
+e_data_book_respond_get_contact_uid_list (EDataBook *book, guint32 opid, GError *error, GList *uids)
+{
+	/* Translators: The '%s' is replaced with a detailed error message */
+	return_error_and_list (book->priv->gdbus_object, e_gdbus_book_complete_get_contact_uid_list, opid, error, _("Cannot get contact uid list: %s"), uids, TRUE);
+}
+
+static gboolean
 impl_Book_authenticateUser (EGdbusBook *object, GDBusMethodInvocation *invocation, const gchar *IN_user, const gchar *IN_passwd, const gchar *IN_auth_method, EDataBook *book)
 {
 	OperationData *op;
@@ -844,6 +877,7 @@ e_data_book_init (EDataBook *ebook)
 	g_signal_connect (gdbus_object, "handle-remove", G_CALLBACK (impl_Book_remove), ebook);
 	g_signal_connect (gdbus_object, "handle-get-contact", G_CALLBACK (impl_Book_getContact), ebook);
 	g_signal_connect (gdbus_object, "handle-get-contact-list", G_CALLBACK (impl_Book_getContactList), ebook);
+	g_signal_connect (gdbus_object, "handle-get-contact-uid-list", G_CALLBACK (impl_Book_getContactUidList), ebook);
 	g_signal_connect (gdbus_object, "handle-authenticate-user", G_CALLBACK (impl_Book_authenticateUser), ebook);
 	g_signal_connect (gdbus_object, "handle-add-contact", G_CALLBACK (impl_Book_addContact), ebook);
 	g_signal_connect (gdbus_object, "handle-remove-contacts", G_CALLBACK (impl_Book_removeContacts), ebook);
diff --git a/addressbook/libedata-book/e-data-book.h b/addressbook/libedata-book/e-data-book.h
index d938ec6..548bd2c 100644
--- a/addressbook/libedata-book/e-data-book.h
+++ b/addressbook/libedata-book/e-data-book.h
@@ -150,6 +150,10 @@ void                    e_data_book_respond_get_contact_list (EDataBook *book,
 							      guint32 opid,
 							      GError *error,
 							      GList *cards);
+void                    e_data_book_respond_get_contact_uid_list (EDataBook *book,
+							          guint32 opid,
+							          GError *error,
+							          GList *uids);
 void                    e_data_book_respond_get_changes    (EDataBook *book,
 							    guint32 opid,
 							    GError *error,
diff --git a/addressbook/libegdbus/e-gdbus-egdbusbook.c b/addressbook/libegdbus/e-gdbus-egdbusbook.c
index 43c5248..3bb8beb 100644
--- a/addressbook/libegdbus/e-gdbus-egdbusbook.c
+++ b/addressbook/libegdbus/e-gdbus-egdbusbook.c
@@ -71,6 +71,7 @@ enum
   __REMOVE_METHOD,
   __GET_CONTACT_METHOD,
   __GET_CONTACT_LIST_METHOD,
+  __GET_CONTACT_UID_LIST_METHOD,
   __AUTHENTICATE_USER_METHOD,
   __ADD_CONTACT_METHOD,
   __REMOVE_CONTACTS_METHOD,
@@ -262,6 +263,7 @@ e_gdbus_book_default_init (EGdbusBookIface *iface)
   g_hash_table_insert (_method_name_to_id, (gpointer) "remove", GUINT_TO_POINTER (__REMOVE_METHOD));
   g_hash_table_insert (_method_name_to_id, (gpointer) "getContact", GUINT_TO_POINTER (__GET_CONTACT_METHOD));
   g_hash_table_insert (_method_name_to_id, (gpointer) "getContactList", GUINT_TO_POINTER (__GET_CONTACT_LIST_METHOD));
+  g_hash_table_insert (_method_name_to_id, (gpointer) "getContactUidList", GUINT_TO_POINTER (__GET_CONTACT_UID_LIST_METHOD));
   g_hash_table_insert (_method_name_to_id, (gpointer) "authenticateUser", GUINT_TO_POINTER (__AUTHENTICATE_USER_METHOD));
   g_hash_table_insert (_method_name_to_id, (gpointer) "addContact", GUINT_TO_POINTER (__ADD_CONTACT_METHOD));
   g_hash_table_insert (_method_name_to_id, (gpointer) "removeContacts", GUINT_TO_POINTER (__REMOVE_CONTACTS_METHOD));
@@ -470,6 +472,34 @@ e_gdbus_book_default_init (EGdbusBookIface *iface)
                   2,
                   G_TYPE_DBUS_METHOD_INVOCATION,
                   G_TYPE_STRING);
+    
+  /**
+   * EGdbusBook::handle-get-contact-uid-list:
+   * @object: The exported object emitting the signal.
+   * @invocation: A #GDBusMethodInvocation object that can be used to return a value or error.
+   * @query: Parameter.
+   *
+   * On exported objects, this signal is emitted when a remote process (identified by @invocation) invokes the <literal>getContactUidList</literal> D-Bus method on @object. Use e_gdbus_book_complete_get_contact_uid_list() to return a value or g_dbus_method_invocation_return_error() to return an error.
+   *
+   * The signal is emitted in the thread-default main loop of the thread that e_gdbus_book_register_object() was called from.
+   *
+   * On proxies, this signal is never emitted.
+   *
+   * Returns: %TRUE if you want to handle the method call (will stop further handlers from being called), %FALSE otherwise.
+   */
+  signals[__GET_CONTACT_UID_LIST_METHOD] =
+    g_signal_new ("handle-get-contact-uid-list",
+                  G_TYPE_FROM_INTERFACE (iface),
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (EGdbusBookIface, handle_get_contact_uid_list),
+                  g_signal_accumulator_true_handled,
+                  NULL,
+                  _e_gdbus_gdbus_cclosure_marshaller_BOOLEAN__OBJECT_STRING,
+                  G_TYPE_BOOLEAN,
+                  2,
+                  G_TYPE_DBUS_METHOD_INVOCATION,
+                  G_TYPE_STRING);
+    
   /**
    * EGdbusBook::handle-authenticate-user:
    * @object: The exported object emitting the signal.
@@ -1229,6 +1259,126 @@ _out:
 }
 
 /**
+ * e_gdbus_book_call_get_contact_uid_list:
+ * @proxy: A #EGdbusBook.
+ * @in_query: Method parameter.
+ * @cancellable: A #GCancellable or %NULL.
+ * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL if you don't care about the result of the method invocation.
+ * @user_data: Data to pass to @callback.
+ *
+ * Invokes the <literal>org.gnome.evolution.dataserver.addressbook.Book.getContactUidList</literal>
+ * D-Bus method on the remote object represented by @proxy.
+ *
+ * This is an asynchronous method. When the operation is finished,
+ * callback will be invoked in the thread-default main loop of the
+ * thread you are calling this method from. You can then call
+ * e_gdbus_book_call_get_contact_uid_list_finish() to get the result of the operation.
+ *
+ * See e_gdbus_book_call_get_contact_uid_list_sync() for the synchronous version of this method.
+ */
+void e_gdbus_book_call_get_contact_uid_list (
+        EGdbusBook *proxy,
+        const gchar *in_query,
+        GCancellable *cancellable,
+        GAsyncReadyCallback callback,
+        gpointer user_data)
+{
+  GVariant *_params;
+  _params = g_variant_new ("(s)",
+                           in_query);
+  g_dbus_proxy_call (G_DBUS_PROXY (proxy),
+                     "getContactUidList",
+                     _params,
+                     G_DBUS_CALL_FLAGS_NONE,
+                     -1,
+                     cancellable,
+                     callback,
+                     user_data);
+}
+
+/**
+ * e_gdbus_book_call_get_contact_uid_list_finish:
+ * @proxy: A #EGdbusBook.
+ * @out_uids: Return location for out parameter or %NULL. Free with g_strfreev().
+ * @res: A #GAsyncResult obtained from the #GAsyncReadyCallback passed to e_gdbus_book_call_get_contact_uid_list().
+ * @error: Return location for error or %NULL.
+ *
+ * Finishes invoking the <literal>org.gnome.evolution.dataserver.addressbook.Book.getContactUidList</literal>
+ * D-Bus method on the remote object represented by @proxy.
+ *
+ * Returns: %TRUE if the call succeeded, %FALSE if @error is set.
+ */
+gboolean e_gdbus_book_call_get_contact_uid_list_finish (
+        EGdbusBook *proxy,
+        gchar ***out_uids,
+        GAsyncResult *res,
+        GError **error)
+{
+  gboolean _ret = FALSE;
+  GVariant *_result;
+  _result = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error);
+  if (_result == NULL)
+    goto _out;
+  {
+    g_variant_get (_result,
+                   "(^as)",
+                   out_uids);
+  }
+  g_variant_unref (_result);
+  _ret = TRUE;
+_out:
+  return _ret;
+}
+
+/**
+ * e_gdbus_book_call_get_contact_uid_list_sync:
+ * @proxy: A #EGdbusBook.
+ * @in_query: Method parameter.
+ * @out_uids: Return location for out parameter or %NULL. Free with g_strfreev().
+ * @cancellable: A #GCancellable or %NULL.
+ * @error: Return location for error or %NULL.
+ *
+ * Synchronously invokes the <literal>org.gnome.evolution.dataserver.addressbook.Book.getContactUidList</literal>
+ * D-Bus method on the remote object represented by @proxy.
+ *
+ * The calling thread is blocked until a reply is received. See
+ * e_gdbus_book_call_get_contact_uid_list() for the asynchronous version of this method.
+ *
+ * Returns: %TRUE if the call succeeded, %FALSE if @error is set.
+ */
+gboolean e_gdbus_book_call_get_contact_uid_list_sync (
+        EGdbusBook *proxy,
+        const gchar *in_query,
+        gchar ***out_uids,
+        GCancellable *cancellable,
+        GError **error)
+{
+  gboolean _ret = FALSE;
+  GVariant *_params;
+  GVariant *_result;
+  _params = g_variant_new ("(s)",
+                           in_query);
+  _result = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy),
+                                   "getContactUidList",
+                                   _params,
+                                   G_DBUS_CALL_FLAGS_NONE,
+                                   -1,
+                                   cancellable,
+                                   error);
+  if (_result == NULL)
+    goto _out;
+  {
+    g_variant_get (_result,
+                   "(^as)",
+                   out_uids);
+  }
+  g_variant_unref (_result);
+  _ret = TRUE;
+_out:
+  return _ret;
+}
+
+/**
  * e_gdbus_book_call_authenticate_user:
  * @proxy: A #EGdbusBook.
  * @in_user: Method parameter.
@@ -2671,6 +2821,31 @@ void e_gdbus_book_complete_get_contact_list (
 }
 
 /**
+ * e_gdbus_book_complete_get_contact_uid_list:
+ * @object: A #EGdbusBook.
+ * @invocation: A #GDBusMethodInvocation.
+ * @out_uids: Value to return.
+ *
+ * Completes handling the <literal>org.gnome.evolution.dataserver.addressbook.Book.getContactUidList</literal>
+ * D-Bus method invocation by returning a value.
+ *
+ * If you want to return an error, use g_dbus_method_invocation_return_error()
+ * or similar instead.
+ *
+ * This method will free @invocation, you cannot use it afterwards.
+ */
+void e_gdbus_book_complete_get_contact_uid_list (
+        EGdbusBook *object,
+        GDBusMethodInvocation *invocation,
+        const gchar * const *out_uids)
+{
+  GVariant *_params;
+  _params = g_variant_new ("(^as)",
+                           out_uids);
+  g_dbus_method_invocation_return_value (invocation, _params);
+}
+
+/**
  * e_gdbus_book_complete_authenticate_user:
  * @object: A #EGdbusBook.
  * @invocation: A #GDBusMethodInvocation.
@@ -3147,6 +3322,41 @@ static const GDBusMethodInfo e_gdbus_book_method_getContactList =
   (GDBusAnnotationInfo **) NULL,
 };
 
+static const GDBusArgInfo e_gdbus_book_method_in_getContactUidList_query =
+{
+  -1,
+  (gchar *) "query",
+  (gchar *) "s",
+  (GDBusAnnotationInfo **) NULL,
+};
+static const GDBusArgInfo * const e_gdbus_book_method_in_getContactUidList_arg_pointers[] =
+{
+  &e_gdbus_book_method_in_getContactUidList_query,
+  NULL
+};
+
+static const GDBusArgInfo e_gdbus_book_method_out_getContactUidList_uids =
+{
+  -1,
+  (gchar *) "uids",
+  (gchar *) "as",
+  (GDBusAnnotationInfo **) NULL,
+};
+static const GDBusArgInfo * const e_gdbus_book_method_out_getContactUidList_arg_pointers[] =
+{
+  &e_gdbus_book_method_out_getContactUidList_uids,
+  NULL
+};
+
+static const GDBusMethodInfo e_gdbus_book_method_getContactUidList =
+{
+  -1,
+  (gchar *) "getContactUidList",
+  (GDBusArgInfo **) &e_gdbus_book_method_in_getContactUidList_arg_pointers,
+  (GDBusArgInfo **) &e_gdbus_book_method_out_getContactUidList_arg_pointers,
+  (GDBusAnnotationInfo **) NULL,
+};
+
 static const GDBusArgInfo e_gdbus_book_method_in_authenticateUser_user =
 {
   -1,
@@ -3454,6 +3664,7 @@ static const GDBusMethodInfo * const e_gdbus_book_method_info_pointers[] =
   &e_gdbus_book_method_remove,
   &e_gdbus_book_method_getContact,
   &e_gdbus_book_method_getContactList,
+  &e_gdbus_book_method_getContactUidList,
   &e_gdbus_book_method_authenticateUser,
   &e_gdbus_book_method_addContact,
   &e_gdbus_book_method_removeContacts,
@@ -3537,6 +3748,7 @@ handle_method_call (GDBusConnection       *connection,
       break;
 
     case __GET_CONTACT_LIST_METHOD:
+    case __GET_CONTACT_UID_LIST_METHOD:
       {
         EGdbusBook *object = E_GDBUS_BOOK (user_data);
         gboolean handled;
diff --git a/addressbook/libegdbus/e-gdbus-egdbusbook.h b/addressbook/libegdbus/e-gdbus-egdbusbook.h
index 767dbea..b55f9dd 100644
--- a/addressbook/libegdbus/e-gdbus-egdbusbook.h
+++ b/addressbook/libegdbus/e-gdbus-egdbusbook.h
@@ -35,6 +35,7 @@ typedef struct _EGdbusBook EGdbusBook; /* Dummy typedef */
  * @handle_remove: Handler for the #EGdbusBook::handle-remove signal.
  * @handle_get_contact: Handler for the #EGdbusBook::handle-get-contact signal.
  * @handle_get_contact_list: Handler for the #EGdbusBook::handle-get-contact-list signal.
+ * @handle_get_contact_uid_list: Handler for the #EGdbusBook::handle-get-contact-uid-list signal.
  * @handle_authenticate_user: Handler for the #EGdbusBook::handle-authenticate-user signal.
  * @handle_add_contact: Handler for the #EGdbusBook::handle-add-contact signal.
  * @handle_remove_contacts: Handler for the #EGdbusBook::handle-remove-contacts signal.
@@ -201,6 +202,10 @@ struct _EGdbusBookIface
         EGdbusBook *object,
         GDBusMethodInvocation *invocation,
         const gchar *in_query);
+  gboolean (*handle_get_contact_uid_list) (
+        EGdbusBook *object,
+        GDBusMethodInvocation *invocation,
+        const gchar *in_query);
   gboolean (*handle_authenticate_user) (
         EGdbusBook *object,
         GDBusMethodInvocation *invocation,
@@ -325,6 +330,26 @@ gboolean e_gdbus_book_call_get_contact_list_sync (
         GCancellable *cancellable,
         GError **error);
 
+void e_gdbus_book_call_get_contact_uid_list (
+        EGdbusBook *proxy,
+        const gchar *in_query,
+        GCancellable *cancellable,
+        GAsyncReadyCallback callback,
+        gpointer user_data);
+
+gboolean e_gdbus_book_call_get_contact_uid_list_finish (
+        EGdbusBook *proxy,
+        gchar ***out_uids,
+        GAsyncResult *res,
+        GError **error);
+
+gboolean e_gdbus_book_call_get_contact_uid_list_sync (
+        EGdbusBook *proxy,
+        const gchar *in_query,
+        gchar ***out_uids,
+        GCancellable *cancellable,
+        GError **error);
+
 void e_gdbus_book_call_authenticate_user (
         EGdbusBook *proxy,
         const gchar *in_user,
@@ -568,6 +593,11 @@ void e_gdbus_book_complete_get_contact_list (
         GDBusMethodInvocation *invocation,
         const gchar * const *out_vcards);
 
+void e_gdbus_book_complete_get_contact_uid_list (
+        EGdbusBook *object,
+        GDBusMethodInvocation *invocation,
+        const gchar * const *out_uids);
+
 void e_gdbus_book_complete_authenticate_user (
         EGdbusBook *object,
         GDBusMethodInvocation *invocation);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]