diff options
author | Christian Schaarschmidt <schaarsc@gmx.de> | 2014-05-06 20:31:50 +0800 |
---|---|---|
committer | Milan Crha <mcrha@redhat.com> | 2014-05-06 20:31:50 +0800 |
commit | c2de4087369147ed6797f6b7866629ff9da19dfc (patch) | |
tree | d9d91c19f4250f5b87bb6a18629d3a8f5465c734 | |
parent | 5306c9f8b0f3bd173b7864d1ba284ead4e5ffadd (diff) | |
download | gsoc2013-evolution-c2de4087369147ed6797f6b7866629ff9da19dfc.tar gsoc2013-evolution-c2de4087369147ed6797f6b7866629ff9da19dfc.tar.gz gsoc2013-evolution-c2de4087369147ed6797f6b7866629ff9da19dfc.tar.bz2 gsoc2013-evolution-c2de4087369147ed6797f6b7866629ff9da19dfc.tar.lz gsoc2013-evolution-c2de4087369147ed6797f6b7866629ff9da19dfc.tar.xz gsoc2013-evolution-c2de4087369147ed6797f6b7866629ff9da19dfc.tar.zst gsoc2013-evolution-c2de4087369147ed6797f6b7866629ff9da19dfc.zip |
Bug #653892 - Allow to enter more than four email addresses
-rw-r--r-- | addressbook/gui/contact-editor/contact-editor.ui | 181 | ||||
-rw-r--r-- | addressbook/gui/contact-editor/e-contact-editor-dyntable.c | 30 | ||||
-rw-r--r-- | addressbook/gui/contact-editor/e-contact-editor.c | 414 | ||||
-rw-r--r-- | addressbook/gui/widgets/eab-contact-merging.c | 78 | ||||
-rw-r--r-- | addressbook/printing/e-contact-print.c | 285 | ||||
-rw-r--r-- | addressbook/tools/evolution-addressbook-export-list-cards.c | 11 | ||||
-rw-r--r-- | e-util/e-name-selector-entry.c | 98 | ||||
-rw-r--r-- | e-util/e-tree-model-generator.c | 12 | ||||
-rw-r--r-- | e-util/e-tree-model-generator.h | 2 |
9 files changed, 573 insertions, 538 deletions
diff --git a/addressbook/gui/contact-editor/contact-editor.ui b/addressbook/gui/contact-editor/contact-editor.ui index 0c6edc838c..d4ae442f49 100644 --- a/addressbook/gui/contact-editor/contact-editor.ui +++ b/addressbook/gui/contact-editor/contact-editor.ui @@ -311,157 +311,40 @@ <property name="visible">True</property> <property name="label_xalign">0</property> <property name="shadow_type">none</property> - <child> - <object class="GtkTable" id="email-table"> - <property name="visible">True</property> - <property name="border_width">12</property> - <property name="n_rows">3</property> - <property name="n_columns">4</property> - <property name="column_spacing">6</property> - <property name="row_spacing">6</property> - <child> - <object class="GtkEntry" id="entry-email-3"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="name">email-3</property> - </object> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <object class="GtkEntry" id="entry-email-1"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="name">email-1</property> - </object> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <object class="GtkEntry" id="entry-email-2"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="name">email-2</property> - </object> - <packing> - <property name="left_attach">3</property> - <property name="right_attach">4</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <object class="GtkEntry" id="entry-email-4"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="name">email-4</property> - </object> - <packing> - <property name="left_attach">3</property> - <property name="right_attach">4</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <object class="GtkCheckButton" id="checkbutton-htmlmail"> - <property name="label" translatable="yes">_Wants to receive HTML mail</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="use_underline">True</property> - <property name="draw_indicator">True</property> - </object> - <packing> - <property name="right_attach">4</property> - <property name="top_attach">2</property> - <property name="bottom_attach">3</property> - <property name="x_options">GTK_FILL</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <object class="GtkComboBox" id="combobox-email-1"> - <property name="visible">True</property> - <property name="model">model2</property> - <child> - <object class="GtkCellRendererText" id="renderer2"/> - <attributes> - <attribute name="text">0</attribute> - </attributes> - </child> - </object> - <packing> - <property name="x_options">GTK_FILL</property> - <property name="y_options">GTK_FILL</property> - </packing> - </child> - <child> - <object class="GtkComboBox" id="combobox-email-3"> - <property name="visible">True</property> - <property name="model">model3</property> - <child> - <object class="GtkCellRendererText" id="renderer3"/> - <attributes> - <attribute name="text">0</attribute> - </attributes> - </child> - </object> - <packing> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="x_options">GTK_FILL</property> - <property name="y_options">GTK_FILL</property> - </packing> - </child> - <child> - <object class="GtkComboBox" id="combobox-email-2"> - <property name="visible">True</property> - <property name="model">model4</property> - <child> - <object class="GtkCellRendererText" id="renderer4"/> - <attributes> - <attribute name="text">0</attribute> - </attributes> - </child> - </object> - <packing> - <property name="left_attach">2</property> - <property name="right_attach">3</property> - <property name="x_options">GTK_FILL</property> - <property name="y_options">GTK_FILL</property> - </packing> - </child> + <child> - <object class="GtkComboBox" id="combobox-email-4"> + <object class="GtkVBox" id="vboxmail"> <property name="visible">True</property> - <property name="model">model5</property> - <child> - <object class="GtkCellRendererText" id="renderer5"/> - <attributes> - <attribute name="text">0</attribute> - </attributes> - </child> - </object> - <packing> - <property name="left_attach">2</property> - <property name="right_attach">3</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="x_options">GTK_FILL</property> - <property name="y_options">GTK_FILL</property> - </packing> - </child> - </object> - </child> + <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="mail-dyntable"> + <property name="visible">True</property> + </object> + <packing> + <property name="position">0</property> + </packing> + </child> + + <child> + <object class="GtkCheckButton" id="checkbutton-htmlmail"> + <property name="label" translatable="yes">_Wants to receive HTML mail</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="use_underline">True</property> + <property name="draw_indicator">True</property> + </object> + <packing> + <property name="position">1</property> + </packing> + </child> + + </object> + </child> + <child type="label"> <object class="GtkHBox" id="hbox561"> <property name="visible">True</property> diff --git a/addressbook/gui/contact-editor/e-contact-editor-dyntable.c b/addressbook/gui/contact-editor/e-contact-editor-dyntable.c index eb702720bf..68f298cdc9 100644 --- a/addressbook/gui/contact-editor/e-contact-editor-dyntable.c +++ b/addressbook/gui/contact-editor/e-contact-editor-dyntable.c @@ -257,6 +257,9 @@ add_empty_entry (EContactEditorDynTable *dyntable) GtkWidget *box, *entry; EContactEditorDynTableClass *class; + if (dyntable->priv->curr_entries >= dyntable->priv->max_entries) + return; + grid = GTK_GRID (dyntable); position_to_grid (dyntable, dyntable->priv->curr_entries, &col, &row); @@ -331,7 +334,9 @@ remove_empty_entries (EContactEditorDynTable *dyntable, gboolean fillup) } - if (fillup && dyntable->priv->curr_entries < dyntable->priv->show_min_entries) + if (fillup + && (dyntable->priv->curr_entries < dyntable->priv->show_min_entries + || (dyntable->priv->justified && col < dyntable->priv->columns-1))) add_empty_entry (dyntable); } @@ -409,21 +414,28 @@ void e_contact_editor_dyntable_set_max_entries (EContactEditorDynTable *dyntable, guint max) { - GtkTreeIter iter; GtkTreeModel *store; - gboolean holds_data; + gint n_children; g_return_if_fail (max > 0); store = GTK_TREE_MODEL (dyntable->priv->data_store); - holds_data = gtk_tree_model_get_iter_first (store, &iter); - g_return_if_fail (!holds_data); + + n_children = gtk_tree_model_iter_n_children (store, NULL); + if (n_children > max) { + g_warning ("Dyntable holds %i items, setting max to %i, instead of %i", + n_children, n_children, max); + max = n_children; + } dyntable->priv->max_entries = max; if (dyntable->priv->show_max_entries>max) dyntable->priv->show_max_entries = max; if (dyntable->priv->show_min_entries>max) dyntable->priv->show_min_entries = max; + + remove_empty_entries (dyntable, TRUE); + show_button (dyntable); } /* show at least number_of_entries, with or without data */ @@ -492,10 +504,12 @@ 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); - if (pos >= dyntable->priv->max_entries) - break; - valid = gtk_tree_model_iter_next (store, &iter); + + if (valid && pos >= dyntable->priv->max_entries) { + g_warning ("dyntable is configured with max_entries = %i, ignoring the rest.", dyntable->priv->max_entries); + break; + } } /* fix visibility of added items */ diff --git a/addressbook/gui/contact-editor/e-contact-editor.c b/addressbook/gui/contact-editor/e-contact-editor.c index ab7557188b..081c9fb8b0 100644 --- a/addressbook/gui/contact-editor/e-contact-editor.c +++ b/addressbook/gui/contact-editor/e-contact-editor.c @@ -48,7 +48,7 @@ #define SLOTS_PER_LINE 2 #define SLOTS_IN_COLLAPSED_STATE SLOTS_PER_LINE -#define EMAIL_SLOTS 4 +#define EMAIL_SLOTS 50 #define PHONE_SLOTS 50 #define SIP_SLOTS 4 #define IM_SLOTS 50 @@ -179,7 +179,8 @@ im_service[] = { E_CONTACT_IM_ICQ, N_ ("ICQ") }, { E_CONTACT_IM_GROUPWISE, N_ ("GroupWise") }, { E_CONTACT_IM_SKYPE, N_ ("Skype") }, - { E_CONTACT_IM_TWITTER, N_ ("Twitter") } + { E_CONTACT_IM_TWITTER, N_ ("Twitter") }, + { E_CONTACT_IM_GOOGLE_TALK, N_ ("Google Talk")} }; static EContactField @@ -193,7 +194,8 @@ im_service_fetch_set[] = E_CONTACT_IM_ICQ, E_CONTACT_IM_GROUPWISE, E_CONTACT_IM_SKYPE, - E_CONTACT_IM_TWITTER + E_CONTACT_IM_TWITTER, + E_CONTACT_IM_GOOGLE_TALK }; /* Defaults from the table above */ @@ -899,108 +901,28 @@ set_entry_text (EContactEditor *editor, } static void -set_combo_box_active (EContactEditor *editor, - GtkComboBox *combo_box, - gint active) -{ - g_signal_handlers_block_matched ( - combo_box, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, editor); - gtk_combo_box_set_active (combo_box, active); - g_signal_handlers_unblock_matched ( - combo_box, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, editor); -} - -static void -init_email_record_location (EContactEditor *editor, - gint record) +init_email_record_location (EContactEditor *editor) { - GtkComboBox *location_combo_box; - GtkWidget *email_entry; - gchar *widget_name; - gint i; - GtkTreeIter iter; + GtkWidget *w; GtkListStore *store; + gint i; + EContactEditorDynTable *dyntable; - widget_name = g_strdup_printf ("entry-email-%d", record); - email_entry = e_builder_get_widget (editor->priv->builder, widget_name); - g_free (widget_name); - - widget_name = g_strdup_printf ("combobox-email-%d", record); - location_combo_box = GTK_COMBO_BOX ( - e_builder_get_widget (editor->priv->builder, widget_name)); - g_free (widget_name); - - store = GTK_LIST_STORE (gtk_combo_box_get_model (location_combo_box)); - gtk_list_store_clear (store); + w = e_builder_get_widget (editor->priv->builder, "mail-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, - 0, _(common_location[i].pretty_name), - -1); + gtk_list_store_set (store, &iter, + DYNTABLE_COMBO_COLUMN_TEXT, _(common_location[i].pretty_name), + DYNTABLE_COMBO_COLUMN_SENSITIVE, TRUE, + -1); } - g_signal_connect_swapped ( - location_combo_box, "changed", - G_CALLBACK (gtk_widget_grab_focus), email_entry); - g_signal_connect ( - location_combo_box, "changed", - G_CALLBACK (object_changed), editor); - g_signal_connect ( - email_entry, "changed", - G_CALLBACK (object_changed), editor); - g_signal_connect_swapped ( - email_entry, "activate", - G_CALLBACK (entry_activated), editor); -} - -static void -fill_in_email_record (EContactEditor *editor, - gint record, - const gchar *address, - gint location) -{ - GtkWidget *location_combo_box; - GtkWidget *email_entry; - gchar *widget_name; - - widget_name = g_strdup_printf ("combobox-email-%d", record); - location_combo_box = e_builder_get_widget (editor->priv->builder, widget_name); - g_free (widget_name); - - widget_name = g_strdup_printf ("entry-email-%d", record); - email_entry = e_builder_get_widget (editor->priv->builder, widget_name); - g_free (widget_name); - - set_combo_box_active ( - editor, GTK_COMBO_BOX (location_combo_box), - location >= 0 ? location : email_default[2]); - set_entry_text (editor, GTK_ENTRY (email_entry), address ? address : ""); -} - -static void -extract_email_record (EContactEditor *editor, - gint record, - gchar **address, - gint *location) -{ - GtkWidget *location_combo_box; - GtkWidget *email_entry; - gchar *widget_name; - const gchar *text; - - widget_name = g_strdup_printf ("combobox-email-%d", record); - location_combo_box = e_builder_get_widget (editor->priv->builder, widget_name); - g_free (widget_name); - - widget_name = g_strdup_printf ("entry-email-%d", record); - email_entry = e_builder_get_widget (editor->priv->builder, widget_name); - g_free (widget_name); - - text = gtk_entry_get_text (GTK_ENTRY (email_entry)); - *address = g_strstrip (g_strdup (text)); - *location = gtk_combo_box_get_active (GTK_COMBO_BOX (location_combo_box)); + e_contact_editor_dyntable_set_combo_defaults (dyntable, email_default, G_N_ELEMENTS (email_default)); } static const gchar * @@ -1127,99 +1049,55 @@ set_ui_slot (EVCardAttribute *attr, g_free (slot_str); } -static gint -alloc_ui_slot (EContactEditor *editor, - const gchar *widget_base, - gint preferred_slot, - gint num_slots) -{ - gchar *widget_name; - GtkWidget *widget; - const gchar *entry_contents; - gint i; - - /* See if we can get the preferred slot */ - - if (preferred_slot >= 1) { - widget_name = g_strdup_printf ("%s-%d", widget_base, preferred_slot); - widget = e_builder_get_widget (editor->priv->builder, widget_name); - entry_contents = gtk_entry_get_text (GTK_ENTRY (widget)); - g_free (widget_name); - - if (STRING_IS_EMPTY (entry_contents)) - return preferred_slot; - } - - /* Find first empty slot */ - - for (i = 1; i <= num_slots; i++) { - widget_name = g_strdup_printf ("%s-%d", widget_base, i); - widget = e_builder_get_widget (editor->priv->builder, widget_name); - entry_contents = gtk_entry_get_text (GTK_ENTRY (widget)); - g_free (widget_name); - - if (STRING_IS_EMPTY (entry_contents)) - return i; - } - - return -1; -} - -static void -free_attr_list (GList *attr_list) -{ - GList *l; - - for (l = attr_list; l; l = g_list_next (l)) { - EVCardAttribute *attr = l->data; - e_vcard_attribute_free (attr); - } - - g_list_free (attr_list); -} - static void fill_in_email (EContactEditor *editor) { GList *email_attr_list; GList *l; - gint record_n; + GtkWidget *w; + EContactEditorDynTable *dyntable; + GtkListStore *data_store; + GtkTreeIter iter; + + w = e_builder_get_widget (editor->priv->builder, "mail-dyntable"); + dyntable = E_CONTACT_EDITOR_DYNTABLE (w); /* Clear */ - for (record_n = 1; record_n <= EMAIL_SLOTS; record_n++) { - fill_in_email_record ( - editor, record_n, NULL, email_default[record_n - 1]); - } + e_contact_editor_dyntable_clear_data (dyntable); /* Fill in */ + data_store = e_contact_editor_dyntable_extract_data (dyntable); + email_attr_list = e_contact_get_attributes ( editor->priv->contact, E_CONTACT_EMAIL); - for (record_n = 1, l = email_attr_list; - l && record_n <= EMAIL_SLOTS; l = g_list_next (l)) { + for (l = email_attr_list; l; l = g_list_next (l)) { EVCardAttribute *attr = l->data; gchar *email_address; + gint email_location; gint slot; email_address = e_vcard_attribute_get_value (attr); - slot = alloc_ui_slot ( - editor, "entry-email", - get_ui_slot (attr), EMAIL_SLOTS); + email_location = get_email_location (attr); + slot = get_ui_slot (attr); if (slot < 1) - break; - - fill_in_email_record ( - editor, slot, email_address, - get_email_location (attr)); + slot = EMAIL_SLOTS + 1; //add at the end - record_n++; + gtk_list_store_append (data_store, &iter); + gtk_list_store_set (data_store, &iter, + DYNTABLE_STORE_COLUMN_SORTORDER, slot, + DYNTABLE_STORE_COLUMN_SELECTED_ITEM, email_location, + DYNTABLE_STORE_COLUMN_ENTRY_STRING, email_address, + -1); g_free (email_address); } g_list_free_full (email_attr_list, (GDestroyNotify) e_vcard_attribute_free); + + e_contact_editor_dyntable_fill_in_data (dyntable); } static void @@ -1229,32 +1107,45 @@ extract_email (EContactEditor *editor) 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, "mail-dyntable"); + dyntable = E_CONTACT_EDITOR_DYNTABLE (w); + data_store = e_contact_editor_dyntable_extract_data (dyntable); + tree_model = GTK_TREE_MODEL (data_store); - for (i = 1; i <= EMAIL_SLOTS; i++) { + valid = gtk_tree_model_get_iter_first (tree_model, &iter); + while (valid) { gchar *address; gint location; + EVCardAttribute *attr; - extract_email_record (editor, i, &address, &location); + attr = e_vcard_attribute_new ( + "", e_contact_vcard_attribute (E_CONTACT_EMAIL)); - if (!STRING_IS_EMPTY (address)) { - EVCardAttribute *attr; - attr = e_vcard_attribute_new ( - "", e_contact_vcard_attribute (E_CONTACT_EMAIL)); + gtk_tree_model_get (tree_model,&iter, + DYNTABLE_STORE_COLUMN_SELECTED_ITEM, &location, + DYNTABLE_STORE_COLUMN_ENTRY_STRING, &address, + -1); - if (location >= 0) - e_vcard_attribute_add_param_with_value ( - attr, - e_vcard_attribute_param_new (EVC_TYPE), - email_index_to_location (location)); + if (location >= 0) + e_vcard_attribute_add_param_with_value ( + attr, + e_vcard_attribute_param_new (EVC_TYPE), + email_index_to_location (location)); - e_vcard_attribute_add_value (attr, address); - set_ui_slot (attr, i); + e_vcard_attribute_add_value (attr, address); - attr_list = g_list_append (attr_list, attr); - } + attr_list = g_list_prepend (attr_list, attr); - g_free (address); + valid = gtk_tree_model_iter_next (tree_model, &iter); } + attr_list = g_list_reverse (attr_list); /* Splice in the old attributes, minus the EMAIL_SLOTS first */ @@ -1269,47 +1160,41 @@ extract_email (EContactEditor *editor) e_contact_set_attributes (editor->priv->contact, E_CONTACT_EMAIL, attr_list); - free_attr_list (attr_list); -} - -static void -sensitize_email_record (EContactEditor *editor, - gint record, - gboolean enabled) -{ - GtkWidget *location_combo_box; - GtkWidget *email_entry; - gchar *widget_name; - - widget_name = g_strdup_printf ("combobox-email-%d", record); - location_combo_box = e_builder_get_widget (editor->priv->builder, widget_name); - g_free (widget_name); - - widget_name = g_strdup_printf ("entry-email-%d", record); - email_entry = e_builder_get_widget (editor->priv->builder, widget_name); - g_free (widget_name); - - gtk_widget_set_sensitive (location_combo_box, enabled); - gtk_editable_set_editable (GTK_EDITABLE (email_entry), enabled); + g_list_free_full (attr_list, (GDestroyNotify) e_vcard_attribute_free); } static void sensitize_email (EContactEditor *editor) { - gint i; - - for (i = 1; i <= EMAIL_SLOTS; i++) { - gboolean enabled = TRUE; - - if (!editor->priv->target_editable) - enabled = FALSE; + gboolean enabled = FALSE; + GtkWidget *w; + EContactEditorDynTable *dyntable; + guint max_entries = SLOTS_IN_COLLAPSED_STATE; - if (E_CONTACT_FIRST_EMAIL_ID + i - 1 <= E_CONTACT_LAST_EMAIL_ID && - !is_field_supported (editor, E_CONTACT_FIRST_EMAIL_ID + i - 1)) - enabled = FALSE; + w = e_builder_get_widget (editor->priv->builder, "mail-dyntable"); + dyntable = E_CONTACT_EDITOR_DYNTABLE (w); - sensitize_email_record (editor, i, enabled); + if (editor->priv->target_editable) { + if (is_field_supported (editor, E_CONTACT_EMAIL)) { + enabled = TRUE; + max_entries = EMAIL_SLOTS; + } else if (is_field_supported (editor, E_CONTACT_EMAIL_4)) { + enabled = TRUE; + max_entries = 4; + } else if (is_field_supported (editor, E_CONTACT_EMAIL_3)) { + enabled = TRUE; + max_entries = 3; + } else if (is_field_supported (editor, E_CONTACT_EMAIL_2)) { + enabled = TRUE; + max_entries = 2; + } else if (is_field_supported (editor, E_CONTACT_EMAIL_1)) { + enabled = TRUE; + max_entries = 1; + } } + + gtk_widget_set_sensitive (w, enabled); + e_contact_editor_dyntable_set_max_entries (dyntable, max_entries); } static void @@ -1427,43 +1312,52 @@ static void expand_mail (EContactEditor *editor, gboolean expanded) { - GtkTable *table; - GtkWidget *check; - const gchar *names[] = { - "entry-email-2", "combobox-email-2", - "entry-email-3", "combobox-email-3", - "entry-email-4", "combobox-email-4", - NULL - }; + GtkWidget *w; + EContactEditorDynTable *dyntable; + set_arrow_image (editor, "arrow-mail-expand", expanded); - expand_widget_list (editor, names, expanded); - /* move 'use html mail' into position */ - check = e_builder_get_widget (editor->priv->builder, "checkbutton-htmlmail"); - table = GTK_TABLE (e_builder_get_widget (editor->priv->builder, "email-table")); - if (check != NULL && table != NULL) { - GtkWidget *parent; - - g_object_ref (check); - parent = gtk_widget_get_parent (check); - gtk_container_remove (GTK_CONTAINER (parent), check); - if (expanded) - gtk_table_attach_defaults (table, check, 0, 4, 2, 3); - else - gtk_table_attach_defaults (table, check, 2, 4, 0, 1); - g_object_unref (check); - } + w = e_builder_get_widget (editor->priv->builder, "mail-dyntable"); + dyntable = E_CONTACT_EDITOR_DYNTABLE (w); + + if (expanded) + e_contact_editor_dyntable_set_show_max (dyntable, EMAIL_SLOTS); + else + e_contact_editor_dyntable_set_show_max (dyntable, SLOTS_IN_COLLAPSED_STATE); +} + +static void +row_added_mail (EContactEditorDynTable *dyntable, EContactEditor *editor) +{ + expand_mail (editor, TRUE); } static void init_email (EContactEditor *editor) { - gint i; + GtkWidget *w; + EContactEditorDynTable *dyntable; + + w = e_builder_get_widget (editor->priv->builder, "mail-dyntable"); + dyntable = E_CONTACT_EDITOR_DYNTABLE (w); - for (i = 1; i <= EMAIL_SLOTS; i++) - init_email_record_location (editor, i); + e_contact_editor_dyntable_set_max_entries (dyntable, EMAIL_SLOTS); + e_contact_editor_dyntable_set_num_columns (dyntable, SLOTS_PER_LINE, TRUE); + e_contact_editor_dyntable_set_show_min (dyntable, SLOTS_IN_COLLAPSED_STATE); - expand_mail (editor, !editor->priv->compress_ui); + 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_mail), editor); + + init_email_record_location (editor); + + expand_mail (editor, TRUE); } static void @@ -1496,6 +1390,9 @@ fill_in_phone (EContactEditor *editor) gint phone_type; slot = get_ui_slot (attr); + if (slot < 0) + slot = PHONE_SLOTS + 1; /* append at the end */ + phone_type = get_phone_type (attr); phone = e_vcard_attribute_get_value (attr); @@ -1510,9 +1407,8 @@ fill_in_phone (EContactEditor *editor) } e_contact_editor_dyntable_fill_in_data (dyntable); - g_list_free_full (tel_attr_list, (GDestroyNotify) e_vcard_attribute_free); - expand_phone (editor, TRUE); + g_list_free_full (tel_attr_list, (GDestroyNotify) e_vcard_attribute_free); } static void @@ -1626,7 +1522,7 @@ init_phone (EContactEditor *editor) e_contact_editor_dyntable_set_max_entries (dyntable, PHONE_SLOTS); e_contact_editor_dyntable_set_num_columns (dyntable, SLOTS_PER_LINE, TRUE); - e_contact_editor_dyntable_set_show_min (dyntable, SLOTS_PER_LINE); + e_contact_editor_dyntable_set_show_min (dyntable, SLOTS_IN_COLLAPSED_STATE); g_signal_connect ( w, "changed", @@ -1639,6 +1535,8 @@ init_phone (EContactEditor *editor) G_CALLBACK (row_added_phone), editor); init_phone_record_type (editor); + + expand_phone (editor, TRUE); } static void @@ -1676,12 +1574,17 @@ static void sensitize_phone (EContactEditor *editor) { GtkWidget *w; - gboolean enabled = TRUE; + gboolean enabled = FALSE; + int i; w = e_builder_get_widget (editor->priv->builder, "phone-dyntable"); - if (!editor->priv->target_editable) - enabled = FALSE; + if (editor->priv->target_editable) { + enabled = is_field_supported (editor, E_CONTACT_TEL); + for (i = 0; i < G_N_ELEMENTS (phones) && !enabled; i++) { + enabled = is_field_supported (editor, phones[i].field_id); + } + } gtk_widget_set_sensitive (w, enabled); @@ -1734,8 +1637,6 @@ fill_in_sip (EContactEditor *editor) 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 @@ -1845,7 +1746,7 @@ init_sip (EContactEditor *editor) 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); + e_contact_editor_dyntable_set_show_min (dyntable, SLOTS_IN_COLLAPSED_STATE); g_signal_connect ( w, "changed", @@ -1858,6 +1759,8 @@ init_sip (EContactEditor *editor) G_CALLBACK (row_added_sip), editor); init_sip_record_type (editor); + + expand_sip (editor, TRUE); } static void @@ -1950,7 +1853,7 @@ init_im (EContactEditor *editor) e_contact_editor_dyntable_set_max_entries (dyntable, IM_SLOTS); e_contact_editor_dyntable_set_num_columns (dyntable, SLOTS_PER_LINE, TRUE); - e_contact_editor_dyntable_set_show_min (dyntable, SLOTS_PER_LINE); + e_contact_editor_dyntable_set_show_min (dyntable, SLOTS_IN_COLLAPSED_STATE); g_signal_connect ( w, "changed", @@ -1963,6 +1866,8 @@ init_im (EContactEditor *editor) G_CALLBACK (row_added_im), editor); init_im_record_type (editor); + + expand_im (editor, TRUE); } static gint @@ -2034,8 +1939,6 @@ fill_in_im (EContactEditor *editor) g_list_free_full (im_attr_list, (GDestroyNotify) e_vcard_attribute_free); e_contact_editor_dyntable_fill_in_data (dyntable); - - expand_im (editor, TRUE); } static void @@ -4263,10 +4166,7 @@ expand_im_toggle (EContactEditor *ce) static void expand_mail_toggle (EContactEditor *ce) { - GtkWidget *mail; - - mail = e_builder_get_widget (ce->priv->builder, "entry-email-4"); - expand_mail (ce, !gtk_widget_get_visible (mail)); + expand_mail (ce, !is_arrow_image_arrow_down (ce, "arrow-mail-expand")); } static void diff --git a/addressbook/gui/widgets/eab-contact-merging.c b/addressbook/gui/widgets/eab-contact-merging.c index c788d4003a..38431785a5 100644 --- a/addressbook/gui/widgets/eab-contact-merging.c +++ b/addressbook/gui/widgets/eab-contact-merging.c @@ -543,40 +543,64 @@ check_if_same (EContact *contact, EContact *match) { EContactField field; - GList *email_attr_list; - gint num_of_email; - gchar *str = NULL, *string = NULL, *string1 = NULL; + gchar *string = NULL, *string1 = NULL; gboolean res = TRUE; - email_attr_list = e_contact_get_attributes (match, E_CONTACT_EMAIL); - num_of_email = g_list_length (email_attr_list); for (field = E_CONTACT_FULL_NAME; res && field != (E_CONTACT_LAST_SIMPLE_STRING -1); field++) { - if ((field == E_CONTACT_EMAIL_1 || field == E_CONTACT_EMAIL_2 - || field == E_CONTACT_EMAIL_3 || field == E_CONTACT_EMAIL_4) && (num_of_email < 4)) { - str = (gchar *) e_contact_get_const (contact, field); - switch (num_of_email) - { - case 0: + if (field == E_CONTACT_EMAIL_1) { + GList *email_attr_list1, *email_attr_list2, *iter1, *iter2; + gint num_of_email1, num_of_email2; + + email_attr_list1 = e_contact_get_attributes (contact, E_CONTACT_EMAIL); + num_of_email1 = g_list_length (email_attr_list1); + + email_attr_list2 = e_contact_get_attributes (match, E_CONTACT_EMAIL); + num_of_email2 = g_list_length (email_attr_list2); + + if (num_of_email1 != num_of_email2) { res = FALSE; break; - case 1: - if ((str && *str) && (g_ascii_strcasecmp (e_contact_get_const (match, E_CONTACT_EMAIL_1),str))) - res = FALSE; - break; - case 2: - if ((str && *str) && (g_ascii_strcasecmp (str,e_contact_get_const (match, E_CONTACT_EMAIL_1))) && - (g_ascii_strcasecmp (e_contact_get_const (match, E_CONTACT_EMAIL_2),str))) - res = FALSE; - break; - case 3: - if ((str && *str) && (g_ascii_strcasecmp (e_contact_get_const (match, E_CONTACT_EMAIL_1),str)) && - (g_ascii_strcasecmp (e_contact_get_const (match, E_CONTACT_EMAIL_2),str)) && - (g_ascii_strcasecmp (e_contact_get_const (match, E_CONTACT_EMAIL_3),str))) - res = FALSE; - break; + } else { /* Do pairwise-comparisons on all of the e-mail addresses. */ + iter1 = email_attr_list1; + while (iter1) { + gboolean match = FALSE; + EVCardAttribute *attr; + gchar *email_address1; + + attr = iter1->data; + email_address1 = e_vcard_attribute_get_value (attr); + + iter2 = email_attr_list2; + while ( iter2 && match == FALSE) { + gchar *email_address2; + + attr = iter2->data; + email_address2 = e_vcard_attribute_get_value (attr); + + if (g_ascii_strcasecmp (email_address1, email_address2) == 0) { + match = TRUE; + } + + g_free (email_address2); + iter2 = g_list_next (iter2); + } + + g_free (email_address1); + iter1 = g_list_next (iter1); + + if (match == FALSE) { + res = FALSE; + break; + } + } } + + g_list_free_full (email_attr_list1, (GDestroyNotify) e_vcard_attribute_free); + g_list_free_full (email_attr_list2, (GDestroyNotify) e_vcard_attribute_free); + } else if (field > E_CONTACT_FIRST_EMAIL_ID && field <= E_CONTACT_LAST_EMAIL_ID) { + /* nothing to do, all emails are checked above */ } else { string = (gchar *) e_contact_get_const (contact, field); @@ -592,8 +616,6 @@ check_if_same (EContact *contact, } } - g_list_free_full (email_attr_list, (GDestroyNotify) e_vcard_attribute_free); - return res; } diff --git a/addressbook/printing/e-contact-print.c b/addressbook/printing/e-contact-print.c index 3b1b1cd766..bcd27f879e 100644 --- a/addressbook/printing/e-contact-print.c +++ b/addressbook/printing/e-contact-print.c @@ -63,6 +63,61 @@ struct _EContactPrintContext GSList *contact_list; }; +/* TODO refactor phone_type + * to avoid build dependency loop, code related to phone types was copied from e-contact-editor.c + * once e-contact offers some kind of "translation service" code should be removed from here. + */ +static struct { + EContactField field_id; + const gchar *type_1; + const gchar *type_2; +} phones[] = { + { E_CONTACT_PHONE_ASSISTANT, EVC_X_ASSISTANT, NULL }, + { E_CONTACT_PHONE_BUSINESS, "WORK", "VOICE" }, + { E_CONTACT_PHONE_BUSINESS_FAX, "WORK", "FAX" }, + { E_CONTACT_PHONE_CALLBACK, EVC_X_CALLBACK, NULL }, + { E_CONTACT_PHONE_CAR, "CAR", NULL }, + { E_CONTACT_PHONE_COMPANY, "X-EVOLUTION-COMPANY", NULL }, + { E_CONTACT_PHONE_HOME, "HOME", "VOICE" }, + { E_CONTACT_PHONE_HOME_FAX, "HOME", "FAX" }, + { E_CONTACT_PHONE_ISDN, "ISDN", NULL }, + { E_CONTACT_PHONE_MOBILE, "CELL", NULL }, + { E_CONTACT_PHONE_OTHER, "VOICE", NULL }, + { E_CONTACT_PHONE_OTHER_FAX, "FAX", NULL }, + { E_CONTACT_PHONE_PAGER, "PAGER", NULL }, + { E_CONTACT_PHONE_PRIMARY, "PREF", NULL }, + { E_CONTACT_PHONE_RADIO, EVC_X_RADIO, NULL }, + { E_CONTACT_PHONE_TELEX, EVC_X_TELEX, NULL }, + { E_CONTACT_PHONE_TTYTDD, EVC_X_TTYTDD, NULL } +}; + +static gint +get_phone_type (EVCardAttribute *attr) +{ + gint i; + + 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))) + return i; + } + + return -1; +} + +static gint +get_phone_type_field_id (EVCardAttribute *attr) +{ + gint type_index; + + type_index = get_phone_type (attr); + + if (type_index >= 0) + return phones [type_index].field_id; + else + return -1; +} + static gdouble get_font_height (PangoFontDescription *desc) { @@ -227,6 +282,30 @@ e_contact_start_new_column (EContactPrintContext *ctxt) } } +/* + * returns (transfer-full) a formated email or a copy of value if parsing failed. + */ +static gchar* +format_email (const gchar* value) +{ + gchar *email = NULL, *name = NULL; + + if (eab_parse_qp_email (value, &name, &email)) { + gchar* res; + if (name && *name) + res = g_strdup_printf ("%s <%s>", name, email); + else + res = g_strdup_printf ("%s", email); + + g_free (name); + g_free (email); + + return res; + } + + return g_strdup (value); +} + static gchar * get_contact_string_value (EContact *contact, gint field) @@ -243,21 +322,8 @@ get_contact_string_value (EContact *contact, field == E_CONTACT_EMAIL_2 || field == E_CONTACT_EMAIL_3 || field == E_CONTACT_EMAIL_4) { - gchar *email = NULL, *name = NULL; - - if (eab_parse_qp_email (value, &name, &email)) { - gchar *res; - - if (name && *name) - res = g_strdup_printf ("%s <%s>", name, email); - else - res = g_strdup_printf ("%s", email); - - g_free (name); - g_free (email); - - return res; - } + gchar* res = format_email (value); + return res; } return g_strdup (value); } @@ -296,8 +362,34 @@ e_contact_get_contact_height (EContact *contact, "%s: %s", e_contact_pretty_name (field), value); - cntct_height += e_contact_text_height ( - ctxt->context, ctxt->style->body_font, text); + if (field == E_CONTACT_FIRST_EMAIL_ID) { + GList *emails = e_contact_get_attributes (contact, E_CONTACT_EMAIL); + guint n = g_list_length (emails); + cntct_height += n * e_contact_text_height ( + ctxt->context, + ctxt->style->body_font, + text); + g_list_free_full (emails, (GDestroyNotify) e_vcard_attribute_free); + } else if (field > E_CONTACT_FIRST_EMAIL_ID && + field <= E_CONTACT_LAST_EMAIL_ID) { + /* ignore */ + } else if (field == E_CONTACT_FIRST_PHONE_ID) { + GList *phones = e_contact_get_attributes (contact, E_CONTACT_TEL); + guint n = g_list_length (phones); + cntct_height += n * e_contact_text_height ( + ctxt->context, + ctxt->style->body_font, + text); + g_list_free_full (phones, (GDestroyNotify) e_vcard_attribute_free); + } else if (field > E_CONTACT_FIRST_PHONE_ID && + field <= E_CONTACT_LAST_PHONE_ID) { + /* ignore */ + } else { + cntct_height += e_contact_text_height ( + ctxt->context, + ctxt->style->body_font, + text); + } cntct_height += .2 * get_font_height (ctxt->style->body_font); @@ -309,19 +401,116 @@ e_contact_get_contact_height (EContact *contact, return cntct_height; } +static void +print_line (EContactPrintContext *ctxt, + const gchar *pretty_name, + const gchar *value) +{ + GtkPageSetup *setup; + gdouble page_height; + gint wrapped_lines = 0; + gchar *text; + + setup = gtk_print_context_get_page_setup (ctxt->context); + page_height = gtk_page_setup_get_page_height (setup, GTK_UNIT_POINTS); + + text = g_strdup_printf ( + "%s: %s", + pretty_name, value); + + + if (ctxt->y > page_height) + e_contact_start_new_column (ctxt); + + if (ctxt->pages == ctxt->page_nr) + e_contact_output ( + ctxt->context, ctxt->style->body_font, + ctxt->x, ctxt->y, ctxt->column_width + 4, text); + + if (get_font_width (ctxt->context, + ctxt->style->body_font, text) > ctxt->column_width) + wrapped_lines = + (get_font_width (ctxt->context, + ctxt->style->body_font, text) / + (ctxt->column_width + 4)) + 1; + ctxt->y = + ctxt->y + ((wrapped_lines + 1) * + e_contact_text_height ( + ctxt->context, + ctxt->style->body_font, + text)); + + ctxt->y += .2 * get_font_height (ctxt->style->body_font); + + g_free (text); +} + +static void +print_emails (EContact *contact, + EContactPrintContext *ctxt) +{ + gint i; + GList *emails, *l; + + emails = e_contact_get_attributes (contact, E_CONTACT_EMAIL); + + for (i = 1, l = emails; l; l = g_list_next (l), i++) { + EVCardAttribute *attr = l->data; + gchar *email_address; + gchar *formatted_email; + gchar *pretty_name; + + email_address = e_vcard_attribute_get_value (attr); + formatted_email = format_email (email_address); + pretty_name = g_strdup_printf ("%s %2d", N_ ("Email"), i); + + print_line (ctxt, pretty_name, formatted_email); + + g_free (pretty_name); + g_free (email_address); + g_free (formatted_email); + } + + g_list_free_full (emails, (GDestroyNotify) e_vcard_attribute_free); +} + +static void +print_phones (EContact *contact, + EContactPrintContext * ctxt) +{ + GList *phones, *l; + + phones = e_contact_get_attributes (contact, E_CONTACT_TEL); + + for (l = phones; l; l = g_list_next (l)) { + EVCardAttribute *attr = l->data; + gchar *phone; + gint field_id; + const gchar *pretty_name; + + phone = e_vcard_attribute_get_value (attr); + field_id = get_phone_type_field_id (attr); + if (field_id >= 0) { + pretty_name = e_contact_pretty_name (field_id); + } else { + pretty_name = N_ ("unknown phone type"); + } + print_line (ctxt, pretty_name, phone); + + g_free (phone); + } + + g_list_free_full (phones, (GDestroyNotify) e_vcard_attribute_free); +} static void e_contact_print_contact (EContact *contact, EContactPrintContext *ctxt) { - GtkPageSetup *setup; gchar *file_as; cairo_t *cr; - gdouble page_height; gint field; - setup = gtk_print_context_get_page_setup (ctxt->context); - page_height = gtk_page_setup_get_page_height (setup, GTK_UNIT_POINTS); cr = gtk_print_context_get_cairo_context (ctxt->context); cairo_save (cr); @@ -353,45 +542,29 @@ e_contact_print_contact (EContact *contact, for (field = E_CONTACT_FILE_AS; field != E_CONTACT_LAST_SIMPLE_STRING; field++) { - gchar *value; - gchar *text; - gint wrapped_lines = 0; + if (field == E_CONTACT_FIRST_EMAIL_ID) + print_emails (contact, ctxt); + else if (field > E_CONTACT_FIRST_EMAIL_ID && + field <= E_CONTACT_LAST_EMAIL_ID) + ; /* ignore, all emails are printed in print_emails() */ + else if (field == E_CONTACT_FIRST_PHONE_ID) + print_phones (contact, ctxt); + else if (field > E_CONTACT_FIRST_PHONE_ID && + field <= E_CONTACT_LAST_PHONE_ID) + ; /* ignore, all phones are printed in print_phones() */ + else { + gchar *value; + + value = get_contact_string_value (contact, field); + if (value == NULL || *value == '\0') { + g_free (value); + continue; + } - if (ctxt->y > page_height) - e_contact_start_new_column (ctxt); + print_line (ctxt, e_contact_pretty_name (field), value); - value = get_contact_string_value (contact, field); - if (value == NULL || *value == '\0') { g_free (value); - continue; } - - text = g_strdup_printf ( - "%s: %s", - e_contact_pretty_name (field), value); - - if (ctxt->pages == ctxt->page_nr) - e_contact_output ( - ctxt->context, ctxt->style->body_font, - ctxt->x, ctxt->y, ctxt->column_width + 4, text); - - if (get_font_width (ctxt->context, - ctxt->style->body_font, text) > ctxt->column_width) - wrapped_lines = - (get_font_width (ctxt->context, - ctxt->style->body_font, text) / - (ctxt->column_width + 4)) + 1; - ctxt->y = - ctxt->y + ((wrapped_lines + 1) * - e_contact_text_height ( - ctxt->context, - ctxt->style->body_font, - text)); - - ctxt->y += .2 * get_font_height (ctxt->style->body_font); - - g_free (value); - g_free (text); } ctxt->y += get_font_height (ctxt->style->headings_font) * .4 + 8; diff --git a/addressbook/tools/evolution-addressbook-export-list-cards.c b/addressbook/tools/evolution-addressbook-export-list-cards.c index 3faf245859..c6261f6c53 100644 --- a/addressbook/tools/evolution-addressbook-export-list-cards.c +++ b/addressbook/tools/evolution-addressbook-export-list-cards.c @@ -461,6 +461,17 @@ e_contact_get_csv (EContact *contact, GSList *csv_all_fields) { gchar *aline; + GList *emails; + guint n_emails; + gchar *full_name; + + emails = e_contact_get_attributes (contact, E_CONTACT_EMAIL); + n_emails = g_list_length (emails); + full_name = e_contact_get (contact, E_CONTACT_FULL_NAME); + if (n_emails > 4) + g_warning ("%s: only 4 out of %i emails have been exported", full_name, n_emails); + g_free (full_name); + g_list_free_full (emails, (GDestroyNotify) e_vcard_attribute_free); aline = e_contact_to_csv (contact, csv_all_fields); return aline; diff --git a/e-util/e-name-selector-entry.c b/e-util/e-name-selector-entry.c index 0f872e718f..a50c886e9c 100644 --- a/e-util/e-name-selector-entry.c +++ b/e-util/e-name-selector-entry.c @@ -832,11 +832,13 @@ utf8_casefold_collate_len (const gchar *str1, static gchar * build_textrep_for_contact (EContact *contact, - EContactField cue_field) + EContactField cue_field, + gint email_num) { gchar *name = NULL; gchar *email = NULL; gchar *textrep; + GList *l; switch (cue_field) { case E_CONTACT_FULL_NAME: @@ -846,12 +848,11 @@ build_textrep_for_contact (EContact *contact, email = e_contact_get (contact, E_CONTACT_EMAIL_1); break; - case E_CONTACT_EMAIL_1: - case E_CONTACT_EMAIL_2: - case E_CONTACT_EMAIL_3: - case E_CONTACT_EMAIL_4: + case E_CONTACT_EMAIL: name = NULL; - email = e_contact_get (contact, cue_field); + l = e_contact_get (contact, cue_field); + email = strdup (g_list_nth_data (l, email_num)); + g_list_free_full (l, g_free); break; default: @@ -877,11 +878,11 @@ contact_match_cue (ENameSelectorEntry *name_selector_entry, EContact *contact, const gchar *cue_str, EContactField *matched_field, - gint *matched_field_rank) + gint *matched_field_rank, + gint *matched_email_num) { EContactField fields[] = { E_CONTACT_FULL_NAME, E_CONTACT_NICKNAME, E_CONTACT_FILE_AS, - E_CONTACT_EMAIL_1, E_CONTACT_EMAIL_2, E_CONTACT_EMAIL_3, - E_CONTACT_EMAIL_4 }; + E_CONTACT_EMAIL }; gchar *email; gboolean result = FALSE; gint cue_len; @@ -903,36 +904,47 @@ contact_match_cue (ENameSelectorEntry *name_selector_entry, } g_free (email); - for (i = 0; i < G_N_ELEMENTS (fields); i++) { + for (i = 0; i < G_N_ELEMENTS (fields) && result == FALSE; i++) { + gint email_num; gchar *value; gchar *value_sane; + GList *emails = NULL, *ll = NULL; /* Don't match e-mail addresses in contact lists */ if (e_contact_get (contact, E_CONTACT_IS_LIST) && - fields[i] >= E_CONTACT_FIRST_EMAIL_ID && - fields[i] <= E_CONTACT_LAST_EMAIL_ID) + fields[i] == E_CONTACT_EMAIL) continue; - value = e_contact_get (contact, fields[i]); - if (!value) - continue; + if (fields[i] == E_CONTACT_EMAIL) { + emails = e_contact_get (contact, fields[i]); + } else { + value = e_contact_get (contact, fields[i]); + if (!value) + continue; + emails = g_list_append (emails, value); + } - value_sane = sanitize_string (value); - g_free (value); + for (ll = emails, email_num = 0; ll; ll = ll->next, email_num++) { + value = ll->data; + value_sane = sanitize_string (value); - ENS_DEBUG (g_print ("Comparing '%s' to '%s'\n", value, cue_str)); + ENS_DEBUG (g_print ("Comparing '%s' to '%s'\n", value, cue_str)); - if (!utf8_casefold_collate_len (value_sane, cue_str, cue_len)) { - if (matched_field) - *matched_field = fields [i]; - if (matched_field_rank) - *matched_field_rank = i; + if (!utf8_casefold_collate_len (value_sane, cue_str, cue_len)) { + if (matched_field) + *matched_field = fields[i]; + if (matched_field_rank) + *matched_field_rank = i; + if (matched_email_num) + *matched_email_num = email_num; - result = TRUE; + result = TRUE; + g_free (value_sane); + break; + } g_free (value_sane); - break; } - g_free (value_sane); + g_list_free_full (emails, g_free); } return result; @@ -944,12 +956,14 @@ find_existing_completion (ENameSelectorEntry *name_selector_entry, EContact **contact, gchar **text, EContactField *matched_field, + gint *matched_email_num, EBookClient **book_client) { GtkTreeIter iter; EContact *best_contact = NULL; gint best_field_rank = G_MAXINT; EContactField best_field = 0; + gint best_email_num = -1; EBookClient *best_book_client = NULL; g_assert (cue_str); @@ -965,6 +979,7 @@ find_existing_completion (ENameSelectorEntry *name_selector_entry, do { EContact *current_contact; gint current_field_rank; + gint current_email_num; EContactField current_field; gboolean matches; @@ -972,13 +987,15 @@ find_existing_completion (ENameSelectorEntry *name_selector_entry, if (!current_contact) continue; - matches = contact_match_cue (name_selector_entry, current_contact, cue_str, ¤t_field, ¤t_field_rank); + matches = contact_match_cue (name_selector_entry, current_contact, cue_str, ¤t_field, ¤t_field_rank, ¤t_email_num); if (matches && current_field_rank < best_field_rank) { best_contact = current_contact; best_field_rank = current_field_rank; best_field = current_field; best_book_client = e_contact_store_get_client (name_selector_entry->priv->contact_store, &iter); + best_email_num = current_email_num; } + } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (name_selector_entry->priv->contact_store), &iter)); if (!best_contact) @@ -987,12 +1004,13 @@ find_existing_completion (ENameSelectorEntry *name_selector_entry, if (contact) *contact = best_contact; if (text) - *text = build_textrep_for_contact (best_contact, best_field); + *text = build_textrep_for_contact (best_contact, best_field, best_email_num); if (matched_field) *matched_field = best_field; if (book_client) *book_client = best_book_client; - + if (matched_email_num) + *matched_email_num = best_email_num; return TRUE; } @@ -1060,6 +1078,7 @@ type_ahead_complete (ENameSelectorEntry *name_selector_entry) EBookClient *book_client = NULL; EContactField matched_field; EDestination *destination; + gint matched_email_num; gint cursor_pos; gint range_start = 0; gint range_end = 0; @@ -1088,7 +1107,7 @@ type_ahead_complete (ENameSelectorEntry *name_selector_entry) cue_str = get_entry_substring (name_selector_entry, range_start, range_end); if (!find_existing_completion (name_selector_entry, cue_str, &contact, - &textrep, &matched_field, &book_client)) { + &textrep, &matched_field, &matched_email_num, &book_client)) { g_free (cue_str); return; } @@ -1133,9 +1152,8 @@ type_ahead_complete (ENameSelectorEntry *name_selector_entry) if (contact && destination) { gint email_n = 0; - if (matched_field >= E_CONTACT_FIRST_EMAIL_ID && matched_field <= E_CONTACT_LAST_EMAIL_ID) - email_n = matched_field - E_CONTACT_FIRST_EMAIL_ID; - + if (matched_field == E_CONTACT_EMAIL) + email_n = matched_email_num; e_destination_set_contact (destination, contact, email_n); if (book_client) e_destination_set_client (destination, book_client); @@ -2042,6 +2060,7 @@ contact_layout_pixbuffer (GtkCellLayout *cell_layout, GtkTreeIter contact_store_iter; gint email_n; EContactPhoto *photo; + gboolean iter_is_valid; GdkPixbuf *pixbuf = NULL; if (!name_selector_entry->priv->contact_store) @@ -2050,11 +2069,15 @@ contact_layout_pixbuffer (GtkCellLayout *cell_layout, gtk_tree_model_filter_convert_iter_to_child_iter ( GTK_TREE_MODEL_FILTER (model), &generator_iter, iter); - e_tree_model_generator_convert_iter_to_child_iter ( + iter_is_valid = e_tree_model_generator_convert_iter_to_child_iter ( name_selector_entry->priv->email_generator, &contact_store_iter, &email_n, &generator_iter); + if (!iter_is_valid) { + return; + } + contact = e_contact_store_get_contact (name_selector_entry->priv->contact_store, &contact_store_iter); if (!contact) { g_object_set (cell, "pixbuf", pixbuf, NULL); @@ -2121,6 +2144,7 @@ contact_layout_formatter (GtkCellLayout *cell_layout, gchar *file_as_str; gchar *email_str; gint email_n; + gboolean iter_is_valid; if (!name_selector_entry->priv->contact_store) return; @@ -2128,11 +2152,15 @@ contact_layout_formatter (GtkCellLayout *cell_layout, gtk_tree_model_filter_convert_iter_to_child_iter ( GTK_TREE_MODEL_FILTER (model), &generator_iter, iter); - e_tree_model_generator_convert_iter_to_child_iter ( + iter_is_valid = e_tree_model_generator_convert_iter_to_child_iter ( name_selector_entry->priv->email_generator, &contact_store_iter, &email_n, &generator_iter); + if (!iter_is_valid) { + return; + } + contact = e_contact_store_get_contact (name_selector_entry->priv->contact_store, &contact_store_iter); email_list = e_contact_get (contact, E_CONTACT_EMAIL); email_str = g_list_nth_data (email_list, email_n); diff --git a/e-util/e-tree-model-generator.c b/e-util/e-tree-model-generator.c index f035d120f6..981ca51a0a 100644 --- a/e-util/e-tree-model-generator.c +++ b/e-util/e-tree-model-generator.c @@ -969,7 +969,7 @@ e_tree_model_generator_convert_path_to_child_path (ETreeModelGenerator *tree_mod * The permutation index is the index of the generated row based on this * child row, with the first generated row based on this child row being 0. **/ -void +gboolean e_tree_model_generator_convert_iter_to_child_iter (ETreeModelGenerator *tree_model_generator, GtkTreeIter *child_iter, gint *permutation_n, @@ -979,9 +979,10 @@ e_tree_model_generator_convert_iter_to_child_iter (ETreeModelGenerator *tree_mod GArray *group; gint index; gint internal_offset = 0; + gboolean iter_is_valid = FALSE; - g_return_if_fail (E_IS_TREE_MODEL_GENERATOR (tree_model_generator)); - g_return_if_fail (ITER_IS_VALID (tree_model_generator, generator_iter)); + g_return_val_if_fail (E_IS_TREE_MODEL_GENERATOR (tree_model_generator), iter_is_valid); + g_return_val_if_fail (ITER_IS_VALID (tree_model_generator, generator_iter), iter_is_valid); path = gtk_tree_path_new (); ITER_GET (generator_iter, &group, &index); @@ -1000,11 +1001,14 @@ e_tree_model_generator_convert_iter_to_child_iter (ETreeModelGenerator *tree_mod } if (child_iter) - gtk_tree_model_get_iter (tree_model_generator->priv->child_model, child_iter, path); + iter_is_valid = gtk_tree_model_get_iter (tree_model_generator->priv->child_model, child_iter, path); + if (permutation_n) *permutation_n = internal_offset; gtk_tree_path_free (path); + + return iter_is_valid; } /* ---------------- * diff --git a/e-util/e-tree-model-generator.h b/e-util/e-tree-model-generator.h index 59cf0ad90b..739df1fd66 100644 --- a/e-util/e-tree-model-generator.h +++ b/e-util/e-tree-model-generator.h @@ -92,7 +92,7 @@ void e_tree_model_generator_convert_child_iter_to_iter GtkTreePath * e_tree_model_generator_convert_path_to_child_path (ETreeModelGenerator *tree_model_generator, GtkTreePath *generator_path); -void e_tree_model_generator_convert_iter_to_child_iter +gboolean e_tree_model_generator_convert_iter_to_child_iter (ETreeModelGenerator *tree_model_generator, GtkTreeIter *child_iter, gint *permutation_n, |