static ESExpResult * func_exists_vcard (struct _ESExp *f, gint argc, struct _ESExpResult **argv, gpointer data) { SearchContext *ctx = data; ESExpResult *r; gint truth = FALSE; if (argc == 1 && argv[0]->type == ESEXP_RES_STRING) { const gchar *attr_name; EVCardAttribute *attr; GList *values; gchar *s; attr_name = argv[0]->value.string; attr = e_vcard_get_attribute (E_VCARD (ctx->contact), attr_name); if (attr) { values = e_vcard_attribute_get_values (attr); if (g_list_length (values) > 0) { s = values->data; if (s[0] != '\0') { truth = TRUE; } } } } r = e_sexp_result_new (f, ESEXP_RES_BOOL); r->value.boolean = truth; return r; }
static void contacts_change_groups_cb (GtkWidget *widget, ContactsGroupChangeData *data) { GList *g, *bools = NULL; GList *results = NULL; GList *values = e_vcard_attribute_get_values (data->attr); for (g = data->contacts_data->contacts_groups; g; g = g->next) { if (g_list_find_custom (values, g->data, (GCompareFunc)strcmp)) bools = g_list_append (bools, GINT_TO_POINTER (TRUE)); else bools = g_list_append (bools, GINT_TO_POINTER (FALSE)); } if (contacts_chooser (data->contacts_data, _("Change groups"), _("<b>Choose groups" "</b>"), data->contacts_data->contacts_groups, bools, TRUE, TRUE, &results)) { gchar *new_groups = results ? contacts_string_list_as_string (results, ", ", FALSE) : g_strdup ("None"); g_free (new_groups); e_vcard_attribute_remove_values (data->attr); for (g = results; g; g = g->next) { e_vcard_attribute_add_value (data->attr, g->data); if (!g_list_find_custom (data->contacts_data->contacts_groups, g->data, (GCompareFunc) strcmp)) data->contacts_data->contacts_groups = g_list_prepend (data->contacts_data->contacts_groups, g_strdup (g->data)); } data->contacts_data->changed = TRUE; } }
static char *evcard_name_attribute_to_string(EVCard *evcard) { EVCardAttribute *attrib; GList *l; GString *name = NULL; attrib = e_vcard_get_attribute(evcard, EVC_N); if (!attrib) return NULL; for (l = e_vcard_attribute_get_values(attrib); l; l = l->next) { const char *value = l->data; if (!strlen(value)) continue; if (!name) name = g_string_new(value); else { name = g_string_append(name, ";"); name = g_string_append(name, l->data); } } if (!name) return NULL; return g_string_free(name, FALSE); }
/* * Strip empty attributes from a vcard * Returns: the number of attributes left on the card */ gint hito_vcard_strip_empty_attributes (EVCard *card) { GList *attrs, *values; gboolean remove; EVCardAttribute *attribute; gint count = 0; attrs = e_vcard_get_attributes (card); while (attrs) { count++; attribute = attrs->data; remove = TRUE; values = e_vcard_attribute_get_values (attrs->data); while (values) { if (g_utf8_strlen (values->data, -1) > 0) { remove = FALSE; break; } values = g_list_next (values); } attrs = g_list_next (attrs); if (remove) { e_vcard_remove_attribute (card, attribute); count--; } } return count; }
/** * e_vcard_attribute_get_value: * @attr: an #EVCardAttribute * * Gets the value of a single-valued #EVCardAttribute, @attr. * * Return value: A newly allocated string representing the value. **/ char* e_vcard_attribute_get_value (EVCardAttribute *attr) { GList *values; g_return_val_if_fail (attr != NULL, NULL); values = e_vcard_attribute_get_values (attr); if (!e_vcard_attribute_is_single_valued (attr)) g_warning ("e_vcard_attribute_get_value called on multivalued attribute"); return values ? g_strdup ((char*)values->data) : NULL; }
/* * load the attribute value, returning a newly allocated semicolon seperated * string for multivalue attributes */ gchar* hito_vcard_attribute_get_value_string (EVCardAttribute *attr) { gchar *attr_value = NULL; GList *l; l = e_vcard_attribute_get_values (attr); if (l) { attr_value = g_strdup (l->data); while ((l = g_list_next (l))) { gchar *old = attr_value; if (old) attr_value = g_strdup_printf ("%s; %s", old, (gchar*) l->data); else attr_value = g_strdup (l->data); g_free (old); } } return attr_value; }
gboolean hito_vcard_attribute_has_value (EVCardAttribute *attr, const gchar *value) { GList *list; gboolean result; g_return_val_if_fail (attr, FALSE); g_return_val_if_fail (value, FALSE); result = FALSE; list = e_vcard_attribute_get_values (attr); while (list) { if (list->data && g_str_equal (list->data, value)) { result = TRUE; break; } list = g_list_next (list); } return result; }
/* Calbacks */ static void moko_contacts_add_contact (MokoContacts *contacts, EContact *e_contact) { MokoContactsPrivate *priv; MokoContact *m_contact = NULL; const gchar *name, *uid; GList *attributes, *params, *numbers; g_return_if_fail (MOKO_IS_CONTACTS (contacts)); g_return_if_fail (E_IS_CONTACT (e_contact)); priv = contacts->priv; uid = e_contact_get_const (e_contact, E_CONTACT_UID); if (g_hash_table_lookup (priv->uids, uid)) return; name = e_contact_get_const (e_contact, E_CONTACT_FULL_NAME); if (!name || (g_utf8_strlen (name, -1) <= 0)) name = "Unknown"; /* Create the contact & append to the list */ m_contact = g_new0 (MokoContact, 1); m_contact->name = g_strdup (name); m_contact->uid = g_strdup (uid); m_contact->photo = NULL; priv->contacts = g_list_append (priv->contacts, m_contact); g_hash_table_insert (priv->uids, g_strdup (uid), m_contact); /* Now go through the numbers,creating MokoNumber for them */ for (attributes = e_vcard_get_attributes (E_VCARD(e_contact)); attributes; attributes = attributes->next) { MokoContactEntry *entry; const gchar *phone; const char *attr; attr = e_vcard_attribute_get_name (attributes->data); if (!strcmp (attr, EVC_TEL)) { for (numbers = e_vcard_attribute_get_values (attributes->data); numbers; numbers = numbers->next) { phone = numbers->data; if (phone) { entry = g_new0 (MokoContactEntry, 1); params = e_vcard_attribute_get_param (attributes->data, "TYPE"); if (params) entry->desc = g_strdup (params->data); entry->number = normalize (phone); entry->contact = m_contact; priv->entries = g_list_append (priv->entries, (gpointer)entry); g_hash_table_insert (priv->prefixes, g_strdup (entry->number), (gpointer)entry); add_number (&priv->start, entry); } } } } }
static ESExpResult * func_exists (struct _ESExp *f, gint argc, struct _ESExpResult **argv, gpointer data) { SearchContext *ctx = data; ESExpResult *r; gint truth = FALSE; if (argc == 1 && argv[0]->type == ESEXP_RES_STRING) { const gchar *propname; struct prop_info *info = NULL; gint i; gboolean saw_any = FALSE; propname = argv[0]->value.string; for (i = 0; i < G_N_ELEMENTS (prop_info_table); i++) { if (!strcmp (prop_info_table[i].query_prop, propname)) { saw_any = TRUE; info = &prop_info_table[i]; if (info->prop_type == PROP_TYPE_NORMAL) { const gchar *prop = NULL; /* searches where the query's property * maps directly to an ecard property */ prop = e_contact_get_const (ctx->contact, info->field_id); if (prop && *prop) truth = TRUE; } else if (info->prop_type == PROP_TYPE_LIST) { /* the special searches that match any of the list elements */ truth = info->list_compare (ctx->contact, "", NULL, exists_helper); } else if (info->prop_type == PROP_TYPE_DATE) { EContactDate *date; date = e_contact_get (ctx->contact, info->field_id); if (date) { truth = TRUE; e_contact_date_free (date); } } else { g_warn_if_reached (); saw_any = FALSE; } break; } } if (!saw_any) { /* propname didn't match to any of our known "special" properties, * so try to find if it isn't a real field and if so, then check * against value in this field only */ EContactField fid = e_contact_field_id (propname); if (fid >= E_CONTACT_FIELD_FIRST && fid < E_CONTACT_FIELD_LAST && e_contact_field_is_string (fid)) { const gchar *prop = e_contact_get_const (ctx->contact, fid); if (prop && *prop) truth = TRUE; } else { /* is is not a known EContact field, try with EVCard attributes */ EVCardAttribute *attr; GList *l, *values; if (fid >= E_CONTACT_FIELD_FIRST && fid < E_CONTACT_FIELD_LAST) propname = e_contact_vcard_attribute (fid); attr = e_vcard_get_attribute (E_VCARD (ctx->contact), propname); values = attr ? e_vcard_attribute_get_values (attr) : NULL; for (l = values; l && !truth; l = l->next) { const gchar *value = l->data; if (value && *value) truth = TRUE; } } } } r = e_sexp_result_new (f, ESEXP_RES_BOOL); r->value.boolean = truth; return r; }
static ESExpResult * entry_compare (SearchContext *ctx, struct _ESExp *f, gint argc, struct _ESExpResult **argv, CompareFunc compare) { ESExpResult *r; gint truth = FALSE; if ((argc == 2 && argv[0]->type == ESEXP_RES_STRING && argv[1]->type == ESEXP_RES_STRING) || (argc == 3 && argv[0]->type == ESEXP_RES_STRING && argv[1]->type == ESEXP_RES_STRING && argv[2]->type == ESEXP_RES_STRING)) { gchar *propname; struct prop_info *info = NULL; const gchar *region = NULL; gint i; gboolean any_field; gboolean saw_any = FALSE; if (argc > 2) region = argv[2]->value.string; propname = argv[0]->value.string; any_field = !strcmp (propname, "x-evolution-any-field"); for (i = 0; i < G_N_ELEMENTS (prop_info_table); i++) { if (any_field || !strcmp (prop_info_table[i].query_prop, propname)) { saw_any = TRUE; info = &prop_info_table[i]; if (any_field && info->field_id == E_CONTACT_UID) { /* We need to skip UID from any field contains search * any-field search should be supported for the * visible fields only. */ truth = FALSE; } else if (info->prop_type == PROP_TYPE_NORMAL) { const gchar *prop = NULL; /* straight string property matches */ prop = e_contact_get_const (ctx->contact, info->field_id); if (prop && compare (prop, argv[1]->value.string, region)) { truth = TRUE; } if ((!prop) && compare ("", argv[1]->value.string, region)) { truth = TRUE; } } else if (info->prop_type == PROP_TYPE_LIST) { /* the special searches that match any of the list elements */ truth = info->list_compare (ctx->contact, argv[1]->value.string, region, compare); } else if (info->prop_type == PROP_TYPE_DATE) { /* the special searches that match dates */ EContactDate *date; date = e_contact_get (ctx->contact, info->field_id); if (date) { truth = compare_date (date, argv[1]->value.string, region, compare); e_contact_date_free (date); } } else { g_warn_if_reached (); saw_any = FALSE; break; } /* if we're looking at all fields and find a match, * or if we're just looking at this one field, * break. */ if ((any_field && truth) || !any_field) break; } } if (!saw_any) { /* propname didn't match to any of our known "special" properties, * so try to find if it isn't a real field and if so, then compare * against value in this field only */ EContactField fid = e_contact_field_id (propname); if (fid >= E_CONTACT_FIELD_FIRST && fid < E_CONTACT_FIELD_LAST) { const gchar *prop = e_contact_get_const (ctx->contact, fid); if (prop && compare (prop, argv[1]->value.string, region)) { truth = TRUE; } if ((!prop) && compare ("", argv[1]->value.string, region)) { truth = TRUE; } } else { /* it is not direct EContact known field, so try to find * it in EVCard attributes */ GList *a, *attrs = e_vcard_get_attributes (E_VCARD (ctx->contact)); for (a = attrs; a && !truth; a = a->next) { EVCardAttribute *attr = (EVCardAttribute *) a->data; if (g_ascii_strcasecmp (e_vcard_attribute_get_name (attr), propname) == 0) { GList *l, *values = e_vcard_attribute_get_values (attr); for (l = values; l && !truth; l = l->next) { const gchar *value = l->data; if (value && compare (value, argv[1]->value.string, region)) { truth = TRUE; } else if ((!value) && compare ("", argv[1]->value.string, region)) { truth = TRUE; } } } } } } } r = e_sexp_result_new (f, ESEXP_RES_BOOL); r->value.boolean = truth; return r; }
/* This function returns a GtkEntry derived from field_id for a particular * contact. * Returns GtkWidget * on success, NULL on failure * TODO: Lots of duplicated code here, perhaps add a few bits to utils? */ static GtkWidget * contacts_edit_widget_new (EContact *contact, EVCardAttribute *attr, gboolean multi_line, gboolean *changed) { GtkWidget *type_edit; EContactChangeData *data; const gchar *attr_name = e_vcard_attribute_get_name (attr); /* Create data structure for changes */ data = g_new0 (EContactChangeData, 1); data->contact = contact; data->attr = attr; data->changed = changed; /* Create widget */ if (!e_vcard_attribute_is_single_valued (attr)) { /* Handle structured fields */ GtkWidget *adr_table; guint field; GList *values = e_vcard_attribute_get_values (attr); adr_table = gtk_table_new (1, 2, FALSE); gtk_table_set_col_spacings (GTK_TABLE (adr_table), 6); gtk_table_set_row_spacings (GTK_TABLE (adr_table), 6); gtk_container_set_border_width (GTK_CONTAINER (adr_table), 6); /* Set widget that contains attribute data */ data->widget = adr_table; /* Add type editor */ type_edit = contacts_type_edit_widget_new (attr, multi_line, changed); if (type_edit) { GtkWidget *label = gtk_label_new (NULL); gtk_label_set_use_markup (GTK_LABEL (label), TRUE); gtk_label_set_markup (GTK_LABEL (label), /* TODO: make nicer for i18n */ _("<b>Type:</b>")); gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5); gtk_table_attach (GTK_TABLE (adr_table), label, 0, 1, 0, 1, GTK_FILL, GTK_FILL, 0, 0); gtk_table_attach (GTK_TABLE (adr_table), type_edit, 1, 2, 0, 1, GTK_FILL, GTK_FILL, 0, 0); gtk_widget_show (label); gtk_widget_show (type_edit); } /* Create sub-fields */ for (field = 0; values; values = values->next, field++) { /* If no information exists, assume field is * single-lined. * TODO: It may be more intelligent in the future * to look at the value and search for new-line * characters. */ gboolean multiline = FALSE; GtkWidget *label = NULL, *entry; const ContactsStructuredField *sfield = contacts_get_structured_field (attr_name, field); const gchar *string = (const gchar *)values->data; /* If we have the information, label the field */ if (sfield) { gchar *label_markup; if (sfield->priority == 0) continue; label = gtk_label_new (NULL); multiline = sfield->multiline; gtk_label_set_use_markup (GTK_LABEL (label), TRUE); label_markup = g_strdup_printf ( /** Translators, the first * argument is the field's * name, ex. <b>Country:</b> */ _("<b>%s:</b>"), gettext(sfield->subfield_name)); gtk_label_set_markup (GTK_LABEL (label), label_markup); g_free (label_markup); gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_RIGHT); if (!multiline) gtk_misc_set_alignment ( GTK_MISC (label), 1, 0.5); else gtk_misc_set_alignment ( GTK_MISC (label), 1, 0); gtk_table_attach (GTK_TABLE (adr_table), label, 0, 1, field + 1, field + 2, GTK_FILL, GTK_FILL, 0, 0); gtk_widget_show (label); } /* This code is pretty much a verbatim copy of the * code below to handle single-valued fields */ if (multiline) { GtkTextBuffer *buffer; GtkTextView *view; view = GTK_TEXT_VIEW (gtk_text_view_new ()); gtk_widget_set_name (GTK_WIDGET (view), attr_name); buffer = gtk_text_view_get_buffer (view); gtk_text_buffer_set_text (buffer, string ? string : "", -1); gtk_text_view_set_editable (view, TRUE); gtk_text_view_set_accepts_tab (view, FALSE); entry = gtk_frame_new (NULL); gtk_frame_set_shadow_type (GTK_FRAME (entry), GTK_SHADOW_IN); gtk_container_add (GTK_CONTAINER (entry), GTK_WIDGET (view)); gtk_widget_show (GTK_WIDGET (view)); /* Connect signal for changes */ g_signal_connect (G_OBJECT (buffer), "changed", G_CALLBACK (contacts_entry_changed), data); } else { entry = gtk_entry_new (); gtk_widget_set_name (entry, attr_name); gtk_entry_set_text (GTK_ENTRY (entry), string ? string : ""); /* Connect signal for changes */ g_signal_connect (G_OBJECT (entry), "changed", G_CALLBACK (contacts_entry_changed), data); } gtk_widget_show (entry); /* Hide the label when the entry is hidden */ g_signal_connect_swapped (G_OBJECT (entry), "hide", G_CALLBACK (gtk_widget_hide), label); gtk_table_attach (GTK_TABLE (adr_table), entry, 1, 2, field + 1, field + 2, GTK_FILL | GTK_EXPAND, GTK_FILL, 0, 0); } } else if (multi_line) { /* Handle single-valued fields that span multiple lines */ gchar *string = e_vcard_attribute_get_value (attr); GtkWidget *container = NULL; GtkTextView *view = GTK_TEXT_VIEW (gtk_text_view_new ()); GtkTextBuffer *buffer = gtk_text_view_get_buffer (view); gtk_widget_set_name (GTK_WIDGET (view), attr_name); gtk_text_buffer_set_text (buffer, string ? string : "", -1); gtk_text_view_set_editable (view, TRUE); gtk_text_view_set_accepts_tab (view, FALSE); g_free (string); container = gtk_frame_new (NULL); gtk_frame_set_shadow_type ( GTK_FRAME (container), GTK_SHADOW_IN); gtk_container_add (GTK_CONTAINER (container), GTK_WIDGET (view)); gtk_widget_show (GTK_WIDGET (view)); /* if (type_edit) { gtk_widget_show (type_edit); gtk_widget_show (window); container = gtk_hbox_new (FALSE, 6); gtk_box_pack_start (GTK_BOX (container), type_edit, FALSE, TRUE, 0); gtk_box_pack_end (GTK_BOX (container), window, TRUE, TRUE, 0); }*/ /* Set widget that contains attribute data */ data->widget = container; /* Connect signal for changes */ g_signal_connect (G_OBJECT (buffer), "changed", G_CALLBACK (contacts_entry_changed), data); } else { /* Handle simple single-valued single-line fields */ gchar *string = e_vcard_attribute_get_value (attr); GtkWidget *entry, *container = NULL; entry = gtk_entry_new (); gtk_entry_set_text (GTK_ENTRY (entry), string ? string : ""); gtk_widget_set_name (entry, attr_name); g_free (string); /* if (type_edit) { gtk_widget_show (type_edit); gtk_widget_show (entry); container = gtk_hbox_new (FALSE, 6); gtk_box_pack_start (GTK_BOX (container), type_edit, FALSE, TRUE, 0); gtk_box_pack_end (GTK_BOX (container), entry, TRUE, TRUE, 0); }*/ /* Set widget that contains attribute data */ data->widget = container ? container : entry; /* Connect signal for changes */ g_signal_connect (G_OBJECT (entry), "changed", G_CALLBACK (contacts_entry_changed), data); } /* Free change data structure on destruction */ g_signal_connect_swapped (G_OBJECT (data->widget), "destroy", G_CALLBACK (g_free), data); gtk_widget_set_name (data->widget, attr_name); return data->widget; }
/* utility functions shared between all contact importers */ static void preview_contact (EWebViewPreview *preview, EContact *contact) { gint idx; gboolean had_value = FALSE; const gint fields[] = { E_CONTACT_FILE_AS, E_CONTACT_CATEGORIES, E_CONTACT_IS_LIST, E_CONTACT_LIST_SHOW_ADDRESSES, E_CONTACT_WANTS_HTML, E_CONTACT_FULL_NAME, E_CONTACT_GIVEN_NAME, E_CONTACT_FAMILY_NAME, E_CONTACT_NICKNAME, E_CONTACT_SPOUSE, E_CONTACT_BIRTH_DATE, E_CONTACT_ANNIVERSARY, E_CONTACT_MAILER, E_CONTACT_EMAIL, -1, E_CONTACT_ORG, E_CONTACT_ORG_UNIT, E_CONTACT_OFFICE, E_CONTACT_TITLE, E_CONTACT_ROLE, E_CONTACT_MANAGER, E_CONTACT_ASSISTANT, -1, E_CONTACT_PHONE_ASSISTANT, E_CONTACT_PHONE_BUSINESS, E_CONTACT_PHONE_BUSINESS_2, E_CONTACT_PHONE_BUSINESS_FAX, E_CONTACT_PHONE_CALLBACK, E_CONTACT_PHONE_CAR, E_CONTACT_PHONE_COMPANY, E_CONTACT_PHONE_HOME, E_CONTACT_PHONE_HOME_2, E_CONTACT_PHONE_HOME_FAX, E_CONTACT_PHONE_ISDN, E_CONTACT_PHONE_MOBILE, E_CONTACT_PHONE_OTHER, E_CONTACT_PHONE_OTHER_FAX, E_CONTACT_PHONE_PAGER, E_CONTACT_PHONE_PRIMARY, E_CONTACT_PHONE_RADIO, E_CONTACT_PHONE_TELEX, E_CONTACT_PHONE_TTYTDD, -1, E_CONTACT_ADDRESS_HOME, E_CONTACT_ADDRESS_WORK, E_CONTACT_ADDRESS_OTHER, -1, E_CONTACT_HOMEPAGE_URL, E_CONTACT_BLOG_URL, E_CONTACT_CALENDAR_URI, E_CONTACT_FREEBUSY_URL, E_CONTACT_ICS_CALENDAR, E_CONTACT_VIDEO_URL, -1, E_CONTACT_IM_AIM, E_CONTACT_IM_GROUPWISE, E_CONTACT_IM_JABBER, E_CONTACT_IM_YAHOO, E_CONTACT_IM_MSN, E_CONTACT_IM_ICQ, E_CONTACT_IM_GADUGADU, E_CONTACT_IM_SKYPE, -1, E_CONTACT_NOTE }; g_return_if_fail (preview != NULL); g_return_if_fail (contact != NULL); for (idx = 0; idx < G_N_ELEMENTS (fields); idx++) { EContactField field; if (fields[idx] == -1) { if (had_value) e_web_view_preview_add_empty_line (preview); had_value = FALSE; continue; } field = fields[idx]; if (field == E_CONTACT_BIRTH_DATE || field == E_CONTACT_ANNIVERSARY) { EContactDate *dt = e_contact_get (contact, field); if (dt) { GDate gd = { 0 }; struct tm tm; gchar *value; g_date_set_dmy (&gd, dt->day, dt->month, dt->year); g_date_to_struct_tm (&gd, &tm); value = e_datetime_format_format_tm ( "addressbook", "table", DTFormatKindDate, &tm); if (value) { e_web_view_preview_add_section ( preview, e_contact_pretty_name (field), value); had_value = TRUE; } g_free (value); e_contact_date_free (dt); } } else if (field == E_CONTACT_IS_LIST || field == E_CONTACT_WANTS_HTML || field == E_CONTACT_LIST_SHOW_ADDRESSES) { if (e_contact_get (contact, field)) { e_web_view_preview_add_text ( preview, e_contact_pretty_name (field)); had_value = TRUE; } } else if (field == E_CONTACT_ADDRESS_HOME || field == E_CONTACT_ADDRESS_WORK || field == E_CONTACT_ADDRESS_OTHER) { EContactAddress *addr = e_contact_get (contact, field); if (addr) { gboolean have = FALSE; #define add_it(_what) \ if (addr->_what && *addr->_what) { \ e_web_view_preview_add_section ( \ preview, have ? NULL : \ e_contact_pretty_name (field), addr->_what); \ have = TRUE; \ had_value = TRUE; \ } add_it (po); add_it (ext); add_it (street); add_it (locality); add_it (region); add_it (code); add_it (country); #undef add_it e_contact_address_free (addr); } } else if (field == E_CONTACT_IM_AIM || field == E_CONTACT_IM_GROUPWISE || field == E_CONTACT_IM_JABBER || field == E_CONTACT_IM_YAHOO || field == E_CONTACT_IM_MSN || field == E_CONTACT_IM_ICQ || field == E_CONTACT_IM_GADUGADU || field == E_CONTACT_IM_SKYPE || field == E_CONTACT_EMAIL) { GList *attrs, *a; gboolean have = FALSE; const gchar *pretty_name; pretty_name = e_contact_pretty_name (field); attrs = e_contact_get_attributes (contact, field); for (a = attrs; a; a = a->next) { EVCardAttribute *attr = a->data; GList *value; if (!attr) continue; value = e_vcard_attribute_get_values (attr); while (value != NULL) { const gchar *str = value->data; if (str && *str) { e_web_view_preview_add_section ( preview, have ? NULL : pretty_name, str); have = TRUE; had_value = TRUE; } value = value->next; } e_vcard_attribute_free (attr); } g_list_free (attrs); } else if (field == E_CONTACT_CATEGORIES) { const gchar *pretty_name; const gchar *value; pretty_name = e_contact_pretty_name (field); value = e_contact_get_const (contact, field); if (value != NULL && *value != '\0') { e_web_view_preview_add_section ( preview, pretty_name, value); had_value = TRUE; } } else { const gchar *pretty_name; const gchar *value; pretty_name = e_contact_pretty_name (field); value = e_contact_get_const (contact, field); if (value != NULL && *value != '\0') { e_web_view_preview_add_section ( preview, pretty_name, value); had_value = TRUE; } } } }
static void vcard_import_contact (VCardImporter *gci, EContact *contact) { EContactPhoto *photo; GList *attrs, *attr; gchar *uid = NULL; /* Apple's addressbook.app exports PHOTO's without a TYPE * param, so let's figure out the format here if there's a * PHOTO attribute missing a TYPE param. * * this is sort of a hack, as EContact sets the type for us if * we use the setter. so let's e_contact_get + e_contact_set * on E_CONTACT_PHOTO. */ photo = e_contact_get (contact, E_CONTACT_PHOTO); if (photo) { e_contact_set (contact, E_CONTACT_PHOTO, photo); e_contact_photo_free (photo); } /* Deal with our XML EDestination stuff in EMAIL attributes, if there is any. */ attrs = e_contact_get_attributes (contact, E_CONTACT_EMAIL); for (attr = attrs; attr; attr = attr->next) { EVCardAttribute *a = attr->data; GList *v = e_vcard_attribute_get_values (a); if (v && v->data) { if (!strncmp ((gchar *)v->data, "<?xml", 5)) { EDestination *dest = e_destination_import ((gchar *) v->data); e_destination_export_to_vcard_attribute (dest, a); g_object_unref (dest); } } } e_contact_set_attributes (contact, E_CONTACT_EMAIL, attrs); /* Deal with TEL attributes that don't conform to what we need. * * 1. if there's no location (HOME/WORK/OTHER), default to OTHER. * 2. if there's *only* a location specified, default to VOICE. */ attrs = e_vcard_get_attributes (E_VCARD (contact)); for (attr = attrs; attr; attr = attr->next) { EVCardAttribute *a = attr->data; gboolean location_only = TRUE; gboolean no_location = TRUE; gboolean is_work_home = FALSE; GList *params, *param; if (g_ascii_strcasecmp (e_vcard_attribute_get_name (a), EVC_TEL)) continue; params = e_vcard_attribute_get_params (a); for (param = params; param; param = param->next) { EVCardAttributeParam *p = param->data; GList *vs, *v; if (g_ascii_strcasecmp (e_vcard_attribute_param_get_name (p), EVC_TYPE)) continue; vs = e_vcard_attribute_param_get_values (p); for (v = vs; v; v = v->next) { is_work_home = is_work_home || !g_ascii_strcasecmp ((gchar *)v->data, "WORK") || !g_ascii_strcasecmp ((gchar *)v->data, "HOME"); if (!g_ascii_strcasecmp ((gchar *)v->data, "WORK") || !g_ascii_strcasecmp ((gchar *)v->data, "HOME") || !g_ascii_strcasecmp ((gchar *)v->data, "OTHER")) no_location = FALSE; else location_only = FALSE; } } if (is_work_home) { /* only WORK and HOME phone numbers require locations, * the rest should be kept as is */ if (location_only) { /* add VOICE */ e_vcard_attribute_add_param_with_value (a, e_vcard_attribute_param_new (EVC_TYPE), "VOICE"); } if (no_location) { /* add OTHER */ e_vcard_attribute_add_param_with_value (a, e_vcard_attribute_param_new (EVC_TYPE), "OTHER"); } } } /* Deal with ADR and EMAIL attributes that don't conform to what * we need. If HOME or WORK isn't specified, add TYPE=OTHER. */ attrs = e_vcard_get_attributes (E_VCARD (contact)); for (attr = attrs; attr; attr = attr->next) { EVCardAttribute *a = attr->data; gboolean no_location = TRUE; GList *params, *param; if (g_ascii_strcasecmp (e_vcard_attribute_get_name (a), EVC_ADR) && g_ascii_strcasecmp (e_vcard_attribute_get_name (a), EVC_EMAIL)) continue; params = e_vcard_attribute_get_params (a); for (param = params; param; param = param->next) { EVCardAttributeParam *p = param->data; GList *vs, *v; if (g_ascii_strcasecmp (e_vcard_attribute_param_get_name (p), EVC_TYPE)) continue; vs = e_vcard_attribute_param_get_values (p); for (v = vs; v; v = v->next) { if (!g_ascii_strcasecmp ((gchar *)v->data, "WORK") || !g_ascii_strcasecmp ((gchar *)v->data, "HOME")) no_location = FALSE; } } if (no_location) { /* add OTHER */ e_vcard_attribute_add_param_with_value (a, e_vcard_attribute_param_new (EVC_TYPE), "OTHER"); } } /* Work around the fact that these fields no longer show up in the UI */ add_to_notes (contact, E_CONTACT_OFFICE); add_to_notes (contact, E_CONTACT_SPOUSE); add_to_notes (contact, E_CONTACT_BLOG_URL); /* FIXME Error checking */ if (e_book_client_add_contact_sync (gci->book_client, contact, &uid, NULL, NULL) && uid) { e_contact_set (contact, E_CONTACT_UID, uid); g_free (uid); } }