/** * e_vcard_attribute_has_type: * @attr: an #EVCardAttribute * @typestr: a string representing the type * * Checks if @attr has an #EVCardAttributeParam of the specified type. * * Return value: %TRUE if such a parameter exists, %FALSE otherwise. **/ gboolean e_vcard_attribute_has_type (EVCardAttribute *attr, const char *typestr) { GList *params; GList *p; g_return_val_if_fail (attr != NULL, FALSE); g_return_val_if_fail (typestr != NULL, FALSE); params = e_vcard_attribute_get_params (attr); for (p = params; p; p = p->next) { EVCardAttributeParam *param = p->data; if (!g_ascii_strcasecmp (e_vcard_attribute_param_get_name (param), EVC_TYPE)) { GList *values = e_vcard_attribute_param_get_values (param); GList *v; for (v = values; v; v = v->next) { if (!g_ascii_strcasecmp ((char*)v->data, typestr)) return TRUE; } } } return FALSE; }
/** * e_vcard_attribute_remove_param_value: * @attr: an #EVCardAttribute * @param_name: a parameter name * @s: a value * * Removes the value @s from the parameter @param_name on the attribute @attr. **/ void e_vcard_attribute_remove_param_value (EVCardAttribute *attr, const char *param_name, const char *s) { GList *l, *params; EVCardAttributeParam *param; g_return_if_fail (attr != NULL); g_return_if_fail (param_name != NULL); g_return_if_fail (s != NULL); params = e_vcard_attribute_get_params (attr); for (l = params; l; l = l->next) { param = l->data; if (g_ascii_strcasecmp (e_vcard_attribute_param_get_name (param), param_name) == 0) { l = g_list_find_custom (param->values, s, (GCompareFunc)strcmp); if (l == NULL) { return; } param->values = g_list_delete_link (param->values, l); if (param->values == NULL) { e_vcard_attribute_param_free (param); attr->params = g_list_remove (attr->params, param); } break; } } return; }
/* * Convenience function to set the type parmeter of a vcard attribute * * attr: the attribute to modify * type: semicolan seperated list of values * */ void hito_vcard_attribute_set_type (EVCardAttribute *attr, const gchar *type) { GList *params; EVCardAttributeParam *p = NULL; gchar **values; gint i; /* look for the TYPE parameter */ for (params = e_vcard_attribute_get_params (attr); params; params = g_list_next (params)) { if (!strcmp (e_vcard_attribute_param_get_name (params->data), "TYPE")) { p = params->data; break; } } /* we didn't find the TYPE parameter, so create it now */ if (!p) { /* if there isn't an existing TYPE and we are not setting a value, we can * return straight away */ if (!type) return; p = e_vcard_attribute_param_new ("TYPE"); e_vcard_attribute_add_param (attr, p); } /* remove the current values */ e_vcard_attribute_param_remove_values (p); /* if type is null, we don't want to add any type parameters */ if (!type) return; values = g_strsplit (type, ";", -1); for (i = 0; (values[i]); i++) { e_vcard_attribute_param_add_value (p, values[i]); } g_strfreev (values); }
/** * e_vcard_attribute_get_param: * @attr: an #EVCardAttribute * @name: a parameter name * * Gets the list of values for the paramater @name from @attr. The list and its * contents are owned by @attr, and must not be freed. * * Return value: A list of string elements representing the parameter's values. **/ GList * e_vcard_attribute_get_param (EVCardAttribute *attr, const char *name) { GList *params, *p; g_return_val_if_fail (attr != NULL, NULL); g_return_val_if_fail (name != NULL, NULL); params = e_vcard_attribute_get_params (attr); for (p = params; p; p = p->next) { EVCardAttributeParam *param = p->data; if (g_ascii_strcasecmp (e_vcard_attribute_param_get_name (param), name) == 0) { return e_vcard_attribute_param_get_values (param); } } return NULL; }
static GtkWidget * contacts_type_edit_widget_new (EVCardAttribute *attr, gboolean multi_line, gboolean *changed) { const TypeTuple *types; types = contacts_get_field_types (e_vcard_attribute_get_name (attr)); if (types) { guint i; GtkWidget *combo = gtk_combo_box_entry_new_text (); GtkWidget *align; gchar *first_type = ""; EVCardAttributeParam *param; EContactTypeChangeData *data; /* Retrieve all types, but we only look at the first one * TODO: A sane way of selecting multiple types, to conform * with spec? (Almost no other vCard-using apps do this, * so not high priority) */ GList *contact_types = contacts_get_types ( e_vcard_attribute_get_params (attr)); if (contact_types) { param = (EVCardAttributeParam *)contact_types->data; GList *values = e_vcard_attribute_param_get_values (param); first_type = values ? (gchar *)values->data : ""; g_list_free (contact_types); } else { param = e_vcard_attribute_param_new ("TYPE"); e_vcard_attribute_add_param_with_value ( attr, param, ""); } data = g_new (EContactTypeChangeData, 1); data->param = param; data->attr_name = e_vcard_attribute_get_name (attr); data->changed = changed; for (i = 0; types[i].index; i++) { gtk_combo_box_append_text ( GTK_COMBO_BOX (combo), _(types[i].value)); /* Note: We use a case-insensitive search here, as * specified in the spec (as the types are predefined, * we can use non-locale-friendly strcasecmp) */ if (first_type) { if (g_ascii_strcasecmp (types[i].index, first_type) == 0) { first_type = NULL; gtk_combo_box_set_active ( GTK_COMBO_BOX (combo), i); } } } /* Support custom types, as per spec */ if ((first_type) && (g_ascii_strncasecmp (first_type, "X-", 2) == 0)) { gtk_entry_set_text ( GTK_ENTRY (GTK_BIN (combo)->child), (const gchar *)(first_type+2)); first_type = NULL; } if (first_type) gtk_combo_box_set_active (GTK_COMBO_BOX (combo), i-1); gtk_widget_show (combo); if (/*(e_vcard_attribute_is_single_valued (attr)) &&*/ (multi_line == FALSE)) align = gtk_alignment_new (0, 0.5, 0, 0); else align = gtk_alignment_new (0, 0, 0, 0); /* TODO: Find something better than this? */ gtk_widget_set_size_request (combo, 80, -1); gtk_container_add (GTK_CONTAINER (align), combo); /* Connect signal for changes */ g_signal_connect (G_OBJECT (combo), "changed", G_CALLBACK (contacts_type_entry_changed), data); /* Free change data structure on destruction */ g_signal_connect_swapped (G_OBJECT (align), "destroy", G_CALLBACK (g_free), data); return align; } return NULL; }
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); } }
static const gchar * get_phone_location (EVCardAttribute *attr) { struct _locations { EContactField field_id; const gchar *attr_type; } locations[] = { { E_CONTACT_PHONE_ASSISTANT, EVC_X_ASSISTANT }, { E_CONTACT_PHONE_CALLBACK, EVC_X_CALLBACK }, { E_CONTACT_PHONE_CAR, "CAR" }, { E_CONTACT_PHONE_COMPANY, EVC_X_COMPANY }, { E_CONTACT_PHONE_ISDN, "ISDN" }, { E_CONTACT_PHONE_MOBILE, "CELL" }, { E_CONTACT_PHONE_OTHER_FAX, "FAX" }, { E_CONTACT_PHONE_PAGER, "PAGER" }, { E_CONTACT_PHONE_PRIMARY, "PREF" }, { E_CONTACT_PHONE_RADIO, EVC_X_RADIO }, { E_CONTACT_PHONE_TELEX, EVC_X_TELEX }, { E_CONTACT_PHONE_TTYTDD, EVC_X_TTYTDD } }; GList *params, *plink; GList *values = NULL, *vlink; gboolean done = FALSE; const gchar *location = NULL; gint ii; params = e_vcard_attribute_get_params (attr); for (plink = params; plink; plink = g_list_next (plink)) { EVCardAttributeParam *param = plink->data; if (!g_ascii_strcasecmp (e_vcard_attribute_param_get_name (param), EVC_TYPE)) { values = e_vcard_attribute_param_get_values (param); break; } } for (vlink = values; vlink && !done; vlink = g_list_next (vlink)) { const gchar *value = vlink->data; if (!value) continue; for (ii = 0; ii < G_N_ELEMENTS (locations); ii++) { if (!g_ascii_strcasecmp (value, locations[ii].attr_type)) { if (location) { /* if more than one is set, then fallback to the "Other Phone" */ location = NULL; done = TRUE; break; } location = e_contact_pretty_name (locations[ii].field_id); } } } if (!location) location = e_contact_pretty_name (E_CONTACT_PHONE_OTHER); if (!location) location = _("Phone"); return location; }