[evolution-data-server/openismus-work-master: 4/10] Handle fields-of-interest for local addressbook backend.
- From: Tristan Van Berkom <tvb src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server/openismus-work-master: 4/10] Handle fields-of-interest for local addressbook backend.
- Date: Mon, 25 Jul 2011 23:13:38 +0000 (UTC)
commit dd6a5777279c1d8f88a592d34c76a58d6d31f974
Author: Tristan Van Berkom <tristan van berkom gmail com>
Date: Sun Jun 26 12:05:54 2011 -0400
Handle fields-of-interest for local addressbook backend.
This patch modifies the local file addressbook backend to notify
with vcards holding only the fields requested in the EBookClientView's
fields-of-interest.
A special case it made if only the UID is requested, in that case
the notification vCard is created from an id and no additional
parsing and filtering is needed.
Additionally, the patch adds a filtering algorithm in
e_book_backend_notify_update() to automatically filter vcard
notifications in response to a client adding or modifying a contact.
This patch should address both bugs:
https://bugzilla.gnome.org/show_bug.cgi?id=652179
https://bugzilla.gnome.org/show_bug.cgi?id=652172
addressbook/backends/file/e-book-backend-file.c | 92 +++++++++++++++++++++--
addressbook/libebook/e-contact.c | 38 +++++++++
addressbook/libebook/e-contact.h | 1 +
addressbook/libedata-book/e-book-backend.c | 49 +++++++++++-
4 files changed, 171 insertions(+), 9 deletions(-)
---
diff --git a/addressbook/backends/file/e-book-backend-file.c b/addressbook/backends/file/e-book-backend-file.c
index 596c829..740b251 100644
--- a/addressbook/backends/file/e-book-backend-file.c
+++ b/addressbook/backends/file/e-book-backend-file.c
@@ -633,6 +633,80 @@ get_closure (EDataBookView *book_view)
return g_object_get_data (G_OBJECT (book_view), "EBookBackendFile.BookView::closure");
}
+static gboolean
+view_wants_uid_only (EDataBookView *book_view)
+{
+ GHashTable *fields = e_data_book_view_get_fields_of_interest (book_view);
+
+ if (fields &&
+ g_hash_table_size (fields) == 1 &&
+ g_hash_table_lookup (fields, e_contact_field_name (E_CONTACT_UID)))
+ return TRUE;
+
+ return FALSE;
+}
+
+typedef struct {
+ EContact *contact;
+ EContact *shallow;
+} FilterContactData;
+
+static void
+foreach_filter_contact (const gchar *field,
+ gpointer present,
+ FilterContactData *data)
+{
+ EContactField field_id;
+
+ field_id = e_contact_field_id (field);
+ e_contact_copy_attributes (data->contact, data->shallow, field_id);
+}
+
+static void
+notify_update_vcard (EDataBookView *book_view,
+ gboolean prefiltered,
+ const gchar *id,
+ const gchar *vcard)
+{
+ GHashTable *fields = e_data_book_view_get_fields_of_interest (book_view);
+ gchar *final_vcard;
+
+ if (view_wants_uid_only (book_view)) {
+ /* Create a shallow version of the contacts for views that are
+ * only interested in the uid. */
+ EContact *shallow = e_contact_new ();
+
+ e_contact_set (shallow, E_CONTACT_UID, id);
+ final_vcard = e_vcard_to_string (E_VCARD (shallow), EVC_FORMAT_VCARD_30);
+ g_object_unref (shallow);
+
+ } else if (fields) {
+
+ FilterContactData data = { 0, };
+ EContact *shallow = e_contact_new ();
+ EContact *contact = create_contact (id, vcard);
+
+ /* Set the UID unconditionally */
+ e_contact_set (shallow, E_CONTACT_UID, id);
+
+ /* Transfer any attributes for the fields-of-interest */
+ data.contact = contact;
+ data.shallow = shallow;
+ g_hash_table_foreach (fields, (GHFunc)foreach_filter_contact, &data);
+
+ final_vcard = e_vcard_to_string (E_VCARD (shallow), EVC_FORMAT_VCARD_30);
+ g_object_unref (shallow);
+ g_object_unref (contact);
+ } else {
+ final_vcard = g_strdup (vcard);
+ }
+
+ if (prefiltered)
+ e_data_book_view_notify_update_prefiltered_vcard (book_view, id, final_vcard);
+ else
+ e_data_book_view_notify_update_vcard (book_view, final_vcard);
+}
+
static gpointer
book_view_thread (gpointer data)
{
@@ -643,7 +717,7 @@ book_view_thread (gpointer data)
DB *db;
DBT id_dbt, vcard_dbt;
gint db_error;
- gboolean allcontacts;
+ gboolean allcontacts, uid_only;
g_return_val_if_fail (E_IS_DATA_BOOK_VIEW (data), NULL);
@@ -672,6 +746,9 @@ book_view_thread (gpointer data)
allcontacts = FALSE;
}
+ /* Check if the view only wants UID in the fields-of-interest */
+ uid_only = view_wants_uid_only (book_view);
+
d(printf ("signalling parent thread\n"));
e_flag_set (closure->running);
@@ -689,6 +766,11 @@ book_view_thread (gpointer data)
if (!e_flag_is_set (closure->running))
break;
+ if (uid_only) {
+ notify_update_vcard (book_view, TRUE, id, NULL);
+ continue;
+ }
+
string_to_dbt (id, &id_dbt);
memset (&vcard_dbt, 0, sizeof (vcard_dbt));
vcard_dbt.flags = DB_DBT_MALLOC;
@@ -696,7 +778,7 @@ book_view_thread (gpointer data)
db_error = db->get (db, NULL, &id_dbt, &vcard_dbt, 0);
if (db_error == 0) {
- e_data_book_view_notify_update_prefiltered_vcard (book_view, id, vcard_dbt.data);
+ notify_update_vcard (book_view, TRUE, id, vcard_dbt.data);
}
else {
g_warning (G_STRLOC ": db->get failed with %s", db_strerror (db_error));
@@ -724,10 +806,8 @@ book_view_thread (gpointer data)
/* don't include the version in the list of cards */
if (strcmp (id_dbt.data, E_BOOK_BACKEND_FILE_VERSION_NAME)) {
- if (allcontacts)
- e_data_book_view_notify_update_prefiltered_vcard (book_view, id_dbt.data, vcard_dbt.data);
- else
- e_data_book_view_notify_update_vcard (book_view, vcard_dbt.data);
+ notify_update_vcard (book_view, allcontacts,
+ id_dbt.data, vcard_dbt.data);
} else {
g_free (vcard_dbt.data);
}
diff --git a/addressbook/libebook/e-contact.c b/addressbook/libebook/e-contact.c
index 8ea4904..048d159 100644
--- a/addressbook/libebook/e-contact.c
+++ b/addressbook/libebook/e-contact.c
@@ -1719,6 +1719,44 @@ e_contact_set_attributes (EContact *contact, EContactField field_id, GList *attr
}
/**
+ * e_contact_copy_attributes:
+ * @source: an #EContact
+ * @dest: another #EContact
+ * @field_id: an #EContactField
+ * @attributes: a #GList of pointers to #EVCardAttribute
+ *
+ * Copies the attributes for @field_id from @source into @dest
+ **/
+void
+e_contact_copy_attributes (EContact *source, EContact *dest, EContactField field_id)
+{
+ GList *attrs, *a;
+ const EContactFieldInfo *info = NULL;
+
+ g_return_if_fail (source && E_IS_CONTACT (source));
+ g_return_if_fail (dest && E_IS_CONTACT (dest));
+ g_return_if_fail (field_id >= 1 && field_id <= E_CONTACT_FIELD_LAST);
+
+ info = &field_info[field_id];
+
+ attrs = e_vcard_get_attributes (E_VCARD (source));
+
+ e_vcard_remove_attributes (E_VCARD (dest), NULL, info->vcard_field_name);
+
+ for (a = attrs; a; a = a->next) {
+ EVCardAttribute *attr = a->data;
+ const gchar *name;
+
+ name = e_vcard_attribute_get_name (attr);
+
+ if (!g_ascii_strcasecmp (name, info->vcard_field_name)) {
+ e_vcard_append_attribute (E_VCARD (dest),
+ e_vcard_attribute_copy (attr));
+ }
+ }
+}
+
+/**
* e_contact_name_new:
*
* Creates a new #EContactName struct.
diff --git a/addressbook/libebook/e-contact.h b/addressbook/libebook/e-contact.h
index 729eeeb..64ed5b8 100644
--- a/addressbook/libebook/e-contact.h
+++ b/addressbook/libebook/e-contact.h
@@ -314,6 +314,7 @@ void e_contact_set (EContact *contact, EContactF
EVCardAttribute*'s. */
GList* e_contact_get_attributes (EContact *contact, EContactField field_id);
void e_contact_set_attributes (EContact *contact, EContactField field_id, GList *attributes);
+void e_contact_copy_attributes (EContact *source, EContact *dest, EContactField field_id);
/* misc functions for structured values */
GType e_contact_date_get_type (void);
diff --git a/addressbook/libedata-book/e-book-backend.c b/addressbook/libedata-book/e-book-backend.c
index 358f489..3ae958e 100644
--- a/addressbook/libedata-book/e-book-backend.c
+++ b/addressbook/libedata-book/e-book-backend.c
@@ -804,7 +804,9 @@ e_book_backend_remove_client (EBookBackend *backend,
* @callback returns %FALSE to stop further processing.
**/
void
-e_book_backend_foreach_view (EBookBackend *backend, gboolean (* callback) (EDataBookView *view, gpointer user_data), gpointer user_data)
+e_book_backend_foreach_view (EBookBackend *backend,
+ gboolean (* callback) (EDataBookView *view, gpointer user_data),
+ gpointer user_data)
{
const GSList *views;
EDataBookView *view;
@@ -1026,10 +1028,51 @@ e_book_backend_sync (EBookBackend *backend)
+
+typedef struct {
+ EContact *contact;
+ EContact *shallow;
+} FilterContactData;
+
+static void
+foreach_filter_contact (const gchar *field,
+ gpointer present,
+ FilterContactData *data)
+{
+ EContactField field_id;
+
+ field_id = e_contact_field_id (field);
+ e_contact_copy_attributes (data->contact, data->shallow, field_id);
+}
+
static gboolean
-view_notify_update (EDataBookView *view, gpointer contact)
+view_notify_update (EDataBookView *view, gpointer data)
{
- e_data_book_view_notify_update (view, contact);
+ EContact *contact = data;
+ GHashTable *fields;
+
+ fields = e_data_book_view_get_fields_of_interest (view);
+ if (fields && g_hash_table_size (fields) > 0) {
+ FilterContactData data = { 0, };
+ EContact *shallow = e_contact_new ();
+ gchar *vcard;
+
+ /* Set the UID unconditionally */
+ e_contact_set (shallow, E_CONTACT_UID, e_contact_get_const (contact, E_CONTACT_UID));
+
+ /* Transfer any attributes for the fields-of-interest */
+ data.contact = contact;
+ data.shallow = shallow;
+ g_hash_table_foreach (fields, (GHFunc)foreach_filter_contact, &data);
+
+ vcard = e_vcard_to_string (E_VCARD (shallow), EVC_FORMAT_VCARD_30);
+ g_object_unref (shallow);
+
+ /* Notify with a stripped vcard holding only the fields-of-interest */
+ e_data_book_view_notify_update_vcard (view, vcard);
+ } else {
+ e_data_book_view_notify_update (view, contact);
+ }
return TRUE;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]