[evolution-data-server] EDataBookView cleanups.



commit da21a70d03050292d77029c98ac6afbf7ea71075
Author: Matthew Barnes <mbarnes redhat com>
Date:   Fri Oct 12 13:30:06 2012 -0400

    EDataBookView cleanups.
    
    Some minor API changes with this:
    
       e_data_book_view_get_card_sexp() is now e_data_book_view_get_sexp().
    
       e_data_book_view_get_card_query() is dropped.  Instead use:
    
           sexp = e_data_book_view_get_sexp (view);
           query = e_book_backend_sexp_text (sexp);

 addressbook/backends/file/e-book-backend-file.c    |   34 +-
 addressbook/backends/ldap/e-book-backend-ldap.c    |   10 +-
 addressbook/backends/vcf/e-book-backend-vcf.c      |   12 +-
 .../backends/webdav/e-book-backend-webdav.c        |   10 +-
 addressbook/libedata-book/e-data-book-view.c       | 1114 +++++++++++---------
 addressbook/libedata-book/e-data-book-view.h       |   25 +-
 addressbook/libedata-book/e-data-book.c            |    2 +-
 .../libedata-book/libedata-book-sections.txt       |    3 +-
 8 files changed, 667 insertions(+), 543 deletions(-)
---
diff --git a/addressbook/backends/file/e-book-backend-file.c b/addressbook/backends/file/e-book-backend-file.c
index b31d251..9bace4e 100644
--- a/addressbook/backends/file/e-book-backend-file.c
+++ b/addressbook/backends/file/e-book-backend-file.c
@@ -1273,7 +1273,7 @@ e_book_backend_file_get_contact_list (EBookBackendSync *backend,
 	DBC            *dbc;
 	gint            db_error;
 	DBT  id_dbt, vcard_dbt;
-	EBookBackendSExp *card_sexp = NULL;
+	EBookBackendSExp *sexp = NULL;
 	gboolean search_needed;
 	const gchar *search = query;
 	GSList *contact_list = NULL, *l;
@@ -1326,8 +1326,8 @@ e_book_backend_file_get_contact_list (EBookBackendSync *backend,
 		if (!strcmp (search, "(contains \"x-evolution-any-field\" \"\")"))
 			search_needed = FALSE;
 
-		card_sexp = e_book_backend_sexp_new (search);
-		if (!card_sexp) {
+		sexp = e_book_backend_sexp_new (search);
+		if (!sexp) {
 			g_propagate_error (perror, EDB_ERROR (INVALID_QUERY));
 			return;
 		}
@@ -1354,7 +1354,7 @@ e_book_backend_file_get_contact_list (EBookBackendSync *backend,
 			    (id_dbt.size != strlen (E_BOOK_BACKEND_FILE_REVISION_NAME) + 1
 			     || strcmp (id_dbt.data, E_BOOK_BACKEND_FILE_REVISION_NAME))) {
 
-				if ((!search_needed) || (card_sexp != NULL && e_book_backend_sexp_match_vcard  (card_sexp, vcard_dbt.data))) {
+				if ((!search_needed) || (sexp != NULL && e_book_backend_sexp_match_vcard  (sexp, vcard_dbt.data))) {
 					contact_list = g_slist_prepend (contact_list, vcard_dbt.data);
 				} else {
 					free (vcard_dbt.data);
@@ -1366,7 +1366,7 @@ e_book_backend_file_get_contact_list (EBookBackendSync *backend,
 			db_error = dbc->c_get (dbc, &id_dbt, &vcard_dbt, DB_NEXT);
 
 		}
-		g_object_unref (card_sexp);
+		g_object_unref (sexp);
 
 		if (db_error == DB_NOTFOUND) {
 			/* Success */
@@ -1397,7 +1397,7 @@ e_book_backend_file_get_contact_list_uids (EBookBackendSync *backend,
 	DBC            *dbc;
 	gint            db_error;
 	DBT  id_dbt, vcard_dbt;
-	EBookBackendSExp *card_sexp = NULL;
+	EBookBackendSExp *sexp = NULL;
 	gboolean search_needed;
 	const gchar *search = query;
 	GSList *uids = NULL;
@@ -1419,8 +1419,8 @@ e_book_backend_file_get_contact_list_uids (EBookBackendSync *backend,
 		if (!strcmp (search, "(contains \"x-evolution-any-field\" \"\")"))
 			search_needed = FALSE;
 
-		card_sexp = e_book_backend_sexp_new (search);
-		if (!card_sexp) {
+		sexp = e_book_backend_sexp_new (search);
+		if (!sexp) {
 			g_propagate_error (perror, EDB_ERROR (INVALID_QUERY));
 			return;
 		}
@@ -1447,7 +1447,7 @@ e_book_backend_file_get_contact_list_uids (EBookBackendSync *backend,
 			    (id_dbt.size != strlen (E_BOOK_BACKEND_FILE_REVISION_NAME) + 1
 			     || strcmp (id_dbt.data, E_BOOK_BACKEND_FILE_REVISION_NAME))) {
 
-				if ((!search_needed) || (card_sexp != NULL && e_book_backend_sexp_match_vcard  (card_sexp, vcard_dbt.data))) {
+				if ((!search_needed) || (sexp != NULL && e_book_backend_sexp_match_vcard  (sexp, vcard_dbt.data))) {
 					uids = g_slist_prepend (uids, g_strdup (id_dbt.data));
 				}
 			}
@@ -1457,7 +1457,7 @@ e_book_backend_file_get_contact_list_uids (EBookBackendSync *backend,
 			db_error = dbc->c_get (dbc, &id_dbt, &vcard_dbt, DB_NEXT);
 
 		}
-		g_object_unref (card_sexp);
+		g_object_unref (sexp);
 
 		if (db_error == DB_NOTFOUND) {
 			/* Success */
@@ -1529,6 +1529,7 @@ book_view_thread (gpointer data)
 	EDataBookView *book_view;
 	FileBackendSearchClosure *closure;
 	EBookBackendFile *bf;
+	EBookBackendSExp *sexp;
 	const gchar *query;
 	DB  *db;
 	DBT id_dbt, vcard_dbt;
@@ -1555,8 +1556,10 @@ book_view_thread (gpointer data)
 	 * when/if it's stopped */
 	g_object_ref (book_view);
 
-	db                 = bf->priv->file_db;
-	query              = e_data_book_view_get_card_query (book_view);
+	sexp = e_data_book_view_get_sexp (book_view);
+	query = e_book_backend_sexp_text (sexp);
+
+	db = bf->priv->file_db;
 	fields_of_interest = e_data_book_view_get_fields_of_interest (book_view);
 
 	if (!db) {
@@ -2203,11 +2206,16 @@ view_notify_update (EBookBackendFile *backend,
                     EDataBookView *view,
                     EContact *contact)
 {
+	EBookBackendSExp *sexp;
 	GHashTable *fields   = e_data_book_view_get_fields_of_interest (view);
+	const gchar *query;
 	gboolean    notified = FALSE;
 	gboolean    with_all_required_fields = FALSE;
 
-	if (e_book_backend_sqlitedb_is_summary_query (e_data_book_view_get_card_query (view)) &&
+	sexp = e_data_book_view_get_sexp (view);
+	query = e_book_backend_sexp_text (sexp);
+
+	if (e_book_backend_sqlitedb_is_summary_query (query) &&
 	    e_book_backend_sqlitedb_is_summary_fields (fields)) {
 
 		const gchar *uid = e_contact_get_const (contact, E_CONTACT_UID);
diff --git a/addressbook/backends/ldap/e-book-backend-ldap.c b/addressbook/backends/ldap/e-book-backend-ldap.c
index eade88e..5624d02 100644
--- a/addressbook/backends/ldap/e-book-backend-ldap.c
+++ b/addressbook/backends/ldap/e-book-backend-ldap.c
@@ -4785,6 +4785,8 @@ e_book_backend_ldap_search (EBookBackendLDAP *bl,
                             EDataBook *book,
                             EDataBookView *view)
 {
+	EBookBackendSExp *sexp;
+	const gchar *query;
 	gchar *ldap_query;
 	GList *contacts;
 	GList *l;
@@ -4796,6 +4798,9 @@ e_book_backend_ldap_search (EBookBackendLDAP *bl,
 		g_get_current_time (&start);
 	}
 
+	sexp = e_data_book_view_get_sexp (view);
+	query = e_book_backend_sexp_text (sexp);
+
 	if (!e_backend_get_online (E_BACKEND (bl))) {
 		if (!(bl->priv->marked_for_offline && bl->priv->cache)) {
 			GError *edb_err = EDB_ERROR (REPOSITORY_OFFLINE);
@@ -4804,8 +4809,7 @@ e_book_backend_ldap_search (EBookBackendLDAP *bl,
 			return;
 		}
 
-		contacts = e_book_backend_cache_get_contacts (bl->priv->cache,
-							      e_data_book_view_get_card_query (view));
+		contacts = e_book_backend_cache_get_contacts (bl->priv->cache, query);
 
 		for (l = contacts; l; l = g_list_next (l)) {
 			EContact *contact = l->data;
@@ -4819,7 +4823,7 @@ e_book_backend_ldap_search (EBookBackendLDAP *bl,
 		return;
 	}
 
-	ldap_query = e_book_backend_ldap_build_query (bl, e_data_book_view_get_card_query (view));
+	ldap_query = e_book_backend_ldap_build_query (bl, query);
 
 	/* search for nonempty full names */
 	if (!ldap_query && can_browse ((EBookBackend *) bl))
diff --git a/addressbook/backends/vcf/e-book-backend-vcf.c b/addressbook/backends/vcf/e-book-backend-vcf.c
index 9d6baf8..3da4b63 100644
--- a/addressbook/backends/vcf/e-book-backend-vcf.c
+++ b/addressbook/backends/vcf/e-book-backend-vcf.c
@@ -415,7 +415,7 @@ e_book_backend_vcf_get_contact (EBookBackendSync *backend,
 typedef struct {
 	EBookBackendVCF      *bvcf;
 	gboolean            search_needed;
-	EBookBackendSExp *card_sexp;
+	EBookBackendSExp *sexp;
 	GSList              *list;
 } GetContactListClosure;
 
@@ -423,7 +423,7 @@ static void
 foreach_get_contact_compare (gchar *vcard_string,
                              GetContactListClosure *closure)
 {
-	if ((!closure->search_needed) || e_book_backend_sexp_match_vcard  (closure->card_sexp, vcard_string)) {
+	if ((!closure->search_needed) || e_book_backend_sexp_match_vcard  (closure->sexp, vcard_string)) {
 		closure->list = g_slist_append (closure->list, g_strdup (vcard_string));
 	}
 }
@@ -442,12 +442,12 @@ e_book_backend_vcf_get_contact_list (EBookBackendSync *backend,
 
 	closure.bvcf = bvcf;
 	closure.search_needed = strcmp (search, "(contains \"x-evolution-any-field\" \"\")");
-	closure.card_sexp = e_book_backend_sexp_new (search);
+	closure.sexp = e_book_backend_sexp_new (search);
 	closure.list = NULL;
 
 	g_list_foreach (bvcf->priv->contact_list, (GFunc) foreach_get_contact_compare, &closure);
 
-	g_object_unref (closure.card_sexp);
+	g_object_unref (closure.sexp);
 
 	*contacts = closure.list;
 }
@@ -495,6 +495,7 @@ book_view_thread (gpointer data)
 {
 	EDataBookView *book_view = data;
 	VCFBackendSearchClosure *closure = get_closure (book_view);
+	EBookBackendSExp *sexp;
 	const gchar *query;
 	GList *l;
 
@@ -502,7 +503,8 @@ book_view_thread (gpointer data)
 	 * when/if it's stopped */
 	g_object_ref (book_view);
 
-	query = e_data_book_view_get_card_query (book_view);
+	sexp = e_data_book_view_get_sexp (book_view);
+	query = e_book_backend_sexp_text (sexp);
 
 	if ( !strcmp (query, "(contains \"x-evolution-any-field\" \"\")"))
 		e_data_book_view_notify_progress (book_view, -1, _("Loading..."));
diff --git a/addressbook/backends/webdav/e-book-backend-webdav.c b/addressbook/backends/webdav/e-book-backend-webdav.c
index 5e9cdaf..b4b3917 100644
--- a/addressbook/backends/webdav/e-book-backend-webdav.c
+++ b/addressbook/backends/webdav/e-book-backend-webdav.c
@@ -1069,10 +1069,16 @@ e_book_backend_webdav_start_view (EBookBackend *backend,
 {
 	EBookBackendWebdav        *webdav = E_BOOK_BACKEND_WEBDAV (backend);
 	EBookBackendWebdavPrivate *priv   = webdav->priv;
-	const gchar *query = e_data_book_view_get_card_query (book_view);
-	GList *contacts = e_book_backend_cache_get_contacts (priv->cache, query);
+	EBookBackendSExp *sexp;
+	const gchar *query;
+	GList *contacts;
 	GList *l;
 
+	sexp = e_data_book_view_get_sexp (book_view);
+	query = e_book_backend_sexp_text (sexp);
+
+	contacts = e_book_backend_cache_get_contacts (priv->cache, query);
+
 	for (l = contacts; l != NULL; l = g_list_next (l)) {
 		EContact *contact = l->data;
 		e_data_book_view_notify_update (book_view, contact);
diff --git a/addressbook/libedata-book/e-data-book-view.c b/addressbook/libedata-book/e-data-book-view.c
index c391a75..e7698cf 100644
--- a/addressbook/libedata-book/e-data-book-view.c
+++ b/addressbook/libedata-book/e-data-book-view.c
@@ -37,12 +37,11 @@
 	(G_TYPE_INSTANCE_GET_PRIVATE \
 	((obj), E_TYPE_DATA_BOOK_VIEW, EDataBookViewPrivate))
 
-static void reset_array (GArray *array);
-static void ensure_pending_flush_timeout (EDataBookView *view);
+/* how many items can be hold in a cache, before propagated to UI */
+#define THRESHOLD_ITEMS 32
 
-G_DEFINE_TYPE (EDataBookView, e_data_book_view, G_TYPE_OBJECT);
-#define THRESHOLD_ITEMS   32	/* how many items can be hold in a cache, before propagated to UI */
-#define THRESHOLD_SECONDS  2	/* how long to wait until notifications are propagated to UI; in seconds */
+/* how long to wait until notifications are propagated to UI; in seconds */
+#define THRESHOLD_SECONDS 2
 
 struct _EDataBookViewPrivate {
 	EGdbusBookView *gdbus_object;
@@ -50,8 +49,7 @@ struct _EDataBookViewPrivate {
 	EDataBook *book;
 	EBookBackend *backend;
 
-	gchar * card_query;
-	EBookBackendSExp *card_sexp;
+	EBookBackendSExp *sexp;
 	EBookClientViewFlags flags;
 
 	gboolean running;
@@ -70,19 +68,13 @@ struct _EDataBookViewPrivate {
 	GHashTable *fields_of_interest;
 };
 
-static void e_data_book_view_dispose (GObject *object);
-static void e_data_book_view_finalize (GObject *object);
-
-static void
-e_data_book_view_class_init (EDataBookViewClass *class)
-{
-	GObjectClass *object_class = G_OBJECT_CLASS (class);
-
-	g_type_class_add_private (class, sizeof (EDataBookViewPrivate));
+G_DEFINE_TYPE (EDataBookView, e_data_book_view, G_TYPE_OBJECT);
 
-	object_class->dispose = e_data_book_view_dispose;
-	object_class->finalize = e_data_book_view_finalize;
-}
+enum {
+	PROP_0,
+	PROP_BACKEND,
+	PROP_SEXP
+};
 
 static guint
 str_ic_hash (gconstpointer key)
@@ -91,12 +83,11 @@ str_ic_hash (gconstpointer key)
 	const gchar *str = key;
 	gint ii;
 
-	if (!str)
+	if (str == NULL)
 		return hash;
 
-	for (ii = 0; str[ii]; ii++) {
+	for (ii = 0; str[ii] != '\0'; ii++)
 		hash = hash * 33 + g_ascii_tolower (str[ii]);
-	}
 
 	return hash;
 }
@@ -105,16 +96,17 @@ static gboolean
 str_ic_equal (gconstpointer a,
               gconstpointer b)
 {
-	const gchar *stra = a, *strb = b;
+	const gchar *stra = a;
+	const gchar *strb = b;
 	gint ii;
 
-	if (!stra && !strb)
+	if (stra == NULL && strb == NULL)
 		return TRUE;
 
-	if (!stra || !strb)
+	if (stra == NULL || strb == NULL)
 		return FALSE;
 
-	for (ii = 0; stra[ii] && strb[ii]; ii++) {
+	for (ii = 0; stra[ii] != '\0' && strb[ii] != '\0'; ii++) {
 		if (g_ascii_tolower (stra[ii]) != g_ascii_tolower (strb[ii]))
 			return FALSE;
 	}
@@ -122,95 +114,72 @@ str_ic_equal (gconstpointer a,
 	return stra[ii] == strb[ii];
 }
 
-/**
- * e_data_book_view_register_gdbus_object:
- *
- * Since: 2.32
- **/
-guint
-e_data_book_view_register_gdbus_object (EDataBookView *query,
-                                        GDBusConnection *connection,
-                                        const gchar *object_path,
-                                        GError **error)
-{
-	g_return_val_if_fail (query != NULL, 0);
-	g_return_val_if_fail (E_IS_DATA_BOOK_VIEW (query), 0);
-	g_return_val_if_fail (connection != NULL, 0);
-	g_return_val_if_fail (object_path != NULL, 0);
-
-	return e_gdbus_book_view_register_object (query->priv->gdbus_object, connection, object_path, error);
-}
-
 static void
-book_destroyed_cb (gpointer data,
-                   GObject *dead)
+reset_array (GArray *array)
 {
-	EDataBookView *view = E_DATA_BOOK_VIEW (data);
-	EDataBookViewPrivate *priv = view->priv;
-
-	/* The book has just died, so unset the pointer so we don't try and remove a
-	 * dead weak reference. */
-	view->priv->book = NULL;
+	gint i = 0;
+	gchar *tmp = NULL;
 
-	/* If the view is running stop it here. */
-	if (priv->running) {
-		e_book_backend_stop_view (priv->backend, view);
-		priv->running = FALSE;
-		priv->complete = FALSE;
+	/* Free stored strings */
+	for (i = 0; i < array->len; i++) {
+		tmp = g_array_index (array, gchar *, i);
+		g_free (tmp);
 	}
+
+	/* Force the array size to 0 */
+	g_array_set_size (array, 0);
 }
 
 static void
 send_pending_adds (EDataBookView *view)
 {
-	EDataBookViewPrivate *priv = view->priv;
-
-	if (priv->adds->len == 0)
+	if (view->priv->adds->len == 0)
 		return;
 
-	e_gdbus_book_view_emit_objects_added (view->priv->gdbus_object, (const gchar * const *) priv->adds->data);
-	reset_array (priv->adds);
+	e_gdbus_book_view_emit_objects_added (
+		view->priv->gdbus_object,
+		(const gchar * const *) view->priv->adds->data);
+	reset_array (view->priv->adds);
 }
 
 static void
 send_pending_changes (EDataBookView *view)
 {
-	EDataBookViewPrivate *priv = view->priv;
-
-	if (priv->changes->len == 0)
+	if (view->priv->changes->len == 0)
 		return;
 
-	e_gdbus_book_view_emit_objects_modified (view->priv->gdbus_object, (const gchar * const *) priv->changes->data);
-	reset_array (priv->changes);
+	e_gdbus_book_view_emit_objects_modified (
+		view->priv->gdbus_object,
+		(const gchar * const *) view->priv->changes->data);
+	reset_array (view->priv->changes);
 }
 
 static void
 send_pending_removes (EDataBookView *view)
 {
-	EDataBookViewPrivate *priv = view->priv;
-
-	if (priv->removes->len == 0)
+	if (view->priv->removes->len == 0)
 		return;
 
-	e_gdbus_book_view_emit_objects_removed (view->priv->gdbus_object, (const gchar * const *) priv->removes->data);
-	reset_array (priv->removes);
+	e_gdbus_book_view_emit_objects_removed (
+		view->priv->gdbus_object,
+		(const gchar * const *) view->priv->removes->data);
+	reset_array (view->priv->removes);
 }
 
 static gboolean
 pending_flush_timeout_cb (gpointer data)
 {
 	EDataBookView *view = data;
-	EDataBookViewPrivate *priv = view->priv;
 
-	g_mutex_lock (priv->pending_mutex);
+	g_mutex_lock (view->priv->pending_mutex);
 
-	priv->flush_id = 0;
+	view->priv->flush_id = 0;
 
 	send_pending_adds (view);
 	send_pending_changes (view);
 	send_pending_removes (view);
 
-	g_mutex_unlock (priv->pending_mutex);
+	g_mutex_unlock (view->priv->pending_mutex);
 
 	return FALSE;
 }
@@ -218,12 +187,479 @@ pending_flush_timeout_cb (gpointer data)
 static void
 ensure_pending_flush_timeout (EDataBookView *view)
 {
-	EDataBookViewPrivate *priv = view->priv;
-
-	if (priv->flush_id)
-		return;
+	if (view->priv->flush_id > 0)
+		return;
+
+	view->priv->flush_id = g_timeout_add_seconds (
+		THRESHOLD_SECONDS, pending_flush_timeout_cb, view);
+}
+
+static void
+book_destroyed_cb (gpointer data,
+                   GObject *dead)
+{
+	EDataBookView *view = E_DATA_BOOK_VIEW (data);
+
+	/* The book has just died, so unset the pointer so
+	 * we don't try and remove a dead weak reference. */
+	view->priv->book = NULL;
+
+	/* If the view is running stop it here. */
+	if (view->priv->running) {
+		e_book_backend_stop_view (view->priv->backend, view);
+		view->priv->running = FALSE;
+		view->priv->complete = FALSE;
+	}
+}
+
+static gpointer
+bookview_start_thread (gpointer data)
+{
+	EDataBookView *view = data;
+
+	if (view->priv->running)
+		e_book_backend_start_view (view->priv->backend, view);
+	g_object_unref (view);
+
+	return NULL;
+}
+
+static gboolean
+impl_DataBookView_start (EGdbusBookView *object,
+                         GDBusMethodInvocation *invocation,
+                         EDataBookView *view)
+{
+	GThread *thread;
+
+	view->priv->running = TRUE;
+	view->priv->complete = FALSE;
+
+	thread = g_thread_new (
+		NULL, bookview_start_thread, g_object_ref (view));
+	g_thread_unref (thread);
+
+	e_gdbus_book_view_complete_start (object, invocation, NULL);
+
+	return TRUE;
+}
+
+static gpointer
+bookview_stop_thread (gpointer data)
+{
+	EDataBookView *view = data;
+
+	if (!view->priv->running)
+		e_book_backend_stop_view (view->priv->backend, view);
+	g_object_unref (view);
+
+	return NULL;
+}
+
+static gboolean
+impl_DataBookView_stop (EGdbusBookView *object,
+                        GDBusMethodInvocation *invocation,
+                        EDataBookView *view)
+{
+	GThread *thread;
+
+	view->priv->running = FALSE;
+	view->priv->complete = FALSE;
+
+	thread = g_thread_new (
+		NULL, bookview_stop_thread, g_object_ref (view));
+	g_thread_unref (thread);
+
+	e_gdbus_book_view_complete_stop (object, invocation, NULL);
+
+	return TRUE;
+}
+
+static gboolean
+impl_DataBookView_setFlags (EGdbusBookView *object,
+                            GDBusMethodInvocation *invocation,
+                            EBookClientViewFlags flags,
+                            EDataBookView *view)
+{
+	view->priv->flags = flags;
+
+	e_gdbus_book_view_complete_set_flags (object, invocation, NULL);
+
+	return TRUE;
+}
+
+static gboolean
+impl_DataBookView_dispose (EGdbusBookView *object,
+                           GDBusMethodInvocation *invocation,
+                           EDataBookView *view)
+{
+	e_gdbus_book_view_complete_dispose (object, invocation, NULL);
+
+	e_book_backend_stop_view (view->priv->backend, view);
+	view->priv->running = FALSE;
+	e_book_backend_remove_view (view->priv->backend, view);
+
+	g_object_unref (view);
+
+	return TRUE;
+}
+
+static gboolean
+impl_DataBookView_set_fields_of_interest (EGdbusBookView *object,
+                                          GDBusMethodInvocation *invocation,
+                                          const gchar * const *in_fields_of_interest,
+                                          EDataBookView *view)
+{
+	gint ii;
+
+	g_return_val_if_fail (in_fields_of_interest != NULL, TRUE);
+
+	if (view->priv->fields_of_interest != NULL) {
+		g_hash_table_destroy (view->priv->fields_of_interest);
+		view->priv->fields_of_interest = NULL;
+	}
+
+	for (ii = 0; in_fields_of_interest[ii]; ii++) {
+		const gchar *field = in_fields_of_interest[ii];
+
+		if (!*field)
+			continue;
+
+		if (view->priv->fields_of_interest == NULL)
+			view->priv->fields_of_interest =
+				g_hash_table_new_full (
+					(GHashFunc) str_ic_hash,
+					(GEqualFunc) str_ic_equal,
+					(GDestroyNotify) g_free,
+					(GDestroyNotify) NULL);
+
+		g_hash_table_insert (
+			view->priv->fields_of_interest,
+			g_strdup (field), GINT_TO_POINTER (1));
+	}
+
+	e_gdbus_book_view_complete_set_fields_of_interest (
+		object, invocation, NULL);
+
+	return TRUE;
+}
+
+static void
+data_book_view_set_backend (EDataBookView *view,
+                            EBookBackend *backend)
+{
+	g_return_if_fail (E_IS_BOOK_BACKEND (backend));
+	g_return_if_fail (view->priv->backend == NULL);
+
+	view->priv->backend = g_object_ref (backend);
+}
+
+static void
+data_book_view_set_sexp (EDataBookView *view,
+                         EBookBackendSExp *sexp)
+{
+	g_return_if_fail (E_IS_BOOK_BACKEND_SEXP (sexp));
+	g_return_if_fail (view->priv->sexp == NULL);
+
+	view->priv->sexp = g_object_ref (sexp);
+}
+
+static void
+data_book_view_set_property (GObject *object,
+                             guint property_id,
+                             const GValue *value,
+                             GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_BACKEND:
+			data_book_view_set_backend (
+				E_DATA_BOOK_VIEW (object),
+				g_value_get_object (value));
+			return;
+
+		case PROP_SEXP:
+			data_book_view_set_sexp (
+				E_DATA_BOOK_VIEW (object),
+				g_value_get_object (value));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+data_book_view_get_property (GObject *object,
+                             guint property_id,
+                             GValue *value,
+                             GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_BACKEND:
+			g_value_set_object (
+				value,
+				e_data_book_view_get_backend (
+				E_DATA_BOOK_VIEW (object)));
+			return;
+
+		case PROP_SEXP:
+			g_value_set_object (
+				value,
+				e_data_book_view_get_sexp (
+				E_DATA_BOOK_VIEW (object)));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+data_book_view_dispose (GObject *object)
+{
+	EDataBookViewPrivate *priv;
+
+	priv = E_DATA_BOOK_VIEW_GET_PRIVATE (object);
+
+	if (priv->book != NULL) {
+		/* Remove the weak reference */
+		g_object_weak_unref (
+			G_OBJECT (priv->book),
+			book_destroyed_cb, object);
+		priv->book = NULL;
+	}
+
+	if (priv->backend != NULL) {
+		g_object_unref (priv->backend);
+		priv->backend = NULL;
+	}
+
+	if (priv->sexp != NULL) {
+		g_object_unref (priv->sexp);
+		priv->sexp = NULL;
+	}
+
+	g_mutex_lock (priv->pending_mutex);
+
+	if (priv->flush_id > 0) {
+		g_source_remove (priv->flush_id);
+		priv->flush_id = 0;
+	}
+
+	g_mutex_unlock (priv->pending_mutex);
+
+	/* Chain up to parent's dispose() method. */
+	G_OBJECT_CLASS (e_data_book_view_parent_class)->dispose (object);
+}
+
+static void
+data_book_view_finalize (GObject *object)
+{
+	EDataBookViewPrivate *priv;
+
+	priv = E_DATA_BOOK_VIEW_GET_PRIVATE (object);
+
+	reset_array (priv->adds);
+	reset_array (priv->changes);
+	reset_array (priv->removes);
+	g_array_free (priv->adds, TRUE);
+	g_array_free (priv->changes, TRUE);
+	g_array_free (priv->removes, TRUE);
+
+	if (priv->fields_of_interest)
+		g_hash_table_destroy (priv->fields_of_interest);
+
+	g_mutex_free (priv->pending_mutex);
+
+	g_hash_table_destroy (priv->ids);
+
+	/* Chain up to parent's finalize() method. */
+	G_OBJECT_CLASS (e_data_book_view_parent_class)->finalize (object);
+}
+
+static void
+e_data_book_view_class_init (EDataBookViewClass *class)
+{
+	GObjectClass *object_class;
+
+	g_type_class_add_private (class, sizeof (EDataBookViewPrivate));
+
+	object_class = G_OBJECT_CLASS (class);
+	object_class->set_property = data_book_view_set_property;
+	object_class->get_property = data_book_view_get_property;
+	object_class->dispose = data_book_view_dispose;
+	object_class->finalize = data_book_view_finalize;
+
+	g_object_class_install_property (
+		object_class,
+		PROP_BACKEND,
+		g_param_spec_object (
+			"backend",
+			"Backend",
+			"The backend being monitored",
+			E_TYPE_BOOK_BACKEND,
+			G_PARAM_READWRITE |
+			G_PARAM_CONSTRUCT_ONLY |
+			G_PARAM_STATIC_STRINGS));
+
+	g_object_class_install_property (
+		object_class,
+		PROP_SEXP,
+		g_param_spec_object (
+			"sexp",
+			"S-Expression",
+			"The query expression for this view",
+			E_TYPE_BOOK_BACKEND_SEXP,
+			G_PARAM_READWRITE |
+			G_PARAM_CONSTRUCT_ONLY |
+			G_PARAM_STATIC_STRINGS));
+}
+
+static void
+e_data_book_view_init (EDataBookView *view)
+{
+	view->priv = E_DATA_BOOK_VIEW_GET_PRIVATE (view);
+
+	view->priv->flags = E_BOOK_CLIENT_VIEW_FLAGS_NOTIFY_INITIAL;
+
+	view->priv->gdbus_object = e_gdbus_book_view_stub_new ();
+	g_signal_connect (
+		view->priv->gdbus_object, "handle-start",
+		G_CALLBACK (impl_DataBookView_start), view);
+	g_signal_connect (
+		view->priv->gdbus_object, "handle-stop",
+		G_CALLBACK (impl_DataBookView_stop), view);
+	g_signal_connect (
+		view->priv->gdbus_object, "handle-set-flags",
+		G_CALLBACK (impl_DataBookView_setFlags), view);
+	g_signal_connect (
+		view->priv->gdbus_object, "handle-dispose",
+		G_CALLBACK (impl_DataBookView_dispose), view);
+	g_signal_connect (
+		view->priv->gdbus_object, "handle-set-fields-of-interest",
+		G_CALLBACK (impl_DataBookView_set_fields_of_interest), view);
+
+	view->priv->fields_of_interest = NULL;
+	view->priv->running = FALSE;
+	view->priv->complete = FALSE;
+	view->priv->pending_mutex = g_mutex_new ();
+
+	/* THRESHOLD_ITEMS * 2 because we store UID and vcard */
+	view->priv->adds = g_array_sized_new (
+		TRUE, TRUE, sizeof (gchar *), THRESHOLD_ITEMS * 2);
+	view->priv->changes = g_array_sized_new (
+		TRUE, TRUE, sizeof (gchar *), THRESHOLD_ITEMS * 2);
+	view->priv->removes = g_array_sized_new (
+		TRUE, TRUE, sizeof (gchar *), THRESHOLD_ITEMS);
+
+	view->priv->ids = g_hash_table_new_full (
+		(GHashFunc) g_str_hash,
+		(GEqualFunc) g_str_equal,
+		(GDestroyNotify) g_free,
+		(GDestroyNotify) NULL);
+
+	view->priv->flush_id = 0;
+}
+
+/**
+ * e_data_book_view_new:
+ * @book: The #EDataBook to search
+ * @sexp: The query as an #EBookBackendSExp
+ *
+ * Create a new #EDataBookView for the given #EBook, filtering on @sexp,
+ * and place it on DBus at the object path #path.
+ */
+EDataBookView *
+e_data_book_view_new (EDataBook *book,
+                      EBookBackendSExp *sexp)
+{
+	EDataBookView *view;
+	EBookBackend *backend;
+
+	g_return_val_if_fail (E_IS_DATA_BOOK (book), NULL);
+	g_return_val_if_fail (E_IS_BOOK_BACKEND_SEXP (sexp), NULL);
+
+	backend = e_data_book_get_backend (book);
+
+	view = g_object_new (
+		E_TYPE_DATA_BOOK_VIEW,
+		"backend", backend,
+		"sexp", sexp, NULL);
+
+	view->priv->book = book;
+	/* Attach a weak reference to the book, so
+	 * if it dies the book view is destroyed too. */
+	g_object_weak_ref (
+		G_OBJECT (view->priv->book),
+		book_destroyed_cb, view);
+
+	return view;
+}
+
+/**
+ * e_data_book_view_register_gdbus_object:
+ *
+ * Since: 2.32
+ **/
+guint
+e_data_book_view_register_gdbus_object (EDataBookView *query,
+                                        GDBusConnection *connection,
+                                        const gchar *object_path,
+                                        GError **error)
+{
+	g_return_val_if_fail (E_IS_DATA_BOOK_VIEW (query), 0);
+	g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), 0);
+	g_return_val_if_fail (object_path != NULL, 0);
+
+	return e_gdbus_book_view_register_object (
+		query->priv->gdbus_object, connection, object_path, error);
+}
+
+/**
+ * e_data_book_view_get_backend:
+ * @view: an #EDataBookView
+ *
+ * Gets the backend that @view is querying.
+ *
+ * Returns: The associated #EBookBackend.
+ **/
+EBookBackend *
+e_data_book_view_get_backend (EDataBookView *view)
+{
+	g_return_val_if_fail (E_IS_DATA_BOOK_VIEW (view), NULL);
+
+	return view->priv->backend;
+}
+
+/**
+ * e_data_book_view_get_sexp:
+ * @view: an #EDataBookView
+ *
+ * Gets the s-expression used for matching contacts to @view.
+ *
+ * Returns: The #EBookBackendSExp used.
+ **/
+EBookBackendSExp *
+e_data_book_view_get_sexp (EDataBookView *view)
+{
+	g_return_val_if_fail (E_IS_DATA_BOOK_VIEW (view), NULL);
+
+	return view->priv->sexp;
+}
+
+/**
+ * e_data_book_view_get_flags:
+ * @view: an #EDataBookView
+ *
+ * Gets the #EBookClientViewFlags that control the behaviour of @view.
+ *
+ * Returns: the flags for @view.
+ *
+ * Since: 3.4
+ **/
+EBookClientViewFlags
+e_data_book_view_get_flags (EDataBookView *view)
+{
+	g_return_val_if_fail (E_IS_DATA_BOOK_VIEW (view), 0);
 
-	priv->flush_id = g_timeout_add_seconds (THRESHOLD_SECONDS, pending_flush_timeout_cb, view);
+	return view->priv->flags;
 }
 
 /*
@@ -234,21 +670,20 @@ notify_change (EDataBookView *view,
                const gchar *id,
                const gchar *vcard)
 {
-	EDataBookViewPrivate *priv = view->priv;
 	gchar *utf8_vcard, *utf8_id;
 
 	send_pending_adds (view);
 	send_pending_removes (view);
 
-	if (priv->changes->len == THRESHOLD_ITEMS * 2) {
+	if (view->priv->changes->len == THRESHOLD_ITEMS * 2) {
 		send_pending_changes (view);
 	}
 
 	utf8_vcard = e_util_utf8_make_valid (vcard);
 	utf8_id = e_util_utf8_make_valid (id);
 
-	g_array_append_val (priv->changes, utf8_vcard);
-	g_array_append_val (priv->changes, utf8_id);
+	g_array_append_val (view->priv->changes, utf8_vcard);
+	g_array_append_val (view->priv->changes, utf8_id);
 
 	ensure_pending_flush_timeout (view);
 }
@@ -260,19 +695,18 @@ static void
 notify_remove (EDataBookView *view,
                const gchar *id)
 {
-	EDataBookViewPrivate *priv = view->priv;
 	gchar *valid_id;
 
 	send_pending_adds (view);
 	send_pending_changes (view);
 
-	if (priv->removes->len == THRESHOLD_ITEMS) {
+	if (view->priv->removes->len == THRESHOLD_ITEMS) {
 		send_pending_removes (view);
 	}
 
 	valid_id = e_util_utf8_make_valid (id);
-	g_array_append_val (priv->removes, valid_id);
-	g_hash_table_remove (priv->ids, valid_id);
+	g_array_append_val (view->priv->removes, valid_id);
+	g_hash_table_remove (view->priv->ids, valid_id);
 
 	ensure_pending_flush_timeout (view);
 }
@@ -286,7 +720,6 @@ notify_add (EDataBookView *view,
             const gchar *vcard)
 {
 	EBookClientViewFlags flags;
-	EDataBookViewPrivate *priv = view->priv;
 	gchar *utf8_vcard, *utf8_id;
 
 	send_pending_changes (view);
@@ -296,87 +729,36 @@ notify_add (EDataBookView *view,
 
 	/* Do not send contact add notifications during initial stage */
 	flags = e_data_book_view_get_flags (view);
-	if (priv->complete || (flags & E_BOOK_CLIENT_VIEW_FLAGS_NOTIFY_INITIAL) != 0) {
+	if (view->priv->complete || (flags & E_BOOK_CLIENT_VIEW_FLAGS_NOTIFY_INITIAL) != 0) {
 		gchar *utf8_id_copy = g_strdup (utf8_id);
 
-		if (priv->adds->len == THRESHOLD_ITEMS) {
+		if (view->priv->adds->len == THRESHOLD_ITEMS) {
 			send_pending_adds (view);
 		}
 
 		utf8_vcard = e_util_utf8_make_valid (vcard);
 
-		g_array_append_val (priv->adds, utf8_vcard);
-		g_array_append_val (priv->adds, utf8_id_copy);
+		g_array_append_val (view->priv->adds, utf8_vcard);
+		g_array_append_val (view->priv->adds, utf8_id_copy);
 
 		ensure_pending_flush_timeout (view);
 	}
 
-	g_hash_table_insert (priv->ids, utf8_id,
-			     GUINT_TO_POINTER (1));
-}
-
-static gboolean
-impl_DataBookView_set_fields_of_interest (EGdbusBookView *object,
-                                          GDBusMethodInvocation *invocation,
-                                          const gchar * const *in_fields_of_interest,
-                                          EDataBookView *view)
-{
-	EDataBookViewPrivate *priv;
-	gint ii;
-
-	g_return_val_if_fail (in_fields_of_interest != NULL, TRUE);
-
-	priv = view->priv;
-
-	if (priv->fields_of_interest)
-		g_hash_table_destroy (priv->fields_of_interest);
-	priv->fields_of_interest = NULL;
-
-	for (ii = 0; in_fields_of_interest[ii]; ii++) {
-		const gchar *field = in_fields_of_interest[ii];
-
-		if (!*field)
-			continue;
-
-		if (!priv->fields_of_interest)
-			priv->fields_of_interest = g_hash_table_new_full (str_ic_hash, str_ic_equal, g_free, NULL);
-
-		g_hash_table_insert (priv->fields_of_interest, g_strdup (field), GINT_TO_POINTER (1));
-	}
-
-	e_gdbus_book_view_complete_set_fields_of_interest (object, invocation, NULL);
-
-	return TRUE;
-}
-
-static void
-reset_array (GArray *array)
-{
-	gint i = 0;
-	gchar *tmp = NULL;
-
-	/* Free stored strings */
-	for (i = 0; i < array->len; i++) {
-		tmp = g_array_index (array, gchar *, i);
-		g_free (tmp);
-	}
-
-	/* Force the array size to 0 */
-	g_array_set_size (array, 0);
+	g_hash_table_insert (view->priv->ids, utf8_id, GUINT_TO_POINTER (1));
 }
 
 static gboolean
-id_is_in_view (EDataBookView *book_view,
+id_is_in_view (EDataBookView *view,
                const gchar *id)
 {
 	gchar *valid_id;
 	gboolean res;
 
-	g_return_val_if_fail (book_view != NULL, FALSE);
+	g_return_val_if_fail (view != NULL, FALSE);
 	g_return_val_if_fail (id != NULL, FALSE);
 
 	valid_id = e_util_utf8_make_valid (id);
-	res = g_hash_table_lookup (book_view->priv->ids, valid_id) != NULL;
+	res = g_hash_table_lookup (view->priv->ids, valid_id) != NULL;
 	g_free (valid_id);
 
 	return res;
@@ -384,105 +766,110 @@ id_is_in_view (EDataBookView *book_view,
 
 /**
  * e_data_book_view_notify_update:
- * @book_view: an #EDataBookView
+ * @view: an #EDataBookView
  * @contact: an #EContact
  *
  * Notify listeners that @contact has changed. This can
  * trigger an add, change or removal event depending on
  * whether the change causes the contact to start matching,
  * no longer match, or stay matching the query specified
- * by @book_view.
+ * by @view.
  **/
 void
-e_data_book_view_notify_update (EDataBookView *book_view,
+e_data_book_view_notify_update (EDataBookView *view,
                                 const EContact *contact)
 {
-	EDataBookViewPrivate *priv = book_view->priv;
 	gboolean currently_in_view, want_in_view;
 	const gchar *id;
 	gchar *vcard;
 
-	if (!priv->running)
+	g_return_if_fail (E_IS_DATA_BOOK_VIEW (view));
+	g_return_if_fail (E_IS_CONTACT (contact));
+
+	if (!view->priv->running)
 		return;
 
-	g_mutex_lock (priv->pending_mutex);
+	g_mutex_lock (view->priv->pending_mutex);
 
 	id = e_contact_get_const ((EContact *) contact, E_CONTACT_UID);
 
-	currently_in_view = id_is_in_view (book_view, id);
-	want_in_view =
-		e_book_backend_sexp_match_contact (priv->card_sexp, (EContact *) contact);
+	currently_in_view = id_is_in_view (view, id);
+	want_in_view = e_book_backend_sexp_match_contact (
+		view->priv->sexp, (EContact *) contact);
 
 	if (want_in_view) {
 		vcard = e_vcard_to_string (E_VCARD (contact),
 					   EVC_FORMAT_VCARD_30);
 
 		if (currently_in_view)
-			notify_change (book_view, id, vcard);
+			notify_change (view, id, vcard);
 		else
-			notify_add (book_view, id, vcard);
+			notify_add (view, id, vcard);
 
 		g_free (vcard);
 	} else {
 		if (currently_in_view)
-			notify_remove (book_view, id);
+			notify_remove (view, id);
 		/* else nothing; we're removing a card that wasn't there */
 	}
 
-	g_mutex_unlock (priv->pending_mutex);
+	g_mutex_unlock (view->priv->pending_mutex);
 }
 
 /**
  * e_data_book_view_notify_update_vcard:
- * @book_view: an #EDataBookView
+ * @view: an #EDataBookView
  * @vcard: a plain vCard
  *
  * Notify listeners that @vcard has changed. This can
  * trigger an add, change or removal event depending on
  * whether the change causes the contact to start matching,
  * no longer match, or stay matching the query specified
- * by @book_view.  This method should be preferred over
+ * by @view.  This method should be preferred over
  * #e_data_book_view_notify_update when the native
  * representation of a contact is a vCard.
  **/
 void
-e_data_book_view_notify_update_vcard (EDataBookView *book_view,
+e_data_book_view_notify_update_vcard (EDataBookView *view,
                                       const gchar *id,
                                       const gchar *vcard)
 {
-	EDataBookViewPrivate *priv = book_view->priv;
 	gboolean currently_in_view, want_in_view;
 	EContact *contact;
 
-	if (!priv->running)
+	g_return_if_fail (E_IS_DATA_BOOK_VIEW (view));
+	g_return_if_fail (id != NULL);
+	g_return_if_fail (vcard != NULL);
+
+	if (!view->priv->running)
 		return;
 
-	g_mutex_lock (priv->pending_mutex);
+	g_mutex_lock (view->priv->pending_mutex);
 
 	contact = e_contact_new_from_vcard_with_uid (vcard, id);
-	currently_in_view = id_is_in_view (book_view, id);
-	want_in_view =
-		e_book_backend_sexp_match_contact (priv->card_sexp, contact);
+	currently_in_view = id_is_in_view (view, id);
+	want_in_view = e_book_backend_sexp_match_contact (
+		view->priv->sexp, contact);
 
 	if (want_in_view) {
 		if (currently_in_view)
-			notify_change (book_view, id, vcard);
+			notify_change (view, id, vcard);
 		else
-			notify_add (book_view, id, vcard);
+			notify_add (view, id, vcard);
 	} else {
 		if (currently_in_view)
-			notify_remove (book_view, id);
+			notify_remove (view, id);
 	}
 
 	/* Do this last so that id is still valid when notify_ is called */
 	g_object_unref (contact);
 
-	g_mutex_unlock (priv->pending_mutex);
+	g_mutex_unlock (view->priv->pending_mutex);
 }
 
 /**
  * e_data_book_view_notify_update_prefiltered_vcard:
- * @book_view: an #EDataBookView
+ * @view: an #EDataBookView
  * @id: the UID of this contact
  * @vcard: a plain vCard
  *
@@ -490,7 +877,7 @@ e_data_book_view_notify_update_vcard (EDataBookView *book_view,
  * trigger an add, change or removal event depending on
  * whether the change causes the contact to start matching,
  * no longer match, or stay matching the query specified
- * by @book_view.  This method should be preferred over
+ * by @view.  This method should be preferred over
  * #e_data_book_view_notify_update when the native
  * representation of a contact is a vCard.
  *
@@ -501,88 +888,98 @@ e_data_book_view_notify_update_vcard (EDataBookView *book_view,
  * known to exist in the view.
  **/
 void
-e_data_book_view_notify_update_prefiltered_vcard (EDataBookView *book_view,
+e_data_book_view_notify_update_prefiltered_vcard (EDataBookView *view,
                                                   const gchar *id,
                                                   const gchar *vcard)
 {
-	EDataBookViewPrivate *priv = book_view->priv;
 	gboolean currently_in_view;
 
-	if (!priv->running)
+	g_return_if_fail (E_IS_DATA_BOOK_VIEW (view));
+	g_return_if_fail (id != NULL);
+	g_return_if_fail (vcard != NULL);
+
+	if (!view->priv->running)
 		return;
 
-	g_mutex_lock (priv->pending_mutex);
+	g_mutex_lock (view->priv->pending_mutex);
 
-	currently_in_view = id_is_in_view (book_view, id);
+	currently_in_view = id_is_in_view (view, id);
 
 	if (currently_in_view)
-		notify_change (book_view, id, vcard);
+		notify_change (view, id, vcard);
 	else
-		notify_add (book_view, id, vcard);
+		notify_add (view, id, vcard);
 
-	g_mutex_unlock (priv->pending_mutex);
+	g_mutex_unlock (view->priv->pending_mutex);
 }
 
 /**
  * e_data_book_view_notify_remove:
- * @book_view: an #EDataBookView
+ * @view: an #EDataBookView
  * @id: a unique contact ID
  *
  * Notify listeners that a contact specified by @id
- * was removed from @book_view.
+ * was removed from @view.
  **/
 void
-e_data_book_view_notify_remove (EDataBookView *book_view,
+e_data_book_view_notify_remove (EDataBookView *view,
                                 const gchar *id)
 {
-	if (!book_view->priv->running)
+	g_return_if_fail (E_IS_DATA_BOOK_VIEW (view));
+	g_return_if_fail (id != NULL);
+
+	if (!view->priv->running)
 		return;
 
-	g_mutex_lock (book_view->priv->pending_mutex);
+	g_mutex_lock (view->priv->pending_mutex);
 
-	if (id_is_in_view (book_view, id))
-		notify_remove (book_view, id);
+	if (id_is_in_view (view, id))
+		notify_remove (view, id);
 
-	g_mutex_unlock (book_view->priv->pending_mutex);
+	g_mutex_unlock (view->priv->pending_mutex);
 }
 
 /**
  * e_data_book_view_notify_complete:
- * @book_view: an #EDataBookView
+ * @view: an #EDataBookView
  * @error: the error of the query, if any
  *
- * Notifies listeners that all pending updates on @book_view
+ * Notifies listeners that all pending updates on @view
  * have been sent. The listener's information should now be
  * in sync with the backend's.
  **/
 void
-e_data_book_view_notify_complete (EDataBookView *book_view,
+e_data_book_view_notify_complete (EDataBookView *view,
                                   const GError *error)
 {
-	EDataBookViewPrivate *priv = book_view->priv;
 	gchar **strv_error;
 
-	if (!priv->running)
+	g_return_if_fail (E_IS_DATA_BOOK_VIEW (view));
+
+	if (!view->priv->running)
 		return;
+
 	/* View is complete */
-	priv->complete = TRUE;
+	view->priv->complete = TRUE;
 
-	g_mutex_lock (priv->pending_mutex);
+	g_mutex_lock (view->priv->pending_mutex);
 
-	send_pending_adds (book_view);
-	send_pending_changes (book_view);
-	send_pending_removes (book_view);
+	send_pending_adds (view);
+	send_pending_changes (view);
+	send_pending_removes (view);
 
-	g_mutex_unlock (priv->pending_mutex);
+	g_mutex_unlock (view->priv->pending_mutex);
 
 	strv_error = e_gdbus_templates_encode_error (error);
-	e_gdbus_book_view_emit_complete (priv->gdbus_object, (const gchar * const *) strv_error);
+	e_gdbus_book_view_emit_complete (
+		view->priv->gdbus_object,
+		(const gchar * const *) strv_error);
 	g_strfreev (strv_error);
 }
 
 /**
  * e_data_book_view_notify_progress:
- * @book_view: an #EDataBookView
+ * @view: an #EDataBookView
  * @percent: percent done; use -1 when not available
  * @message: a text message
  *
@@ -593,316 +990,27 @@ e_data_book_view_notify_complete (EDataBookView *book_view,
  * Since: 3.2
  **/
 void
-e_data_book_view_notify_progress (EDataBookView *book_view,
+e_data_book_view_notify_progress (EDataBookView *view,
                                   guint percent,
                                   const gchar *message)
 {
 	gchar *gdbus_message = NULL;
 
-	if (!book_view->priv->running)
+	g_return_if_fail (E_IS_DATA_BOOK_VIEW (view));
+
+	if (!view->priv->running)
 		return;
 
 	e_gdbus_book_view_emit_progress (
-		book_view->priv->gdbus_object, percent,
+		view->priv->gdbus_object, percent,
 		e_util_ensure_gdbus_string (message, &gdbus_message));
 
 	g_free (gdbus_message);
 }
 
 /**
- * e_data_book_view_new:
- * @book: The #EDataBook to search
- * @card_query: The query as a string
- * @card_sexp: The query as an #EBookBackendSExp
- *
- * Create a new #EDataBookView for the given #EBook, filtering on #card_sexp,
- * and place it on DBus at the object path #path.
- */
-EDataBookView *
-e_data_book_view_new (EDataBook *book,
-                      const gchar *card_query,
-                      EBookBackendSExp *card_sexp)
-{
-	EDataBookView *view;
-	EDataBookViewPrivate *priv;
-
-	view = g_object_new (E_TYPE_DATA_BOOK_VIEW, NULL);
-	priv = view->priv;
-
-	priv->book = book;
-	/* Attach a weak reference to the book, so if it dies the book view is destroyed too */
-	g_object_weak_ref (G_OBJECT (priv->book), book_destroyed_cb, view);
-	priv->backend = g_object_ref (e_data_book_get_backend (book));
-	priv->card_query = e_util_utf8_make_valid (card_query);
-	priv->card_sexp = card_sexp;
-
-	return view;
-}
-
-static gpointer
-bookview_start_thread (gpointer data)
-{
-	EDataBookView *book_view = data;
-
-	if (book_view->priv->running)
-		e_book_backend_start_view (book_view->priv->backend, book_view);
-	g_object_unref (book_view);
-
-	return NULL;
-}
-
-static gboolean
-impl_DataBookView_start (EGdbusBookView *object,
-                         GDBusMethodInvocation *invocation,
-                         EDataBookView *book_view)
-{
-	GThread *thread;
-
-	book_view->priv->running = TRUE;
-	book_view->priv->complete = FALSE;
-
-	thread = g_thread_new (NULL, bookview_start_thread, g_object_ref (book_view));
-	g_thread_unref (thread);
-
-	e_gdbus_book_view_complete_start (object, invocation, NULL);
-
-	return TRUE;
-}
-
-static gpointer
-bookview_stop_thread (gpointer data)
-{
-	EDataBookView *book_view = data;
-
-	if (!book_view->priv->running)
-		e_book_backend_stop_view (book_view->priv->backend, book_view);
-	g_object_unref (book_view);
-
-	return NULL;
-}
-
-static gboolean
-impl_DataBookView_stop (EGdbusBookView *object,
-                        GDBusMethodInvocation *invocation,
-                        EDataBookView *book_view)
-{
-	GThread *thread;
-
-	book_view->priv->running = FALSE;
-	book_view->priv->complete = FALSE;
-
-	thread = g_thread_new (NULL, bookview_stop_thread, g_object_ref (book_view));
-	g_thread_unref (thread);
-
-	e_gdbus_book_view_complete_stop (object, invocation, NULL);
-
-	return TRUE;
-}
-
-static gboolean
-impl_DataBookView_setFlags (EGdbusBookView *object,
-                            GDBusMethodInvocation *invocation,
-                            EBookClientViewFlags flags,
-                            EDataBookView *book_view)
-{
-	book_view->priv->flags = flags;
-
-	e_gdbus_book_view_complete_set_flags (object, invocation, NULL);
-
-	return TRUE;
-}
-
-static gboolean
-impl_DataBookView_dispose (EGdbusBookView *object,
-                           GDBusMethodInvocation *invocation,
-                           EDataBookView *book_view)
-{
-	e_gdbus_book_view_complete_dispose (object, invocation, NULL);
-
-	e_book_backend_stop_view (book_view->priv->backend, book_view);
-	book_view->priv->running = FALSE;
-	e_book_backend_remove_view (book_view->priv->backend, book_view);
-
-	g_object_unref (book_view);
-
-	return TRUE;
-}
-
-static void
-e_data_book_view_init (EDataBookView *book_view)
-{
-	book_view->priv = E_DATA_BOOK_VIEW_GET_PRIVATE (book_view);
-
-	book_view->priv->flags = E_BOOK_CLIENT_VIEW_FLAGS_NOTIFY_INITIAL;
-
-	book_view->priv->gdbus_object = e_gdbus_book_view_stub_new ();
-	g_signal_connect (
-		book_view->priv->gdbus_object, "handle-start",
-		G_CALLBACK (impl_DataBookView_start), book_view);
-	g_signal_connect (
-		book_view->priv->gdbus_object, "handle-stop",
-		G_CALLBACK (impl_DataBookView_stop), book_view);
-	g_signal_connect (
-		book_view->priv->gdbus_object, "handle-set-flags",
-		G_CALLBACK (impl_DataBookView_setFlags), book_view);
-	g_signal_connect (
-		book_view->priv->gdbus_object, "handle-dispose",
-		G_CALLBACK (impl_DataBookView_dispose), book_view);
-	g_signal_connect (
-		book_view->priv->gdbus_object, "handle-set-fields-of-interest",
-		G_CALLBACK (impl_DataBookView_set_fields_of_interest), book_view);
-
-	book_view->priv->fields_of_interest = NULL;
-	book_view->priv->running = FALSE;
-	book_view->priv->complete = FALSE;
-	book_view->priv->pending_mutex = g_mutex_new ();
-
-	/* THRESHOLD_ITEMS * 2 because we store UID and vcard */
-	book_view->priv->adds = g_array_sized_new (
-		TRUE, TRUE, sizeof (gchar *), THRESHOLD_ITEMS * 2);
-	book_view->priv->changes = g_array_sized_new (
-		TRUE, TRUE, sizeof (gchar *), THRESHOLD_ITEMS * 2);
-	book_view->priv->removes = g_array_sized_new (
-		TRUE, TRUE, sizeof (gchar *), THRESHOLD_ITEMS);
-
-	book_view->priv->ids = g_hash_table_new_full (
-		(GHashFunc) g_str_hash,
-		(GEqualFunc) g_str_equal,
-		(GDestroyNotify) g_free,
-		(GDestroyNotify) NULL);
-
-	book_view->priv->flush_id = 0;
-}
-
-static void
-e_data_book_view_dispose (GObject *object)
-{
-	EDataBookView *book_view = E_DATA_BOOK_VIEW (object);
-	EDataBookViewPrivate *priv = book_view->priv;
-
-	if (priv->book) {
-		/* Remove the weak reference */
-		g_object_weak_unref (G_OBJECT (priv->book), book_destroyed_cb, book_view);
-		priv->book = NULL;
-	}
-
-	if (priv->backend) {
-		g_object_unref (priv->backend);
-		priv->backend = NULL;
-	}
-
-	if (priv->card_sexp) {
-		g_object_unref (priv->card_sexp);
-		priv->card_sexp = NULL;
-	}
-
-	g_mutex_lock (priv->pending_mutex);
-
-	if (priv->flush_id) {
-		g_source_remove (priv->flush_id);
-		priv->flush_id = 0;
-	}
-
-	g_mutex_unlock (priv->pending_mutex);
-
-	G_OBJECT_CLASS (e_data_book_view_parent_class)->dispose (object);
-}
-
-static void
-e_data_book_view_finalize (GObject *object)
-{
-	EDataBookView *book_view = E_DATA_BOOK_VIEW (object);
-	EDataBookViewPrivate *priv = book_view->priv;
-
-	reset_array (priv->adds);
-	reset_array (priv->changes);
-	reset_array (priv->removes);
-	g_array_free (priv->adds, TRUE);
-	g_array_free (priv->changes, TRUE);
-	g_array_free (priv->removes, TRUE);
-	g_free (priv->card_query);
-
-	if (priv->fields_of_interest)
-		g_hash_table_destroy (priv->fields_of_interest);
-
-	g_mutex_free (priv->pending_mutex);
-
-	g_hash_table_destroy (priv->ids);
-
-	G_OBJECT_CLASS (e_data_book_view_parent_class)->finalize (object);
-}
-
-/**
- * e_data_book_view_get_card_query:
- * @book_view: an #EDataBookView
- *
- * Gets the text representation of the s-expression used
- * for matching contacts to @book_view.
- *
- * Returns: The textual s-expression used.
- **/
-const gchar *
-e_data_book_view_get_card_query (EDataBookView *book_view)
-{
-	g_return_val_if_fail (E_IS_DATA_BOOK_VIEW (book_view), NULL);
-
-	return book_view->priv->card_query;
-}
-
-/**
- * e_data_book_view_get_card_sexp:
- * @book_view: an #EDataBookView
- *
- * Gets the s-expression used for matching contacts to
- * @book_view.
- *
- * Returns: The #EBookBackendSExp used.
- **/
-EBookBackendSExp *
-e_data_book_view_get_card_sexp (EDataBookView *book_view)
-{
-	g_return_val_if_fail (E_IS_DATA_BOOK_VIEW (book_view), NULL);
-
-	return book_view->priv->card_sexp;
-}
-
-/**
- * e_data_book_view_get_backend:
- * @book_view: an #EDataBookView
- *
- * Gets the backend that @book_view is querying.
- *
- * Returns: The associated #EBookBackend.
- **/
-EBookBackend *
-e_data_book_view_get_backend (EDataBookView *book_view)
-{
-	g_return_val_if_fail (E_IS_DATA_BOOK_VIEW (book_view), NULL);
-
-	return book_view->priv->backend;
-}
-
-/**
- * e_data_book_view_get_flags:
- * @book_view: an #EDataBookView
- *
- * Gets the #EBookClientViewFlags that control the behaviour of @book_view.
- *
- * Returns: the flags for @book_view.
- *
- * Since: 3.4
- **/
-EBookClientViewFlags
-e_data_book_view_get_flags (EDataBookView *book_view)
-{
-	g_return_val_if_fail (E_IS_DATA_BOOK_VIEW (book_view), 0);
-
-	return book_view->priv->flags;
-}
-
-/**
  * e_data_book_view_get_fields_of_interest:
- * @view: A view object.
+ * @view: an #EDataBookView
  *
  * Returns: Hash table of field names which the listener is interested in.
  * Backends can return fully populated objects, but the listener advertised
@@ -912,7 +1020,7 @@ e_data_book_view_get_flags (EDataBookView *book_view)
  * only GINT_TO_POINTER(1) for easier checking. Also, field names are
  * compared case insensitively.
  **/
-/* const */ GHashTable *
+GHashTable *
 e_data_book_view_get_fields_of_interest (EDataBookView *view)
 {
 	g_return_val_if_fail (E_IS_DATA_BOOK_VIEW (view), NULL);
diff --git a/addressbook/libedata-book/e-data-book-view.h b/addressbook/libedata-book/e-data-book-view.h
index ea2d03e..53291d1 100644
--- a/addressbook/libedata-book/e-data-book-view.h
+++ b/addressbook/libedata-book/e-data-book-view.h
@@ -71,40 +71,37 @@ struct _EDataBookViewClass {
 
 GType		e_data_book_view_get_type	(void) G_GNUC_CONST;
 EDataBookView *	e_data_book_view_new		(struct _EDataBook *book,
-						 const gchar *card_query,
-						 EBookBackendSExp *card_sexp);
+						 EBookBackendSExp *sexp);
 guint		e_data_book_view_register_gdbus_object
 						(EDataBookView *query,
 						 GDBusConnection *connection,
 						 const gchar *object_path,
 						 GError **error);
-
-const gchar *	e_data_book_view_get_card_query	(EDataBookView *book_view);
-EBookBackendSExp *
-		e_data_book_view_get_card_sexp	(EDataBookView *book_view);
 struct _EBookBackend *
-		e_data_book_view_get_backend	(EDataBookView *book_view);
+		e_data_book_view_get_backend	(EDataBookView *view);
+EBookBackendSExp *
+		e_data_book_view_get_sexp	(EDataBookView *view);
 EBookClientViewFlags
-		e_data_book_view_get_flags	(EDataBookView *book_view);
-void		e_data_book_view_notify_update	(EDataBookView *book_view,
+		e_data_book_view_get_flags	(EDataBookView *view);
+void		e_data_book_view_notify_update	(EDataBookView *view,
 						 const EContact *contact);
 
 void		e_data_book_view_notify_update_vcard
-						(EDataBookView *book_view,
+						(EDataBookView *view,
 						 const gchar *id,
 						 const gchar *vcard);
 void		e_data_book_view_notify_update_prefiltered_vcard
-						(EDataBookView *book_view,
+						(EDataBookView *view,
 						 const gchar *id,
 						 const gchar *vcard);
 
-void		e_data_book_view_notify_remove	(EDataBookView *book_view,
+void		e_data_book_view_notify_remove	(EDataBookView *view,
 						 const gchar *id);
 void		e_data_book_view_notify_complete
-						(EDataBookView *book_view,
+						(EDataBookView *view,
 						 const GError *error);
 void		e_data_book_view_notify_progress
-						(EDataBookView *book_view,
+						(EDataBookView *view,
 						 guint percent,
 						 const gchar *message);
 
diff --git a/addressbook/libedata-book/e-data-book.c b/addressbook/libedata-book/e-data-book.c
index ddb9261..7747097 100644
--- a/addressbook/libedata-book/e-data-book.c
+++ b/addressbook/libedata-book/e-data-book.c
@@ -212,7 +212,7 @@ operation_thread (gpointer data,
 
 			path = construct_bookview_path ();
 
-			book_view = e_data_book_view_new (op->book, op->d.query, card_sexp);
+			book_view = e_data_book_view_new (op->book, card_sexp);
 			e_data_book_view_register_gdbus_object (book_view, e_gdbus_book_stub_get_connection (op->book->priv->gdbus_object), path, &error);
 
 			if (error) {
diff --git a/docs/reference/addressbook/libedata-book/libedata-book-sections.txt b/docs/reference/addressbook/libedata-book/libedata-book-sections.txt
index d0b989e..ad8831f 100644
--- a/docs/reference/addressbook/libedata-book/libedata-book-sections.txt
+++ b/docs/reference/addressbook/libedata-book/libedata-book-sections.txt
@@ -329,9 +329,8 @@ e_data_book_factory_get_type
 EDataBookView
 e_data_book_view_new
 e_data_book_view_register_gdbus_object
-e_data_book_view_get_card_query
-e_data_book_view_get_card_sexp
 e_data_book_view_get_backend
+e_data_book_view_get_sexp
 e_data_book_view_get_flags
 e_data_book_view_notify_update
 e_data_book_view_notify_update_vcard



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