EDataBookView cleanups.
authorMatthew Barnes <mbarnes@redhat.com>
Fri, 12 Oct 2012 17:30:06 +0000 (13:30 -0400)
committerMatthew Barnes <mbarnes@redhat.com>
Sat, 13 Oct 2012 12:09:51 +0000 (08:09 -0400)
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
addressbook/backends/ldap/e-book-backend-ldap.c
addressbook/backends/vcf/e-book-backend-vcf.c
addressbook/backends/webdav/e-book-backend-webdav.c
addressbook/libedata-book/e-data-book-view.c
addressbook/libedata-book/e-data-book-view.h
addressbook/libedata-book/e-data-book.c
docs/reference/addressbook/libedata-book/libedata-book-sections.txt

index b31d251..9bace4e 100644 (file)
@@ -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);
index eade88e..5624d02 100644 (file)
@@ -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))
index 9d6baf8..3da4b63 100644 (file)
@@ -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..."));
index 5e9cdaf..b4b3917 100644 (file)
@@ -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);
index c391a75..e7698cf 100644 (file)
        (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);
index ea2d03e..53291d1 100644 (file)
@@ -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);
 
index ddb9261..7747097 100644 (file)
@@ -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) {
index d0b989e..ad8831f 100644 (file)
@@ -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