[evolution-data-server/openismus-work-master: 5/12] 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: 5/12] Handle fields-of-interest for local addressbook backend.
- Date: Fri, 29 Jul 2011 23:55:57 +0000 (UTC)
commit 829a0bba52de999fedbbd24a8767c8c5bdc74015
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 refactors the local addressbook backend to use
the new sqlitedb api instead of the old summary apis.
The result is that vcards are virtually built from the
sqlitedb cache when fields-of-interest is set.
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 | 303 +++++++++++++----------
addressbook/libebook/e-contact.c | 38 +++
addressbook/libebook/e-contact.h | 1 +
addressbook/libedata-book/e-book-backend.c | 49 ++++-
4 files changed, 259 insertions(+), 132 deletions(-)
---
diff --git a/addressbook/backends/file/e-book-backend-file.c b/addressbook/backends/file/e-book-backend-file.c
index 596c829..f9ea22e 100644
--- a/addressbook/backends/file/e-book-backend-file.c
+++ b/addressbook/backends/file/e-book-backend-file.c
@@ -48,7 +48,7 @@
#include "libebook/e-contact.h"
#include "libedata-book/e-book-backend-sexp.h"
-#include "libedata-book/e-book-backend-summary.h"
+#include "libedata-book/e-book-backend-sqlitedb.h"
#include "libedata-book/e-data-book.h"
#include "libedata-book/e-data-book-view.h"
@@ -62,7 +62,11 @@
#define E_BOOK_BACKEND_FILE_VERSION "0.2"
#define PAS_ID_PREFIX "pas-id-"
-#define SUMMARY_FLUSH_TIMEOUT 5000
+
+#define SQLITEDB_EMAIL_ID "addressbook localbackend com"
+#define SQLITEDB_FOLDER_ID "folder_id"
+#define SQLITEDB_FOLDER_NAME "folder"
+
#define EDB_ERROR(_code) e_data_book_create_error (E_DATA_BOOK_STATUS_ ## _code, NULL)
#define EDB_ERROR_EX(_code, _msg) e_data_book_create_error (E_DATA_BOOK_STATUS_ ## _code, _msg)
@@ -72,10 +76,11 @@ G_DEFINE_TYPE (EBookBackendFile, e_book_backend_file, E_TYPE_BOOK_BACKEND_SYNC)
struct _EBookBackendFilePrivate {
gchar *dirname;
gchar *filename;
- gchar *summary_filename;
- DB *file_db;
- DB_ENV *env;
- EBookBackendSummary *summary;
+ DB *file_db;
+ DB_ENV *env;
+
+ EBookBackendSqliteDB *sqlitedb;
+
/* for future use */
gpointer reserved1;
gpointer reserved2;
@@ -120,7 +125,7 @@ string_to_dbt (const gchar *str, DBT *dbt)
}
static EContact*
-create_contact (gchar *uid, const gchar *vcard)
+create_contact (const gchar *uid, const gchar *vcard)
{
EContact *contact = e_contact_new_from_vcard (vcard);
if (!e_contact_get_const (contact, E_CONTACT_UID))
@@ -130,12 +135,14 @@ create_contact (gchar *uid, const gchar *vcard)
}
static gboolean
-build_summary (EBookBackendFilePrivate *bfpriv)
+build_sqlitedb (EBookBackendFilePrivate *bfpriv)
{
DB *db = bfpriv->file_db;
DBC *dbc;
gint db_error;
- DBT id_dbt, vcard_dbt;
+ DBT id_dbt, vcard_dbt;
+ GSList *contacts = NULL;
+ GError *error = NULL;
db_error = db->cursor (db, NULL, &dbc, 0);
@@ -154,8 +161,8 @@ build_summary (EBookBackendFilePrivate *bfpriv)
if (id_dbt.size != strlen (E_BOOK_BACKEND_FILE_VERSION_NAME) + 1
|| strcmp (id_dbt.data, E_BOOK_BACKEND_FILE_VERSION_NAME)) {
EContact *contact = create_contact (id_dbt.data, vcard_dbt.data);
- e_book_backend_summary_add_contact (bfpriv->summary, contact);
- g_object_unref (contact);
+
+ contacts = g_slist_prepend (contacts, contact);
}
db_error = dbc->c_get (dbc, &id_dbt, &vcard_dbt, DB_NEXT);
@@ -164,6 +171,25 @@ build_summary (EBookBackendFilePrivate *bfpriv)
dbc->c_close (dbc);
+ contacts = g_slist_reverse (contacts);
+
+ if (!e_book_backend_sqlitedb_add_contacts (bfpriv->sqlitedb,
+ SQLITEDB_FOLDER_ID,
+ contacts, FALSE, &error)) {
+ g_warning ("Failed to build contact summary: %s", error->message);
+ g_error_free (error);
+ return FALSE;
+ }
+
+ g_slist_foreach (contacts, (GFunc)g_object_unref, NULL);
+ g_slist_free (contacts);
+
+ if (!e_book_backend_sqlitedb_set_is_populated (bfpriv->sqlitedb, SQLITEDB_FOLDER_ID, TRUE, &error)) {
+ g_warning ("Failed to set the sqlitedb populated flag: %s", error->message);
+ g_error_free (error);
+ return FALSE;
+ }
+
return TRUE;
}
@@ -255,7 +281,14 @@ e_book_backend_file_create_contact (EBookBackendSync *backend,
EBookBackendFile *bf = E_BOOK_BACKEND_FILE (backend);
if (do_create (bf, vcard, contact, perror)) {
- e_book_backend_summary_add_contact (bf->priv->summary, *contact);
+ GError *error = NULL;
+
+ if (!e_book_backend_sqlitedb_add_contact (bf->priv->sqlitedb,
+ SQLITEDB_FOLDER_ID,
+ *contact, FALSE, &error)) {
+ g_warning ("Failed to add contact to summary: %s", error->message);
+ g_error_free (error);
+ }
}
}
@@ -268,12 +301,13 @@ e_book_backend_file_remove_contacts (EBookBackendSync *backend,
GError **perror)
{
EBookBackendFile *bf = E_BOOK_BACKEND_FILE (backend);
- DB *db = bf->priv->file_db;
- DBT id_dbt;
- gint db_error;
- const gchar *id;
- const GSList *l;
- GSList *removed_cards = NULL;
+ DB *db = bf->priv->file_db;
+ DBT id_dbt;
+ gint db_error;
+ const gchar *id;
+ GSList *removed_cards = NULL;
+ const GSList *l;
+ GError *error = NULL;
for (l = id_list; l; l = l->next) {
id = l->data;
@@ -297,12 +331,14 @@ e_book_backend_file_remove_contacts (EBookBackendSync *backend,
g_warning (G_STRLOC ": db->sync failed with %s", db_strerror (db_error));
}
- *ids = removed_cards;
-
- for (l = removed_cards; l; l = l->next) {
- id = l->data;
- e_book_backend_summary_remove_contact (bf->priv->summary, id);
+ if (!e_book_backend_sqlitedb_remove_contacts (bf->priv->sqlitedb,
+ SQLITEDB_FOLDER_ID,
+ removed_cards, &error)) {
+ g_warning ("Failed to remove contacts from the summary: %s", error->message);
+ g_error_free (error);
}
+
+ *ids = removed_cards;
}
static void
@@ -353,8 +389,19 @@ e_book_backend_file_modify_contact (EBookBackendSync *backend,
if (db_error != 0) {
g_warning (G_STRLOC ": db->sync failed with %s", db_strerror (db_error));
} else {
- e_book_backend_summary_remove_contact (bf->priv->summary, id);
- e_book_backend_summary_add_contact (bf->priv->summary, *contact);
+ GError *error = NULL;
+
+ if (!e_book_backend_sqlitedb_remove_contact (bf->priv->sqlitedb,
+ SQLITEDB_FOLDER_ID,
+ id, &error)) {
+ g_warning ("Failed to remove contact from the summary: %s", error->message);
+ g_error_free (error);
+ } else if (!e_book_backend_sqlitedb_add_contact (bf->priv->sqlitedb,
+ SQLITEDB_FOLDER_ID,
+ *contact, FALSE, &error)) {
+ g_warning ("Failed to add contact to summary: %s", error->message);
+ g_error_free (error);
+ }
}
} else {
g_warning (G_STRLOC ": db->put failed with %s", db_strerror(db_error));
@@ -412,36 +459,27 @@ e_book_backend_file_get_contact_list (EBookBackendSync *backend,
EBookBackendSExp *card_sexp = NULL;
gboolean search_needed;
const gchar *search = query;
- GSList *contact_list = NULL;
+ GSList *contact_list = NULL, *l;
+ GSList *summary_list = NULL;
d(printf ("e_book_backend_file_get_contact_list (%s)\n", search));
- if (e_book_backend_summary_is_summary_query (bf->priv->summary, search)) {
- /* do a summary query */
- GPtrArray *ids = e_book_backend_summary_search (bf->priv->summary, search);
- gint i;
+ summary_list = e_book_backend_sqlitedb_search (bf->priv->sqlitedb,
+ SQLITEDB_FOLDER_ID,
+ search, NULL, NULL);
- if (!ids) {
- g_propagate_error (perror, EDB_ERROR (CONTACT_NOT_FOUND));
- return;
- }
+ if (summary_list) {
- for (i = 0; i < ids->len; i++) {
- gchar *id = g_ptr_array_index (ids, i);
- string_to_dbt (id, &id_dbt);
- memset (&vcard_dbt, 0, sizeof (vcard_dbt));
- vcard_dbt.flags = DB_DBT_MALLOC;
+ for (l = summary_list; l; l = l->next) {
+ EbSdbSearchData *data = l->data;
- db_error = db->get (db, NULL, &id_dbt, &vcard_dbt, 0);
- if (db_error == 0) {
- contact_list = g_slist_prepend (contact_list, vcard_dbt.data);
- } else {
- g_warning (G_STRLOC ": db->get failed with %s", db_strerror (db_error));
- db_error_to_gerror (db_error, perror);
- break;
- }
+ contact_list = g_slist_prepend (contact_list, data->vcard);
+ data->vcard = NULL;
}
- g_ptr_array_free (ids, TRUE);
+
+ g_slist_foreach (summary_list, (GFunc)e_book_backend_sqlitedb_search_data_free, NULL);
+ g_slist_free (summary_list);
+
} else {
search_needed = TRUE;
if (!strcmp (search, "(contains \"x-evolution-any-field\" \"\")"))
@@ -522,24 +560,12 @@ e_book_backend_file_get_contact_list_uids (EBookBackendSync *backend,
GSList *uids = NULL;
d(printf ("e_book_backend_file_get_contact_list (%s)\n", search));
- if (e_book_backend_summary_is_summary_query (bf->priv->summary, search)) {
- /* do a summary query */
- GPtrArray *ids = e_book_backend_summary_search (bf->priv->summary, search);
- gint i;
-
- if (!ids) {
- g_propagate_error (perror, EDB_ERROR (CONTACT_NOT_FOUND));
- return;
- }
- for (i = 0; i < ids->len; i++) {
- gchar *id = g_ptr_array_index (ids, i);
+ uids = e_book_backend_sqlitedb_search_uids (bf->priv->sqlitedb,
+ SQLITEDB_FOLDER_ID,
+ search, NULL);
- uids = g_slist_prepend (uids, g_strdup (id));
- }
-
- g_ptr_array_free (ids, TRUE);
- } else {
+ if (!uids) {
search_needed = TRUE;
if (!strcmp (search, "(contains \"x-evolution-any-field\" \"\")"))
search_needed = FALSE;
@@ -633,6 +659,38 @@ get_closure (EDataBookView *book_view)
return g_object_get_data (G_OBJECT (book_view), "EBookBackendFile.BookView::closure");
}
+static void
+notify_update_vcard (EDataBookView *book_view,
+ gboolean prefiltered,
+ const gchar *id,
+ gchar *vcard)
+{
+ if (prefiltered)
+ e_data_book_view_notify_update_prefiltered_vcard (book_view, id, vcard);
+ else
+ e_data_book_view_notify_update_vcard (book_view, vcard);
+}
+
+static void
+accumulate_fields (gchar *field_name,
+ gpointer is_present,
+ GSList **accum_list)
+{
+ *accum_list = g_slist_prepend (*accum_list, field_name);
+}
+
+static GSList *
+generate_fields_of_interest_list (EDataBookView *book_view)
+{
+ GHashTable *fields = e_data_book_view_get_fields_of_interest (book_view);
+ GSList *interest_list = NULL;
+
+ if (fields)
+ g_hash_table_foreach (fields, (GHFunc)accumulate_fields, &interest_list);
+
+ return interest_list;
+}
+
static gpointer
book_view_thread (gpointer data)
{
@@ -644,6 +702,7 @@ book_view_thread (gpointer data)
DBT id_dbt, vcard_dbt;
gint db_error;
gboolean allcontacts;
+ GSList *summary_list, *fields_of_interest, *l;
g_return_val_if_fail (E_IS_DATA_BOOK_VIEW (data), NULL);
@@ -661,8 +720,9 @@ book_view_thread (gpointer data)
when/if it's stopped */
e_data_book_view_ref (book_view);
- db = bf->priv->file_db;
- query = e_data_book_view_get_card_query (book_view);
+ db = bf->priv->file_db;
+ query = e_data_book_view_get_card_query (book_view);
+ fields_of_interest = generate_fields_of_interest_list (book_view);
if ( !strcmp (query, "(contains \"x-evolution-any-field\" \"\")")) {
e_data_book_view_notify_progress (book_view, -1, _("Loading..."));
@@ -675,37 +735,21 @@ book_view_thread (gpointer data)
d(printf ("signalling parent thread\n"));
e_flag_set (closure->running);
- if (e_book_backend_summary_is_summary_query (bf->priv->summary, query)) {
- /* do a summary query */
- GPtrArray *ids = e_book_backend_summary_search (bf->priv->summary, e_data_book_view_get_card_query (book_view));
- gint i;
-
- if (!ids)
- goto done;
-
- for (i = 0; i < ids->len; i++) {
- gchar *id = g_ptr_array_index (ids, i);
-
- if (!e_flag_is_set (closure->running))
- break;
+ summary_list = e_book_backend_sqlitedb_search (bf->priv->sqlitedb,
+ SQLITEDB_FOLDER_ID,
+ query, fields_of_interest, NULL);
+ if (summary_list) {
- string_to_dbt (id, &id_dbt);
- memset (&vcard_dbt, 0, sizeof (vcard_dbt));
- vcard_dbt.flags = DB_DBT_MALLOC;
+ for (l = summary_list; l; l = l->next) {
+ EbSdbSearchData *data = l->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);
- }
- else {
- g_warning (G_STRLOC ": db->get failed with %s", db_strerror (db_error));
- }
+ notify_update_vcard (book_view, TRUE, data->uid, data->vcard);
+ data->vcard = NULL;
}
- g_ptr_array_free (ids, TRUE);
- }
- else {
+ g_slist_foreach (summary_list, (GFunc)e_book_backend_sqlitedb_search_data_free, NULL);
+ g_slist_free (summary_list);
+ } else {
/* iterate over the db and do the query there */
DBC *dbc;
@@ -724,10 +768,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);
}
@@ -747,7 +789,9 @@ book_view_thread (gpointer data)
}
}
-done:
+
+ g_slist_free (fields_of_interest);
+
if (e_flag_is_set (closure->running))
e_data_book_view_notify_complete (book_view, NULL /* Success */);
@@ -997,14 +1041,13 @@ e_book_backend_file_open (EBookBackendSync *backend,
GError **perror)
{
EBookBackendFile *bf = E_BOOK_BACKEND_FILE (backend);
- gchar *dirname, *filename;
- gboolean readonly = TRUE;
- ESource *source = e_book_backend_get_source (E_BOOK_BACKEND (backend));
- gint db_error;
- DB *db;
- DB_ENV *env;
- time_t db_mtime;
- struct stat sb;
+ gchar *dirname, *filename;
+ gboolean readonly = TRUE;
+ ESource *source = e_book_backend_get_source (E_BOOK_BACKEND (backend));
+ gint db_error;
+ DB *db;
+ DB_ENV *env;
+ GError *local_error = NULL;
#ifdef CREATE_DEFAULT_VCARD
gboolean create_default_vcard = FALSE;
@@ -1200,23 +1243,25 @@ e_book_backend_file_open (EBookBackendSync *backend,
bf->priv->dirname = dirname;
bf->priv->filename = filename;
- if (g_stat (bf->priv->filename, &sb) == -1) {
- db->close (db, 0);
- bf->priv->file_db = NULL;
- g_propagate_error (perror, e_data_book_create_error_fmt (E_DATA_BOOK_STATUS_OTHER_ERROR, "stat(%s) failed", bf->priv->filename));
+ bf->priv->sqlitedb = e_book_backend_sqlitedb_new (bf->priv->dirname,
+ SQLITEDB_EMAIL_ID,
+ SQLITEDB_FOLDER_ID,
+ SQLITEDB_FOLDER_NAME,
+ FALSE,
+ perror);
+ if (!bf->priv->sqlitedb)
return;
- }
- db_mtime = sb.st_mtime;
-
- g_free (bf->priv->summary_filename);
- bf->priv->summary_filename = g_strconcat (bf->priv->filename, ".summary", NULL);
- bf->priv->summary = e_book_backend_summary_new (bf->priv->summary_filename, SUMMARY_FLUSH_TIMEOUT);
- if (e_book_backend_summary_is_up_to_date (bf->priv->summary, db_mtime) == FALSE
- || e_book_backend_summary_load (bf->priv->summary) == FALSE ) {
- if (!bf->priv->summary || !build_summary (bf->priv)) {
- g_propagate_error (perror, e_data_book_create_error_fmt (E_DATA_BOOK_STATUS_OTHER_ERROR, "Failed to build summary for an address book %s", bf->priv->filename));
+ if (!e_book_backend_sqlitedb_get_is_populated (bf->priv->sqlitedb,
+ SQLITEDB_FOLDER_ID,
+ &local_error)) {
+ if (local_error) {
+ g_propagate_error (perror, local_error);
return;
+ } else if (!build_sqlitedb (bf->priv)) {
+ g_propagate_error (perror, e_data_book_create_error_fmt (E_DATA_BOOK_STATUS_OTHER_ERROR,
+ "Failed to build summary for an address book %s",
+ bf->priv->filename));
}
}
@@ -1261,11 +1306,12 @@ e_book_backend_file_remove (EBookBackendSync *backend,
return;
}
- /* unref the summary before we remove the file so it's not written out again */
- g_object_unref (bf->priv->summary);
- bf->priv->summary = NULL;
- if (-1 == g_unlink (bf->priv->summary_filename))
- g_warning ("failed to remove summary file `%s`: %s", bf->priv->summary_filename, g_strerror (errno));
+ if (!e_book_backend_sqlitedb_remove (bf->priv->sqlitedb, perror))
+ return;
+
+ /* unref the sqlitedb before we remove the file so it's not written out again */
+ g_object_unref (bf->priv->sqlitedb);
+ bf->priv->sqlitedb = NULL;
dir = g_dir_open (bf->priv->dirname, 0, NULL);
if (dir) {
@@ -1377,9 +1423,9 @@ e_book_backend_file_dispose (GObject *object)
}
G_UNLOCK (global_env);
- if (bf->priv->summary) {
- g_object_unref (bf->priv->summary);
- bf->priv->summary = NULL;
+ if (bf->priv->sqlitedb) {
+ g_object_unref (bf->priv->sqlitedb);
+ bf->priv->sqlitedb = NULL;
}
G_OBJECT_CLASS (e_book_backend_file_parent_class)->dispose (object);
@@ -1394,7 +1440,6 @@ e_book_backend_file_finalize (GObject *object)
g_free (bf->priv->filename);
g_free (bf->priv->dirname);
- g_free (bf->priv->summary_filename);
g_free (bf->priv);
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]