[evolution-data-server] Bug #652173 - libebook: Delay client-side vCard parsing
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server] Bug #652173 - libebook: Delay client-side vCard parsing
- Date: Wed, 22 Jun 2011 14:19:01 +0000 (UTC)
commit b4e498e53e058872f524552b2508d918fa531c01
Author: Christophe Dumez <christophe dumez intel com>
Date: Wed Jun 22 16:18:21 2011 +0200
Bug #652173 - libebook: Delay client-side vCard parsing
addressbook/libebook/e-contact.c | 111 +++++++++++++++++++++++--------------
addressbook/libebook/e-vcard.c | 66 +++++++++++++++++++---
addressbook/libebook/e-vcard.h | 2 +
3 files changed, 128 insertions(+), 51 deletions(-)
---
diff --git a/addressbook/libebook/e-contact.c b/addressbook/libebook/e-contact.c
index f486eb5..9fd6982 100644
--- a/addressbook/libebook/e-contact.c
+++ b/addressbook/libebook/e-contact.c
@@ -87,6 +87,8 @@ static gpointer fn_getter (EContact *contact, EVCardAttribute *attr);
static void fn_setter (EContact *contact, EVCardAttribute *attr, gpointer data);
static gpointer n_getter (EContact *contact, EVCardAttribute *attr);
static void n_setter (EContact *contact, EVCardAttribute *attr, gpointer data);
+static gpointer fileas_getter (EContact *contact, EVCardAttribute *attr);
+static void fileas_setter (EContact *contact, EVCardAttribute *attr, gpointer data);
static gpointer adr_getter (EContact *contact, EVCardAttribute *attr);
static void adr_setter (EContact *contact, EVCardAttribute *attr, gpointer data);
static gpointer date_getter (EContact *contact, EVCardAttribute *attr);
@@ -112,7 +114,9 @@ static void cert_setter (EContact *contact, EVCardAttribute *attr, gpointer data
static const EContactFieldInfo field_info[] = {
{0,}, /* Dummy row as EContactField starts from 1 */
STRING_FIELD (E_CONTACT_UID, EVC_UID, "id", N_("Unique ID"), FALSE),
- STRING_FIELD (E_CONTACT_FILE_AS, EVC_X_FILE_AS, "file_as", N_("File Under"), FALSE),
+ /* FILE_AS is not really a structured field - we use a getter/setter
+ so we can generate its value if necessary in the getter */
+ GETSET_FIELD (E_CONTACT_FILE_AS, EVC_X_FILE_AS, "file_as", N_("File Under"), FALSE, fileas_getter, fileas_setter),
/* URI of the book to which the contact belongs to */
STRING_FIELD (E_CONTACT_BOOK_URI, EVC_X_BOOK_URI, "book_uri", N_("Book URI"), FALSE),
@@ -540,6 +544,68 @@ fn_setter (EContact *contact, EVCardAttribute *attr, gpointer data)
}
}
+static gpointer
+fileas_getter (EContact *contact, EVCardAttribute *attr)
+{
+ if (!attr) {
+ /* Generate a FILE_AS field */
+ EContactName *name;
+ gchar* new_file_as = NULL;
+
+ name = e_contact_get (contact, E_CONTACT_NAME);
+
+ /* Use name if available */
+ if (name) {
+ gchar *strings[3], **stringptr;
+
+ stringptr = strings;
+ if (name->family && *name->family)
+ *(stringptr++) = name->family;
+ if (name->given && *name->given)
+ *(stringptr++) = name->given;
+ if (stringptr != strings) {
+ *stringptr = NULL;
+ new_file_as = g_strjoinv (", ", strings);
+ }
+
+ e_contact_name_free (name);
+ }
+
+ /* Use org as fallback */
+ if (!new_file_as) {
+ const gchar *org = e_contact_get_const (contact, E_CONTACT_ORG);
+
+ if (org && *org) {
+ new_file_as = g_strdup (org);
+ }
+ }
+
+ /* Add the FILE_AS attribute to the vcard */
+ if (new_file_as) {
+ attr = e_vcard_attribute_new (NULL, EVC_X_FILE_AS);
+ e_vcard_add_attribute_with_value (E_VCARD (contact), attr, new_file_as);
+
+ g_free (new_file_as);
+ }
+ }
+
+ if (attr) {
+ GList *p = e_vcard_attribute_get_values (attr);
+
+ return p && p->data ? p->data : (gpointer) "";
+ } else {
+ return NULL;
+ }
+}
+
+static void
+fileas_setter (EContact *contact, EVCardAttribute *attr, gpointer data)
+{
+ /* Default implementation */
+ const gchar* file_as = data;
+ e_vcard_attribute_add_value (attr, file_as ? : "");
+}
+
static gpointer
@@ -1214,49 +1280,11 @@ EContact*
e_contact_new_from_vcard (const gchar *vcard)
{
EContact *contact;
- const gchar *file_as;
-
g_return_val_if_fail (vcard != NULL, NULL);
contact = g_object_new (E_TYPE_CONTACT, NULL);
e_vcard_construct (E_VCARD (contact), vcard);
- /* Generate a FILE_AS field if needed */
-
- file_as = e_contact_get_const (contact, E_CONTACT_FILE_AS);
- if (!file_as || !*file_as) {
- EContactName *name;
- const gchar *org;
- gchar *file_as_new = NULL;
- gchar *strings[4];
- gchar **strings_p = strings;
-
- name = e_contact_get (contact, E_CONTACT_NAME);
- org = e_contact_get_const (contact, E_CONTACT_ORG);
-
- if (name) {
- if (name->family && *name->family)
- *(strings_p++) = name->family;
- if (name->given && *name->given)
- *(strings_p++) = name->given;
-
- if (strings_p != strings) {
- *strings_p = NULL;
- file_as_new = g_strjoinv (", ", strings);
- }
-
- e_contact_name_free (name);
- }
-
- if (!file_as_new && org && *org)
- file_as_new = g_strdup (org);
-
- if (file_as_new) {
- e_contact_set (contact, E_CONTACT_FILE_AS, file_as_new);
- g_free (file_as_new);
- }
- }
-
return contact;
}
@@ -1488,15 +1516,14 @@ e_contact_get (EContact *contact, EContactField field_id)
EVCardAttribute *attr = e_contact_get_first_attr (contact, info->vcard_field_name);
gpointer rv = NULL;
- if (attr)
- rv = info->struct_getter (contact, attr);
+ rv = info->struct_getter (contact, attr);
if (info->t & E_CONTACT_FIELD_TYPE_STRUCT)
return (gpointer) info->boxed_type_getter ();
else if (!rv)
return NULL;
else
- return g_strstrip (g_strdup (rv));
+ return rv ? g_strstrip (g_strdup (rv)) : NULL;
}
else if (info->t & E_CONTACT_FIELD_TYPE_SYNTHETIC) {
switch (info->field_id) {
diff --git a/addressbook/libebook/e-vcard.c b/addressbook/libebook/e-vcard.c
index 28fcb88..6b308d6 100644
--- a/addressbook/libebook/e-vcard.c
+++ b/addressbook/libebook/e-vcard.c
@@ -46,6 +46,7 @@ typedef enum {
struct _EVCardPrivate {
GList *attributes;
+ gchar *vcard;
};
struct _EVCardAttribute {
@@ -71,10 +72,12 @@ e_vcard_dispose (GObject *object)
EVCard *evc = E_VCARD (object);
if (evc->priv) {
-
+ /* Directly access priv->attributes and don't call e_vcard_ensure_attributes(),
+ * since it is pointless to start vCard parsing that late. */
g_list_foreach (evc->priv->attributes, (GFunc) e_vcard_attribute_free, NULL);
g_list_free (evc->priv->attributes);
+ g_free (evc->priv->vcard);
g_free (evc->priv);
evc->priv = NULL;
}
@@ -652,6 +655,24 @@ parse (EVCard *evc, const gchar *str)
evc->priv->attributes = g_list_reverse (evc->priv->attributes);
}
+static GList*
+e_vcard_ensure_attributes (EVCard *evc)
+{
+ if (evc->priv->vcard) {
+ gchar *vcs = evc->priv->vcard;
+
+ /* detach vCard to avoid loops */
+ evc->priv->vcard = NULL;
+
+ /* Parse the vCard */
+ parse (evc, vcs);
+ g_free (vcs);
+ }
+
+ return evc->priv->attributes;
+}
+
+
/**
* e_vcard_escape_string:
* @s: the string to escape
@@ -746,9 +767,12 @@ e_vcard_construct (EVCard *evc, const gchar *str)
{
g_return_if_fail (E_IS_VCARD (evc));
g_return_if_fail (str != NULL);
+ g_return_if_fail (evc->priv->vcard == NULL);
+ g_return_if_fail (evc->priv->attributes == NULL);
+ /* Lazy construction */
if (*str)
- parse (evc, str);
+ evc->priv->vcard = g_strdup (str);
}
/**
@@ -809,7 +833,7 @@ e_vcard_to_string_vcard_30 (EVCard *evc)
vcard might contain */
g_string_append (str, "VERSION:3.0" CRLF);
- for (l = evc->priv->attributes; l; l = l->next) {
+ for (l = e_vcard_ensure_attributes (evc); l; l = l->next) {
GList *list;
EVCardAttribute *attr = l->data;
GString *attr_str;
@@ -949,6 +973,12 @@ e_vcard_to_string (EVCard *evc, EVCardFormat format)
{
g_return_val_if_fail (E_IS_VCARD (evc), NULL);
+ /* If the vcard is not parsed yet, return it directly */
+ /* XXX: The format is ignored but it does not really matter
+ since only 3.0 is supported at the moment */
+ if (evc->priv->vcard)
+ return g_strdup (evc->priv->vcard);
+
switch (format) {
case EVC_FORMAT_VCARD_21:
return e_vcard_to_string_vcard_21 (evc);
@@ -977,7 +1007,7 @@ e_vcard_dump_structure (EVCard *evc)
g_return_if_fail (E_IS_VCARD (evc));
printf ("vCard\n");
- for (a = evc->priv->attributes; a; a = a->next) {
+ for (a = e_vcard_ensure_attributes (evc); a; a = a->next) {
GList *p;
EVCardAttribute *attr = a->data;
printf ("+-- %s\n", attr->name);
@@ -1114,7 +1144,7 @@ e_vcard_remove_attributes (EVCard *evc, const gchar *attr_group, const gchar *at
g_return_if_fail (E_IS_VCARD (evc));
g_return_if_fail (attr_name != NULL);
- attr = evc->priv->attributes;
+ attr = e_vcard_ensure_attributes (evc);
while (attr) {
GList *next_attr;
EVCardAttribute *a = attr->data;
@@ -1148,6 +1178,8 @@ e_vcard_remove_attribute (EVCard *evc, EVCardAttribute *attr)
g_return_if_fail (E_IS_VCARD (evc));
g_return_if_fail (attr != NULL);
+ /* No need to call e_vcard_ensure_attributes() here. It has already been
+ called if this is a valid call and attr is among our attributes */
evc->priv->attributes = g_list_remove (evc->priv->attributes, attr);
e_vcard_attribute_free (attr);
}
@@ -1167,7 +1199,7 @@ e_vcard_append_attribute (EVCard *evc, EVCardAttribute *attr)
g_return_if_fail (E_IS_VCARD (evc));
g_return_if_fail (attr != NULL);
- evc->priv->attributes = g_list_append (evc->priv->attributes, attr);
+ evc->priv->attributes = g_list_append (e_vcard_ensure_attributes (evc), attr);
}
/**
@@ -1237,7 +1269,7 @@ e_vcard_add_attribute (EVCard *evc, EVCardAttribute *attr)
g_return_if_fail (E_IS_VCARD (evc));
g_return_if_fail (attr != NULL);
- evc->priv->attributes = g_list_prepend (evc->priv->attributes, attr);
+ evc->priv->attributes = g_list_prepend (e_vcard_ensure_attributes (evc), attr);
}
/**
@@ -1808,7 +1840,7 @@ e_vcard_get_attributes (EVCard *evcard)
{
g_return_val_if_fail (E_IS_VCARD (evcard), NULL);
- return evcard->priv->attributes;
+ return e_vcard_ensure_attributes (evcard);
}
/**
@@ -1831,7 +1863,7 @@ e_vcard_get_attribute (EVCard *evc,
g_return_val_if_fail (E_IS_VCARD (evc), NULL);
g_return_val_if_fail (name != NULL, NULL);
- attrs = e_vcard_get_attributes (evc);
+ attrs = e_vcard_ensure_attributes (evc);
for (l = attrs; l; l = l->next) {
EVCardAttribute *attr;
@@ -2094,6 +2126,22 @@ e_vcard_attribute_get_param (EVCardAttribute *attr, const gchar *name)
}
/**
+ * e_vcard_is_parsed:
+ * @evc: an #EVCard
+ *
+ * Check if the @evc has been parsed already. Used for debugging.
+ *
+ * Return value: %TRUE if @evc has been parsed, %FALSE otherwise.
+ **/
+gboolean
+e_vcard_is_parsed (EVCard *evc)
+{
+ g_return_val_if_fail (E_IS_VCARD (evc), FALSE);
+ return (!evc->priv->vcard && evc->priv->attributes);
+}
+
+
+/**
* e_vcard_attribute_param_get_name:
* @param: an #EVCardAttributeParam
*
diff --git a/addressbook/libebook/e-vcard.h b/addressbook/libebook/e-vcard.h
index 696d0af..544dff4 100644
--- a/addressbook/libebook/e-vcard.h
+++ b/addressbook/libebook/e-vcard.h
@@ -159,6 +159,8 @@ void e_vcard_construct (EVCard *evc, const gchar *str);
EVCard* e_vcard_new (void);
EVCard* e_vcard_new_from_string (const gchar *str);
+gboolean e_vcard_is_parsed (EVCard *evc);
+
gchar * e_vcard_to_string (EVCard *evc, EVCardFormat format);
/* mostly for debugging */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]