From da21a70d03050292d77029c98ac6afbf7ea71075 Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Fri, 12 Oct 2012 13:30:06 -0400 Subject: [PATCH] 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 -- 2.7.4