diff options
-rw-r--r-- | addressbook/gui/contact-editor/contact-editor.ui | 78 | ||||
-rw-r--r-- | addressbook/gui/contact-editor/e-contact-editor-dyntable.c | 4 | ||||
-rw-r--r-- | addressbook/gui/contact-editor/e-contact-editor.c | 314 | ||||
-rw-r--r-- | addressbook/gui/widgets/eab-contact-formatter.c | 206 | ||||
-rw-r--r-- | e-util/e-html-utils.c | 40 | ||||
-rw-r--r-- | e-util/e-html-utils.h | 3 |
6 files changed, 611 insertions, 34 deletions
diff --git a/addressbook/gui/contact-editor/contact-editor.ui b/addressbook/gui/contact-editor/contact-editor.ui index af2d41a84a..0c6edc838c 100644 --- a/addressbook/gui/contact-editor/contact-editor.ui +++ b/addressbook/gui/contact-editor/contact-editor.ui @@ -598,6 +598,82 @@ </packing> </child> <child> + <object class="GtkFrame" id="sip-frame"> + <property name="visible">True</property> + <property name="label_xalign">0</property> + <property name="shadow_type">none</property> + + <child> + <object class="GtkVBox" id="vbox-sip"> + <property name="visible">True</property> + <property name="border_width">12</property> + <property name="orientation">vertical</property> + <property name="spacing">6</property> + + <child> + <object class="EContactEditorDynTable" type-func="e_contact_editor_dyntable_get_type" id="sip-dyntable"> + <property name="visible">True</property> + </object> + <packing> + <property name="position">0</property> + </packing> + </child> + + </object> + </child> + + <child type="label"> + <object class="GtkHBox" id="hbox-sip"> + <property name="visible">True</property> + <property name="spacing">4</property> + <child> + <object class="GtkLabel" id="label-sip"> + <property name="visible">True</property> + <property name="label" translatable="yes">SIP Address</property> + <attributes> + <attribute name="weight" value="bold"/> + </attributes> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkButton" id="button-sip-expand"> + <property name="width_request">20</property> + <property name="height_request">20</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="relief">none</property> + <child internal-child="accessible"> + <object class="AtkObject" id="button-sip-expand-atkobject"> + <property name="AtkObject::accessible-name" translatable="yes">SIP Address</property> + </object> + </child> + <child> + <object class="GtkArrow" id="arrow-sip-expand"> + <property name="visible">True</property> + <property name="shadow_type">none</property> + </object> + </child> + </object> + <packing> + <property name="position">1</property> + </packing> + </child> + </object> + </child> + + </object> + <packing> + <property name="expand">False</property> + <property name="position">2</property> + </packing> + </child> + <child> <object class="GtkFrame" id="frame66"> <property name="visible">True</property> <property name="label_xalign">0</property> @@ -670,7 +746,7 @@ </object> <packing> <property name="expand">False</property> - <property name="position">2</property> + <property name="position">3</property> </packing> </child> </object> diff --git a/addressbook/gui/contact-editor/e-contact-editor-dyntable.c b/addressbook/gui/contact-editor/e-contact-editor-dyntable.c index 4706d5b1f9..eb702720bf 100644 --- a/addressbook/gui/contact-editor/e-contact-editor-dyntable.c +++ b/addressbook/gui/contact-editor/e-contact-editor-dyntable.c @@ -492,7 +492,9 @@ e_contact_editor_dyntable_fill_in_data (EContactEditorDynTable *dyntable) w = gtk_grid_get_child_at (grid, col + 1, row); class->widget_fill (dyntable, w, str_data); - g_return_if_fail(pos < dyntable->priv->max_entries); + if (pos >= dyntable->priv->max_entries) + break; + valid = gtk_tree_model_iter_next (store, &iter); } diff --git a/addressbook/gui/contact-editor/e-contact-editor.c b/addressbook/gui/contact-editor/e-contact-editor.c index 07cfa01c41..6751a002ba 100644 --- a/addressbook/gui/contact-editor/e-contact-editor.c +++ b/addressbook/gui/contact-editor/e-contact-editor.c @@ -50,6 +50,7 @@ #define SLOTS_IN_COLLAPSED_STATE SLOTS_PER_LINE #define EMAIL_SLOTS 4 #define PHONE_SLOTS 50 +#define SIP_SLOTS 4 #define IM_SLOTS 50 #define ADDRESS_SLOTS 3 @@ -123,8 +124,7 @@ static struct { EContactField field_id; const gchar *type_1; const gchar *type_2; -} -phones[] = { +} phones[] = { { E_CONTACT_PHONE_ASSISTANT, EVC_X_ASSISTANT, NULL }, { E_CONTACT_PHONE_BUSINESS, "WORK", "VOICE" }, { E_CONTACT_PHONE_BUSINESS_FAX, "WORK", "FAX" }, @@ -212,6 +212,7 @@ common_location[] = /* Default from the table above */ static const gint email_default[] = { 0, 1, 2, 2 }; +static const gint sips_default[] = { 0, 1, 2, 2 }; #define STRING_IS_EMPTY(x) (!(x) || !(*(x))) #define STRING_MAKE_NON_NULL(x) ((x) ? (x) : "") @@ -1017,6 +1018,13 @@ phone_index_to_type (gint index, *type_2 = phones [index].type_2; } +static void +sip_index_to_type (gint index, + const gchar **type_1) +{ + *type_1 = common_location[index].name; +} + static gint get_email_location (EVCardAttribute *attr) { @@ -1037,14 +1045,26 @@ get_phone_type (EVCardAttribute *attr) for (i = 0; i < G_N_ELEMENTS (phones); i++) { if (e_vcard_attribute_has_type (attr, phones[i].type_1) && - (phones[i].type_2 == NULL || - e_vcard_attribute_has_type (attr, phones[i].type_2))) + (phones[i].type_2 == NULL || e_vcard_attribute_has_type (attr, phones[i].type_2))) return i; } return -1; } +static gint +get_sip_type (EVCardAttribute *attr) +{ + gint ii; + + for (ii = 0; ii < G_N_ELEMENTS (common_location); ii++) { + if (e_vcard_attribute_has_type (attr, common_location[ii].name)) + return ii; + } + + return -1; +} + static EVCardAttributeParam * get_ui_slot_param (EVCardAttribute *attr) { @@ -1368,6 +1388,24 @@ expand_phone (EContactEditor *editor, } static void +expand_sip (EContactEditor *editor, + gboolean expanded) +{ + GtkWidget *w; + EContactEditorDynTable *dyntable; + + set_arrow_image (editor, "arrow-sip-expand", expanded); + + w = e_builder_get_widget (editor->priv->builder, "sip-dyntable"); + dyntable = E_CONTACT_EDITOR_DYNTABLE (w); + + if (expanded) + e_contact_editor_dyntable_set_show_max (dyntable, SIP_SLOTS); + else + e_contact_editor_dyntable_set_show_max (dyntable, SLOTS_IN_COLLAPSED_STATE); +} + +static void expand_im (EContactEditor *editor, gboolean expanded) { @@ -1431,7 +1469,7 @@ init_email (EContactEditor *editor) static void fill_in_phone (EContactEditor *editor) { - GList *phone_attr_list; + GList *tel_attr_list; GList *l; GtkWidget *w; EContactEditorDynTable *dyntable; @@ -1447,14 +1485,15 @@ fill_in_phone (EContactEditor *editor) /* Fill in */ - phone_attr_list = e_contact_get_attributes (editor->priv->contact, E_CONTACT_TEL); + tel_attr_list = e_contact_get_attributes (editor->priv->contact, E_CONTACT_TEL); + data_store = e_contact_editor_dyntable_extract_data (dyntable); - for (l = phone_attr_list;l ; l = g_list_next (l)) { + for (l = tel_attr_list; l; l = g_list_next (l)) { EVCardAttribute *attr = l->data; - gchar *phone; - gint slot; - gint phone_type; + gchar *phone; + gint slot; + gint phone_type; slot = get_ui_slot (attr); phone_type = get_phone_type (attr); @@ -1471,7 +1510,7 @@ fill_in_phone (EContactEditor *editor) } e_contact_editor_dyntable_fill_in_data (dyntable); - g_list_free_full (phone_attr_list, (GDestroyNotify) e_vcard_attribute_free); + g_list_free_full (tel_attr_list, (GDestroyNotify) e_vcard_attribute_free); expand_phone (editor, TRUE); } @@ -1479,10 +1518,10 @@ fill_in_phone (EContactEditor *editor) static void extract_phone (EContactEditor *editor) { - GList *attr_list = NULL; + GList *tel_attr_list = NULL; GList *old_attr_list; GList *ll; - gint i; + gint i; GtkWidget *w; EContactEditorDynTable *dyntable; GtkListStore *data_store; @@ -1496,17 +1535,17 @@ extract_phone (EContactEditor *editor) tree_model = GTK_TREE_MODEL (data_store); valid = gtk_tree_model_get_iter_first (tree_model, &iter); - while (valid){ + while (valid) { gint phone_type; gchar *phone; EVCardAttribute *attr; - attr = e_vcard_attribute_new ("", "TEL"); gtk_tree_model_get (tree_model,&iter, DYNTABLE_STORE_COLUMN_SELECTED_ITEM, &phone_type, DYNTABLE_STORE_COLUMN_ENTRY_STRING, &phone, -1); + attr = e_vcard_attribute_new ("", EVC_TEL); if (phone_type >= 0) { const gchar *type_1; const gchar *type_2; @@ -1523,14 +1562,14 @@ extract_phone (EContactEditor *editor) e_vcard_attribute_add_value (attr, phone); - attr_list = g_list_prepend (attr_list, attr); + tel_attr_list = g_list_prepend (tel_attr_list, attr); valid = gtk_tree_model_iter_next (tree_model, &iter); } - attr_list = g_list_reverse (attr_list); /* Splice in the old attributes, minus the PHONE_SLOTS first */ + tel_attr_list = g_list_reverse (tel_attr_list); old_attr_list = e_contact_get_attributes (editor->priv->contact, E_CONTACT_TEL); for (ll = old_attr_list, i = 1; ll && i <= PHONE_SLOTS; i++) { e_vcard_attribute_free (ll->data); @@ -1538,11 +1577,11 @@ extract_phone (EContactEditor *editor) } old_attr_list = ll; - attr_list = g_list_concat (attr_list, old_attr_list); + tel_attr_list = g_list_concat (tel_attr_list, old_attr_list); - e_contact_set_attributes (editor->priv->contact, E_CONTACT_TEL, attr_list); + e_contact_set_attributes (editor->priv->contact, E_CONTACT_TEL, tel_attr_list); - g_list_free_full (attr_list, (GDestroyNotify) e_vcard_attribute_free); + g_list_free_full (tel_attr_list, (GDestroyNotify) e_vcard_attribute_free); } static void @@ -1650,6 +1689,226 @@ sensitize_phone (EContactEditor *editor) } static void +fill_in_sip (EContactEditor *editor) +{ + GList *sip_attr_list; + GList *l; + GtkWidget *w; + EContactEditorDynTable *dyntable; + GtkListStore *data_store; + GtkTreeIter iter; + + w = e_builder_get_widget (editor->priv->builder, "sip-dyntable"); + dyntable = E_CONTACT_EDITOR_DYNTABLE (w); + + /* Clear */ + + e_contact_editor_dyntable_clear_data (dyntable); + + /* Fill in */ + + sip_attr_list = e_contact_get_attributes (editor->priv->contact, E_CONTACT_SIP); + + data_store = e_contact_editor_dyntable_extract_data (dyntable); + + for (l = sip_attr_list; l; l = g_list_next (l)) { + EVCardAttribute *attr = l->data; + gchar *sip; + gint sip_type; + + sip_type = get_sip_type (attr); + sip = e_vcard_attribute_get_value (attr); + + if (sip_type < 0) + sip_type = 2; + + gtk_list_store_append (data_store, &iter); + gtk_list_store_set (data_store,&iter, + DYNTABLE_STORE_COLUMN_SORTORDER, -1, + DYNTABLE_STORE_COLUMN_SELECTED_ITEM, sip_type, + DYNTABLE_STORE_COLUMN_ENTRY_STRING, sip, + -1); + + g_free (sip); + } + + e_contact_editor_dyntable_fill_in_data (dyntable); + g_list_free_full (sip_attr_list, (GDestroyNotify) e_vcard_attribute_free); + + expand_sip (editor, TRUE); +} + +static void +extract_sip (EContactEditor *editor) +{ + GList *sip_attr_list = NULL; + GList *old_attr_list; + GList *ll; + gint i; + GtkWidget *w; + EContactEditorDynTable *dyntable; + GtkListStore *data_store; + GtkTreeModel *tree_model; + GtkTreeIter iter; + gboolean valid; + + w = e_builder_get_widget (editor->priv->builder, "sip-dyntable"); + dyntable = E_CONTACT_EDITOR_DYNTABLE (w); + data_store = e_contact_editor_dyntable_extract_data (dyntable); + tree_model = GTK_TREE_MODEL (data_store); + + valid = gtk_tree_model_get_iter_first (tree_model, &iter); + while (valid) { + gint sip_type; + gchar *sip; + EVCardAttribute *attr; + + gtk_tree_model_get (tree_model,&iter, + DYNTABLE_STORE_COLUMN_SELECTED_ITEM, &sip_type, + DYNTABLE_STORE_COLUMN_ENTRY_STRING, &sip, + -1); + + attr = e_vcard_attribute_new ("", EVC_X_SIP); + if (sip_type >= 0) { + const gchar *type_1; + + sip_index_to_type (sip_type, &type_1); + + e_vcard_attribute_add_param_with_value ( + attr, e_vcard_attribute_param_new (EVC_TYPE), type_1); + } + + e_vcard_attribute_add_value (attr, sip); + + sip_attr_list = g_list_prepend (sip_attr_list, attr); + + valid = gtk_tree_model_iter_next (tree_model, &iter); + } + + /* Splice in the old attributes, minus the SIP_SLOTS first */ + + sip_attr_list = g_list_reverse (sip_attr_list); + old_attr_list = e_contact_get_attributes (editor->priv->contact, E_CONTACT_SIP); + for (ll = old_attr_list, i = 1; ll && i <= SIP_SLOTS; i++) { + e_vcard_attribute_free (ll->data); + ll = g_list_delete_link (ll, ll); + } + + old_attr_list = ll; + sip_attr_list = g_list_concat (sip_attr_list, old_attr_list); + + e_contact_set_attributes (editor->priv->contact, E_CONTACT_SIP, sip_attr_list); + + g_list_free_full (sip_attr_list, (GDestroyNotify) e_vcard_attribute_free); +} + +static void +init_sip_record_type (EContactEditor *editor) +{ + GtkWidget *w; + GtkListStore *store; + gint i; + EContactEditorDynTable *dyntable; + + w = e_builder_get_widget (editor->priv->builder, "sip-dyntable"); + dyntable = E_CONTACT_EDITOR_DYNTABLE (w); + store = e_contact_editor_dyntable_get_combo_store (dyntable); + + for (i = 0; i < G_N_ELEMENTS (common_location); i++) { + GtkTreeIter iter; + + gtk_list_store_append (store, &iter); + gtk_list_store_set (store, &iter, + DYNTABLE_COMBO_COLUMN_TEXT, _(common_location[i].pretty_name), + DYNTABLE_COMBO_COLUMN_SENSITIVE, TRUE, + -1); + } + + e_contact_editor_dyntable_set_combo_defaults (dyntable, sips_default, G_N_ELEMENTS (sips_default)); +} + +static void +row_added_sip (EContactEditorDynTable *dyntable, + EContactEditor *editor) +{ + expand_sip (editor, TRUE); +} + +static void +init_sip (EContactEditor *editor) +{ + GtkWidget *w; + EContactEditorDynTable *dyntable; + + w = e_builder_get_widget (editor->priv->builder, "sip-dyntable"); + dyntable = E_CONTACT_EDITOR_DYNTABLE (w); + + e_contact_editor_dyntable_set_max_entries (dyntable, SIP_SLOTS); + e_contact_editor_dyntable_set_num_columns (dyntable, SLOTS_PER_LINE, TRUE); + e_contact_editor_dyntable_set_show_min (dyntable, SLOTS_PER_LINE); + + g_signal_connect ( + w, "changed", + G_CALLBACK (object_changed), editor); + g_signal_connect_swapped ( + w, "activate", + G_CALLBACK (entry_activated), editor); + g_signal_connect ( + w, "row-added", + G_CALLBACK (row_added_sip), editor); + + init_sip_record_type (editor); +} + +static void +sensitize_sip_types (EContactEditor *editor) +{ + GtkWidget *w; + GtkListStore *listStore; + GtkTreeModel *model; + GtkTreeIter iter; + gint i; + gboolean valid; + + w = e_builder_get_widget (editor->priv->builder, "sip-dyntable"); + listStore = e_contact_editor_dyntable_get_combo_store (E_CONTACT_EDITOR_DYNTABLE (w)); + model = GTK_TREE_MODEL (listStore); + + valid = gtk_tree_model_get_iter_first (model, &iter); + + for (i = 0; i < G_N_ELEMENTS (common_location); i++) { + if (!valid) { + g_warning (G_STRLOC ": Unexpected end of sip items in combo box"); + return; + } + + gtk_list_store_set (GTK_LIST_STORE (model), &iter, + DYNTABLE_COMBO_COLUMN_SENSITIVE, + is_field_supported (editor, E_CONTACT_SIP), + -1); + + valid = gtk_tree_model_iter_next (model, &iter); + } +} + +static void +sensitize_sip (EContactEditor *editor) +{ + GtkWidget *w; + gboolean enabled = TRUE; + + w = e_builder_get_widget (editor->priv->builder, "sip-dyntable"); + + if (!editor->priv->target_editable || + !is_field_supported (editor, E_CONTACT_SIP)) + enabled = FALSE; + + gtk_widget_set_sensitive (w, enabled); + + sensitize_sip_types (editor); +} + +static void row_added_im (EContactEditorDynTable *dyntable, EContactEditor *editor) { expand_im (editor, TRUE); @@ -2906,6 +3165,7 @@ fill_in_all (EContactEditor *editor) fill_in_simple (editor); fill_in_email (editor); fill_in_phone (editor); + fill_in_sip (editor); fill_in_im (editor); fill_in_address (editor); } @@ -2916,6 +3176,7 @@ extract_all (EContactEditor *editor) extract_simple (editor); extract_email (editor); extract_phone (editor); + extract_sip (editor); extract_im (editor); extract_address (editor); } @@ -2927,6 +3188,7 @@ sensitize_all (EContactEditor *editor) sensitize_simple (editor); sensitize_email (editor); sensitize_phone (editor); + sensitize_sip (editor); sensitize_im (editor); sensitize_address (editor); } @@ -2942,6 +3204,7 @@ init_all (EContactEditor *editor) init_simple (editor); init_email (editor); init_phone (editor); + init_sip (editor); init_im (editor); init_personal (editor); init_address (editor); @@ -3969,6 +4232,12 @@ expand_phone_toggle (EContactEditor *ce) } static void +expand_sip_toggle (EContactEditor *ce) +{ + expand_sip (ce, !is_arrow_image_arrow_down (ce, "arrow-sip-expand")); +} + +static void expand_im_toggle (EContactEditor *ce) { expand_im (ce, !is_arrow_image_arrow_down (ce, "arrow-im-expand")); @@ -4100,6 +4369,11 @@ e_contact_editor_init (EContactEditor *e_contact_editor) widget, "clicked", G_CALLBACK (expand_phone_toggle), e_contact_editor); widget = e_builder_get_widget ( + e_contact_editor->priv->builder, "button-sip-expand"); + g_signal_connect_swapped ( + widget, "clicked", + G_CALLBACK (expand_sip_toggle), e_contact_editor); + widget = e_builder_get_widget ( e_contact_editor->priv->builder, "button-im-expand"); g_signal_connect_swapped ( widget, "clicked", diff --git a/addressbook/gui/widgets/eab-contact-formatter.c b/addressbook/gui/widgets/eab-contact-formatter.c index f4b24a21bc..5935145cdc 100644 --- a/addressbook/gui/widgets/eab-contact-formatter.c +++ b/addressbook/gui/widgets/eab-contact-formatter.c @@ -64,6 +64,8 @@ struct _EABContactFormatterPrivate { EABContactDisplayMode mode; gboolean render_maps; + gboolean supports_callto; + gboolean supports_sip; }; enum { @@ -86,6 +88,9 @@ G_DEFINE_TYPE ( eab_contact_formatter, G_TYPE_OBJECT); +#define E_CREATE_CALLTO_URL (E_TEXT_TO_HTML_LAST_FLAG << 0) +#define E_CREATE_SIP_URL (E_TEXT_TO_HTML_LAST_FLAG << 1) + static gboolean icon_available (const gchar *icon) { @@ -285,6 +290,31 @@ render_table_row (GString *buffer, g_free (value); } +/* Returns NULL if no replace had been done (and + original 'str' should be used instead). Otherwise + free the returned pointer with g_free(). +*/ +static gchar * +maybe_create_url (const gchar *str, + guint html_flags) +{ + gchar *tmp = NULL; + const gchar *url = NULL; + + g_return_val_if_fail (str != NULL, NULL); + + if ((html_flags & E_CREATE_CALLTO_URL) != 0) { + url = "callto:"; + } else if ((html_flags & E_CREATE_SIP_URL) != 0) { + url = "sip:"; + } + + if (url && g_ascii_strncasecmp (str, url, strlen (url)) != 0) + tmp = g_strconcat (url, str, NULL); + + return tmp; +} + static void accum_attribute (GString *buffer, EContact *contact, @@ -297,8 +327,17 @@ accum_attribute (GString *buffer, str = e_contact_get_const (contact, field); - if (str != NULL && *str != '\0') + if (str != NULL && *str != '\0') { + gchar *tmp = NULL; + + tmp = maybe_create_url (str, html_flags); + if (tmp) + str = tmp; + render_table_row (buffer, html_label, str, icon, html_flags); + + g_free (tmp); + } } static void @@ -336,24 +375,125 @@ accum_attribute_multival (GString *buffer, { GList *val_list, *l; GString *val = g_string_new (""); + const gchar *str; + gchar *tmp; val_list = e_contact_get (contact, field); for (l = val_list; l; l = l->next) { + str = l->data; + if (l != val_list) g_string_append (val, "<br>"); - g_string_append (val, l->data); + tmp = maybe_create_url (str, html_flags); + if (tmp) + str = tmp; + + if ((html_flags & E_TEXT_TO_HTML_CONVERT_URLS) != 0) { + gchar *value = e_text_to_html (str, html_flags); + + if (value && *value) + g_string_append (val, value); + + g_free (value); + } else { + g_string_append (val, str); + } + + g_free (tmp); } - if (val->str && *val->str) + if (val->str && *val->str) { + if ((html_flags & E_TEXT_TO_HTML_CONVERT_URLS) != 0) + html_flags = 0; + render_table_row (buffer, html_label, val->str, icon, html_flags); + } g_string_free (val, TRUE); g_list_foreach (val_list, (GFunc) g_free, NULL); g_list_free (val_list); } +typedef enum { + EAB_CONTACT_FORMATTER_SIP_TYPE_HOME, + EAB_CONTACT_FORMATTER_SIP_TYPE_WORK, + EAB_CONTACT_FORMATTER_SIP_TYPE_OTHER +} EABContactFormatterSIPType; + +static void +accum_sip (GString *buffer, + EContact *contact, + EABContactFormatterSIPType use_sip_type, + const gchar *icon, + guint html_flags) +{ + const gchar *html_label = _("SIP"); + GList *sip_attr_list, *l; + GString *val = g_string_new (""); + gchar *tmp; + + sip_attr_list = e_contact_get_attributes (contact, E_CONTACT_SIP); + for (l = sip_attr_list; l; l = g_list_next (l)) { + EVCardAttribute *attr = l->data; + gchar *sip; + const gchar *str; + EABContactFormatterSIPType sip_type; + + if (e_vcard_attribute_has_type (attr, "HOME")) + sip_type = EAB_CONTACT_FORMATTER_SIP_TYPE_HOME; + else if (e_vcard_attribute_has_type (attr, "WORK")) + sip_type = EAB_CONTACT_FORMATTER_SIP_TYPE_WORK; + else + sip_type = EAB_CONTACT_FORMATTER_SIP_TYPE_OTHER; + + if (sip_type != use_sip_type) + continue; + + sip = e_vcard_attribute_get_value (attr); + if (!sip || !*sip) { + g_free (sip); + continue; + } + + tmp = maybe_create_url (sip, html_flags); + if (tmp) + str = tmp; + else + str = sip; + + if ((html_flags & E_TEXT_TO_HTML_CONVERT_URLS) != 0) { + gchar *value = e_text_to_html (str, html_flags); + + if (value && *value) { + if (val->len) + g_string_append (val, "<br>"); + g_string_append (val, value); + } + + g_free (value); + } else { + if (val->len) + g_string_append (val, "<br>"); + g_string_append (val, str); + } + + g_free (tmp); + g_free (sip); + } + + if (val->str && *val->str) { + if ((html_flags & E_TEXT_TO_HTML_CONVERT_URLS) != 0) + html_flags = 0; + + render_table_row (buffer, html_label, val->str, icon, html_flags); + } + + g_string_free (val, TRUE); + g_list_free_full (sip_attr_list, (GDestroyNotify) e_vcard_attribute_free); +} + static const gchar * get_email_location (EVCardAttribute *attr) { @@ -554,6 +694,13 @@ render_contact_column (EABContactFormatter *formatter, GList *email_list, *l, *email_attr_list, *al; gint email_num = 0; const gchar *nl; + guint32 sip_flags = 0; + + if (formatter->priv->supports_sip) + sip_flags = E_TEXT_TO_HTML_CONVERT_URLS | + E_TEXT_TO_HTML_HIDE_URL_SCHEME | + E_TEXT_TO_HTML_URL_IS_WHOLE_TEXT | + E_CREATE_SIP_URL; email = g_string_new (""); nl = ""; @@ -595,6 +742,8 @@ render_contact_column (EABContactFormatter *formatter, if (email->len) render_table_row (accum, _("Email"), email->str, NULL, 0); + accum_sip (accum, contact, EAB_CONTACT_FORMATTER_SIP_TYPE_OTHER, NULL, sip_flags); + accum_attribute (accum, contact, _("Nickname"), E_CONTACT_NICKNAME, NULL, 0); accum_attribute_multival (accum, contact, _("AIM"), E_CONTACT_IM_AIM, AIM_ICON, 0); accum_attribute_multival (accum, contact, _("GroupWise"), E_CONTACT_IM_GROUPWISE, GROUPWISE_ICON, 0); @@ -647,6 +796,19 @@ render_work_column (EABContactFormatter *formatter, GString *buffer) { GString *accum = g_string_new (""); + guint32 phone_flags = 0, sip_flags = 0; + + if (formatter->priv->supports_callto) + phone_flags = E_TEXT_TO_HTML_CONVERT_URLS | + E_TEXT_TO_HTML_HIDE_URL_SCHEME | + E_TEXT_TO_HTML_URL_IS_WHOLE_TEXT | + E_CREATE_CALLTO_URL; + + if (formatter->priv->supports_sip) + sip_flags = E_TEXT_TO_HTML_CONVERT_URLS | + E_TEXT_TO_HTML_HIDE_URL_SCHEME | + E_TEXT_TO_HTML_URL_IS_WHOLE_TEXT | + E_CREATE_SIP_URL; accum_attribute (accum, contact, _("Company"), E_CONTACT_ORG, NULL, 0); accum_attribute (accum, contact, _("Department"), E_CONTACT_ORG_UNIT, NULL, 0); @@ -658,8 +820,9 @@ render_work_column (EABContactFormatter *formatter, accum_attribute (accum, contact, _("Video Chat"), E_CONTACT_VIDEO_URL, VIDEOCONF_ICON, E_TEXT_TO_HTML_CONVERT_URLS); accum_attribute (accum, contact, _("Calendar"), E_CONTACT_CALENDAR_URI, NULL, E_TEXT_TO_HTML_CONVERT_URLS); accum_attribute (accum, contact, _("Free/Busy"), E_CONTACT_FREEBUSY_URL, NULL, E_TEXT_TO_HTML_CONVERT_URLS); - accum_attribute (accum, contact, _("Phone"), E_CONTACT_PHONE_BUSINESS, NULL, 0); + accum_attribute (accum, contact, _("Phone"), E_CONTACT_PHONE_BUSINESS, NULL, phone_flags); accum_attribute (accum, contact, _("Fax"), E_CONTACT_PHONE_BUSINESS_FAX, NULL, 0); + accum_sip (accum, contact, EAB_CONTACT_FORMATTER_SIP_TYPE_WORK, NULL, sip_flags); accum_address (accum, contact, _("Address"), E_CONTACT_ADDRESS_WORK, E_CONTACT_ADDRESS_LABEL_WORK); if (formatter->priv->render_maps) accum_address_map (accum, contact, E_CONTACT_ADDRESS_WORK); @@ -682,11 +845,25 @@ render_personal_column (EABContactFormatter *formatter, GString *buffer) { GString *accum = g_string_new (""); + guint32 phone_flags = 0, sip_flags = 0; + + if (formatter->priv->supports_callto) + phone_flags = E_TEXT_TO_HTML_CONVERT_URLS | + E_TEXT_TO_HTML_HIDE_URL_SCHEME | + E_TEXT_TO_HTML_URL_IS_WHOLE_TEXT | + E_CREATE_CALLTO_URL; + + if (formatter->priv->supports_sip) + sip_flags = E_TEXT_TO_HTML_CONVERT_URLS | + E_TEXT_TO_HTML_HIDE_URL_SCHEME | + E_TEXT_TO_HTML_URL_IS_WHOLE_TEXT | + E_CREATE_SIP_URL; accum_attribute (accum, contact, _("Home Page"), E_CONTACT_HOMEPAGE_URL, NULL, E_TEXT_TO_HTML_CONVERT_URLS); accum_attribute (accum, contact, _("Web Log"), E_CONTACT_BLOG_URL, NULL, E_TEXT_TO_HTML_CONVERT_URLS); - accum_attribute (accum, contact, _("Phone"), E_CONTACT_PHONE_HOME, NULL, 0); - accum_attribute (accum, contact, _("Mobile Phone"), E_CONTACT_PHONE_MOBILE, NULL, 0); + accum_attribute (accum, contact, _("Phone"), E_CONTACT_PHONE_HOME, NULL, phone_flags); + accum_attribute (accum, contact, _("Mobile Phone"), E_CONTACT_PHONE_MOBILE, NULL, phone_flags); + accum_sip (accum, contact, EAB_CONTACT_FORMATTER_SIP_TYPE_HOME, NULL, sip_flags); accum_address (accum, contact, _("Address"), E_CONTACT_ADDRESS_HOME, E_CONTACT_ADDRESS_LABEL_HOME); accum_time_attribute (accum, contact, _("Birthday"), E_CONTACT_BIRTH_DATE, NULL, 0); accum_time_attribute (accum, contact, _("Anniversary"), E_CONTACT_ANNIVERSARY, NULL, 0); @@ -1022,6 +1199,21 @@ render_compact (EABContactFormatter *formatter, g_string_append (buffer, "</body></html>\n"); } +static gboolean +eab_contact_formatter_scheme_supported (const gchar *scheme) +{ + GAppInfo *app_info; + gboolean supported; + + app_info = g_app_info_get_default_for_uri_scheme (scheme); + supported = app_info != NULL; + + if (app_info && g_app_info_can_delete (app_info)) + g_app_info_delete (app_info); + + return supported; +} + static void eab_contact_formatter_set_property (GObject *object, guint property_id, @@ -1115,6 +1307,8 @@ eab_contact_formatter_init (EABContactFormatter *formatter) formatter->priv->mode = EAB_CONTACT_DISPLAY_RENDER_NORMAL; formatter->priv->render_maps = FALSE; + formatter->priv->supports_callto = eab_contact_formatter_scheme_supported ("callto"); + formatter->priv->supports_sip = eab_contact_formatter_scheme_supported ("sip"); } EABContactFormatter * diff --git a/e-util/e-html-utils.c b/e-util/e-html-utils.c index 4c49315c3d..260e26bdc0 100644 --- a/e-util/e-html-utils.c +++ b/e-util/e-html-utils.c @@ -75,13 +75,18 @@ static gint special_chars[] = { static gchar * url_extract (const guchar **text, - gboolean full_url) + gboolean full_url, + gboolean use_whole_text) { const guchar *end = *text, *p; gchar *out; - while (*end && is_url_char (*end)) - end++; + if (use_whole_text) { + end = (*text) + strlen ((const gchar *) (*text)); + } else { + while (*end && is_url_char (*end)) + end++; + } /* Back up if we probably went too far. */ while (end > *text && is_trailing_garbage (*(end - 1))) @@ -221,6 +226,13 @@ is_citation (const guchar *c, * - E_TEXT_TO_HTML_CITE: quote the text with "> " at the start of each * line. * + * - E_TEXT_TO_HTML_HIDE_URL_SCHEME: hides scheme part of the URL in + * the display part of the generated text (thus, instead of "http://www.example.com", + * user will only see "www.example.com") + * + * - E_TEXT_TO_HTML_URL_IS_WHOLE_TEXT: set when the whole @input text + * represents a URL + * * Returns: a newly-allocated string containing HTML **/ gchar * @@ -291,14 +303,30 @@ e_text_to_html_full (const gchar *input, !g_ascii_strncasecmp ((gchar *) cur, "h323:", 5) || !g_ascii_strncasecmp ((gchar *) cur, "sip:", 4) || !g_ascii_strncasecmp ((gchar *) cur, "webcal:", 7)) { - tmpurl = url_extract (&cur, TRUE); + tmpurl = url_extract (&cur, TRUE, (flags & E_TEXT_TO_HTML_URL_IS_WHOLE_TEXT) != 0); if (tmpurl) { refurl = e_text_to_html (tmpurl, 0); - dispurl = g_strdup (refurl); + if ((flags & E_TEXT_TO_HTML_HIDE_URL_SCHEME) != 0) { + const gchar *str; + + str = strchr (refurl, ':'); + if (str) { + str++; + if (g_ascii_strncasecmp (str, "//", 2) == 0) { + str += 2; + } + + dispurl = g_strdup (str); + } else { + dispurl = g_strdup (refurl); + } + } else { + dispurl = g_strdup (refurl); + } } } else if (!g_ascii_strncasecmp ((gchar *) cur, "www.", 4) && is_url_char (*(cur + 4))) { - tmpurl = url_extract (&cur, FALSE); + tmpurl = url_extract (&cur, FALSE, (flags & E_TEXT_TO_HTML_URL_IS_WHOLE_TEXT) != 0); if (tmpurl) { dispurl = e_text_to_html (tmpurl, 0); refurl = g_strdup_printf ( diff --git a/e-util/e-html-utils.h b/e-util/e-html-utils.h index 6ff93d7e65..ea48fbd890 100644 --- a/e-util/e-html-utils.h +++ b/e-util/e-html-utils.h @@ -36,6 +36,9 @@ #define E_TEXT_TO_HTML_CONVERT_ADDRESSES (1 << 5) #define E_TEXT_TO_HTML_ESCAPE_8BIT (1 << 6) #define E_TEXT_TO_HTML_CITE (1 << 7) +#define E_TEXT_TO_HTML_HIDE_URL_SCHEME (1 << 8) +#define E_TEXT_TO_HTML_URL_IS_WHOLE_TEXT (1 << 9) +#define E_TEXT_TO_HTML_LAST_FLAG (1 << 10) gchar *e_text_to_html_full (const gchar *input, guint flags, guint32 color); gchar *e_text_to_html (const gchar *input, guint flags); |