From: Jose Dapena Paz Date: Wed, 2 May 2007 14:12:38 +0000 (+0000) Subject: * src/modest-ui-actions.[ch]: X-Git-Tag: git_migration_finished~3730 X-Git-Url: http://git.maemo.org/git/?p=modest;a=commitdiff_plain;h=556398d85f1803ab8d4871a107bc4b8938c444ae * src/modest-ui-actions.[ch]: * Run check names before sending email from editor. * New check names action, used to validate and search addresses in addressbook. * src/modest-address-book.h: * Added new check_names method. * src/modest-text-utils.[ch]: * Added ..._get_addresses_indexes. It finds the offset ranges of the addresses in a string. * ..._split_addresses_list now takes ";" into account, not only ",". * ..._split_addresses_list fixed offset calculations. Now uses utf8 characters. * ..._validate_recipient: strips the string before processing. * ..._validate_recipient: now counts utf8 characters. Also accepts spaces in left part of the address, even when they're not between quotes. * src/maemo/modest-address-book.c: * ..._add_address: now the dialog title uses the logical id. * (ui_get_formatted_email_id): Now it adds quotes to address strings with spaces. * New ..._check_names method. It validates all addresses in the recipient editor. If address is valid, ok, if not valid, it checks if this is an email address attempt (shows error) or a generic string (searches in addressbook and replaces with matches). * src/maemo/modest-msg-edit-window.c: * New ..._check_names method. Checks all recipient fields using new check names implementation in addressbook module. * src/maemo/ui/modest-msg-edit-window-ui.xml: * Added "Check names" menu option. * src/gnome/modest-address-book.c: * Added stubs for new functions. * src/gnome/modest-msg-edit-window.c: * Added stubs for new functions. * src/widgets/modest-msg-edit-window.h: * New _check_names method. * src/widgets/modest-recpt-editor.[ch]: * Now , and ; inside quotes do not insert a CR. * New ..._replace_with_resolved_recipient method, to replace a range of the editor with a resolved recipient. It's used on _check_names implementation. * src/widgets/modest-msg-edit-window-ui.h: * Added action for check names. pmo-trunk-r1730 --- diff --git a/src/gnome/modest-address-book.c b/src/gnome/modest-address-book.c index be2d292..e401a51 100644 --- a/src/gnome/modest-address-book.c +++ b/src/gnome/modest-address-book.c @@ -42,3 +42,10 @@ modest_address_book_select_addresses (ModestRecptEditor *editor) { g_message (__FUNCTION__); } + +gboolean +modest_address_book_check_names (ModestRecptEditor *editor) +{ + g_message (__FUNCTION__); + return TRUE; +} diff --git a/src/gnome/modest-msg-edit-window.c b/src/gnome/modest-msg-edit-window.c index 51a4590..637d172 100644 --- a/src/gnome/modest-msg-edit-window.c +++ b/src/gnome/modest-msg-edit-window.c @@ -555,6 +555,15 @@ modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window) g_message ("not implemented yet %s", __FUNCTION__); } +gboolean +modest_msg_edit_window_check_names (ModestMsgEditWindow *window) +{ + g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE); + + g_message ("not implemented yet %s", __FUNCTION__); + return TRUE; +} + void modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window, gint file_format) diff --git a/src/maemo/modest-address-book.c b/src/maemo/modest-address-book.c index 183034a..8554d1d 100644 --- a/src/maemo/modest-address-book.c +++ b/src/maemo/modest-address-book.c @@ -56,6 +56,8 @@ static gchar *ui_get_formatted_email_id(gchar * current_given_name, gchar * current_sur_name, gchar * current_email_id); static gchar *run_add_email_addr_to_contact_dlg(const gchar * contact_name); static GSList *select_email_addrs_for_contact(GList * email_addr_list); +static gboolean resolve_address (const gchar *address, GSList **resolved_addresses, gchar **contact_id); +static gchar *unquote_string (const gchar *str); static void @@ -102,6 +104,18 @@ open_addressbook () return TRUE; /* FIXME */ } +static gboolean +open_addressbook_sync () +{ + book = e_book_new_system_addressbook (NULL); + if (!book) + return FALSE; + + e_book_open (book, FALSE, NULL); + + return TRUE; +} + void modest_address_book_add_address (const gchar *address) { @@ -160,6 +174,7 @@ modest_address_book_select_addresses (ModestRecptEditor *recpt_editor) contact_dialog = osso_abook_select_dialog_new (OSSO_ABOOK_TREE_VIEW (contact_view)); osso_abook_select_dialog_set_new_contact (OSSO_ABOOK_SELECT_DIALOG (contact_dialog), TRUE); + gtk_window_set_title (GTK_WINDOW (contact_dialog), _("mcen_ti_select_recipients")); gtk_widget_show (contact_dialog); @@ -365,27 +380,23 @@ ui_get_formatted_email_id(gchar * current_given_name, gchar * current_sur_name, gchar * current_email_id) { GString *email_id_str = NULL; - gchar *email_id = NULL; email_id_str = g_string_new(NULL); if ((current_given_name != NULL) && ((strlen(current_given_name) != 0)) && (current_sur_name != NULL) && ((strlen(current_sur_name) != 0))) { - g_string_printf(email_id_str, "%s %s %c%s%c", current_given_name, - current_sur_name, '<', current_email_id, '>'); - email_id = g_strdup(email_id_str->str); + g_string_append_printf(email_id_str, "%s %s", current_given_name, current_sur_name); } else if ((current_given_name != NULL) && (strlen(current_given_name) != 0)) { - g_string_printf(email_id_str, "%s %c%s%c", current_given_name, '<', - current_email_id, '>'); - email_id = g_strdup(email_id_str->str); + g_string_append_printf(email_id_str, "%s", current_given_name); } else if ((current_sur_name != NULL) && (strlen(current_sur_name) != 0)) { - g_string_printf(email_id_str, "%s %c%s%c", current_sur_name, '<', - current_email_id, '>'); - email_id = g_strdup(email_id_str->str); + g_string_append_printf(email_id_str, "%s", current_sur_name); } - g_string_free(email_id_str, TRUE); - email_id_str = NULL; - return (email_id); + if (g_utf8_strchr (email_id_str->str, -1, ' ')) { + g_string_prepend_c (email_id_str, '\"'); + g_string_append_c (email_id_str, '\"'); + } + g_string_append_printf (email_id_str, " %c%s%c", '<', current_email_id, '>'); + return g_string_free (email_id_str, FALSE); } /** @@ -542,3 +553,245 @@ select_email_addrs_for_contact(GList * email_addr_list) gtk_widget_destroy(select_email_addr_dlg); return selected_email_addr_list; } + +gboolean +modest_address_book_check_names (ModestRecptEditor *recpt_editor) +{ + const gchar *recipients = NULL; + GSList *start_indexes = NULL, *end_indexes = NULL; + GSList *current_start, *current_end; + gboolean result = TRUE; + GtkTextBuffer *buffer; + gint offset_delta = 0; + gint last_length; + GtkTextIter start_iter, end_iter; + GtkWidget *banner; + + g_return_val_if_fail (MODEST_IS_RECPT_EDITOR (recpt_editor), FALSE); + + banner = hildon_banner_show_animation (NULL, NULL, _("mail_ib_checking_names")); + g_object_ref (G_OBJECT (banner)); + + recipients = modest_recpt_editor_get_recipients (recpt_editor); + last_length = g_utf8_strlen (recipients, -1); + g_message ("LENGTH %d", last_length); + modest_text_utils_get_addresses_indexes (recipients, &start_indexes, &end_indexes); + + if (start_indexes == NULL) { + gtk_widget_destroy (banner); + g_object_unref (G_OBJECT(banner)); + return TRUE; + } + + current_start = start_indexes; + current_end = end_indexes; + buffer = modest_recpt_editor_get_buffer (recpt_editor); + + while (current_start != NULL) { + gchar *address; + gchar *start_ptr, *end_ptr; + gint start_pos, end_pos; + + start_pos = (*((gint*) current_start->data)) + offset_delta; + end_pos = (*((gint*) current_end->data)) + offset_delta; + + start_ptr = g_utf8_offset_to_pointer (recipients, start_pos); + end_ptr = g_utf8_offset_to_pointer (recipients, end_pos); + + address = g_strndup (start_ptr, end_ptr - start_ptr); + gtk_text_buffer_get_iter_at_offset (buffer, &start_iter, start_pos); + gtk_text_buffer_get_iter_at_offset (buffer, &end_iter, end_pos); + gtk_text_buffer_select_range (buffer, &start_iter, &end_iter); + + g_message ("RANGE %d - %d", start_pos, end_pos); + + g_message ("ADDRESS %s", address); + if (!modest_text_utils_validate_recipient (address)) { + if (strstr (address, "@") == NULL) { + /* here goes searching in addressbook */ + gchar *contact_id = NULL;; + GSList *resolved_addresses = NULL; + result = resolve_address (address, &resolved_addresses, &contact_id); + + if (result) { + gint new_length; + /* replace string */ + modest_recpt_editor_replace_with_resolved_recipient (recpt_editor, + &start_iter, &end_iter, + resolved_addresses, + contact_id); + g_free (contact_id); + g_slist_foreach (resolved_addresses, (GFunc) g_free, NULL); + g_slist_free (resolved_addresses); + + /* update offset delta */ + recipients = modest_recpt_editor_get_recipients (recpt_editor); + new_length = g_utf8_strlen (recipients, -1); + offset_delta = offset_delta + new_length - last_length; + last_length = new_length; + g_message ("LENGTH %d", last_length); + } + } else { + /* this address is not valid, select it and return control to user showing banner */ + + hildon_banner_show_information (NULL, NULL, _("mcen_ib_invalid_mail")); + result = FALSE; + } + } + g_free (address); + if (result == FALSE) + break; + + current_start = g_slist_next (current_start); + current_end = g_slist_next (current_end); + } + + if (current_start == NULL) { + gtk_text_buffer_get_end_iter (buffer, &end_iter); + gtk_text_buffer_place_cursor (buffer, &end_iter); + } + + gtk_widget_destroy (banner); + g_object_unref (G_OBJECT (banner)); + modest_recpt_editor_grab_focus (recpt_editor); + + g_slist_foreach (start_indexes, (GFunc) g_free, NULL); + g_slist_foreach (end_indexes, (GFunc) g_free, NULL); + g_slist_free (start_indexes); + g_slist_free (end_indexes); + + return result; + +} + +static GList * +get_contacts_for_name (const gchar *name) +{ + EBookQuery *full_name_book_query = NULL; + GList *result; + gchar *unquoted; + + if (name == NULL) + return NULL; + + unquoted = unquote_string (name); + full_name_book_query = e_book_query_field_test (E_CONTACT_FULL_NAME, E_BOOK_QUERY_CONTAINS, unquoted); + g_free (unquoted); + + e_book_get_contacts (book, full_name_book_query, &result, NULL); + e_book_query_unref (full_name_book_query); + + return result; +} + +static GList * +select_contacts_for_name_dialog (const gchar *name) +{ + EBookQuery *full_name_book_query = NULL; + EBookView *book_view = NULL; + GList *result = NULL; + gchar *unquoted; + + unquoted = unquote_string (name); + full_name_book_query = e_book_query_field_test (E_CONTACT_FULL_NAME, E_BOOK_QUERY_CONTAINS, unquoted); + g_free (unquoted); + e_book_get_book_view (book, full_name_book_query, NULL, -1, &book_view, NULL); + e_book_query_unref (full_name_book_query); + + if (book_view) { + GtkWidget *contact_view = NULL; + GtkWidget *contact_dialog = NULL; + osso_abook_tree_model_set_book_view (OSSO_ABOOK_TREE_MODEL (contact_model), book_view); + e_book_view_start (book_view); + + contact_view = osso_abook_contact_view_new_basic (contact_model); + contact_dialog = osso_abook_select_dialog_new (OSSO_ABOOK_TREE_VIEW (contact_view)); + + if (gtk_dialog_run (GTK_DIALOG (contact_dialog)) == GTK_RESPONSE_OK) { + result = osso_abook_contact_view_get_selection (OSSO_ABOOK_CONTACT_VIEW (contact_view)); + } + e_book_view_stop (book_view); + g_object_unref (book_view); + gtk_widget_destroy (contact_dialog); + } + + return result; +} + +static gboolean +resolve_address (const gchar *address, GSList **resolved_addresses, gchar **contact_id) +{ + GList *resolved_contacts; + + contact_model = osso_abook_contact_model_new (); + if (!open_addressbook_sync ()) { + if (contact_model) { + g_object_unref (contact_model); + contact_model = NULL; + } + return FALSE; + } + + resolved_contacts = get_contacts_for_name (address); + + if (resolved_contacts == NULL) { + /* no matching contacts for the search string */ + hildon_banner_show_information (NULL, NULL, _("mcen_nc_no_matching_contacts")); + return FALSE; + } + + if (g_list_length (resolved_contacts) > 1) { + /* show a dialog to select the contact from the resolved ones */ + g_list_free (resolved_contacts); + + resolved_contacts = select_contacts_for_name_dialog (address); + } + + /* get the resolved contacts (can be no contact) */ + if (resolved_contacts) { + EContact *contact = (EContact *) resolved_contacts->data; + + *resolved_addresses = get_recipients_for_given_contact (contact); + if (*resolved_addresses) { + *contact_id = g_strdup (e_contact_get_const (contact, E_CONTACT_UID)); + } + /* TODO: free the resolved_contacts list */ + return TRUE; + } else { + /* cancelled dialog to select more than one contact or + * selected no contact */ + return FALSE; + } + +} + +static gchar * +unquote_string (const gchar *str) +{ + GString *buffer; + gchar *p; + + if (str == NULL) + return NULL; + + buffer = g_string_new_len (NULL, strlen (str)); + for (p = (gchar *) str; *p != '\0'; p = g_utf8_next_char (p)) { + if (*p == '"') { + p = g_utf8_next_char (p); + while ((*p != '\0')&&(*p != '"')) { + if (*p == '\\') { + g_string_append_unichar (buffer, g_utf8_get_char (p)); + p = g_utf8_next_char (p); + + } + g_string_append_unichar (buffer, g_utf8_get_char (p)); + p = g_utf8_next_char (p); + } + } else { + g_string_append_unichar (buffer, g_utf8_get_char (p)); + } + } + + return g_string_free (buffer, FALSE); + +} diff --git a/src/maemo/modest-msg-edit-window.c b/src/maemo/modest-msg-edit-window.c index ff31676..e3f16cc 100644 --- a/src/maemo/modest-msg-edit-window.c +++ b/src/maemo/modest-msg-edit-window.c @@ -2030,3 +2030,32 @@ is_modified (ModestMsgEditWindow *editor) return FALSE; } +gboolean +modest_msg_edit_window_check_names (ModestMsgEditWindow *window) +{ + ModestMsgEditWindowPrivate *priv = NULL; + + g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE); + priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window); + + /* check if there's no recipient added */ + if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) && + (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) && + (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) { + /* no recipient contents, then select contacts */ + modest_msg_edit_window_open_addressbook (window, NULL); + return FALSE; + } + + if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field))) + return FALSE; + if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field))) + return FALSE; + if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field))) + return FALSE; + + modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field)); + + return TRUE; + +} diff --git a/src/maemo/ui/modest-msg-edit-window-ui.xml b/src/maemo/ui/modest-msg-edit-window-ui.xml index a156210..4d27342 100644 --- a/src/maemo/ui/modest-msg-edit-window-ui.xml +++ b/src/maemo/ui/modest-msg-edit-window-ui.xml @@ -37,6 +37,7 @@ + diff --git a/src/modest-address-book.h b/src/modest-address-book.h index 9231f96..4f55ee0 100644 --- a/src/modest-address-book.h +++ b/src/modest-address-book.h @@ -54,5 +54,18 @@ modest_address_book_add_address (const gchar *address); void modest_address_book_select_addresses (ModestRecptEditor *editor); +/** + * modest_address_book_check_names: + * @editor: a #ModestRecptEditor + * + * Performs verification of addresses in a recipient editor. + * + * Returns: %TRUE if all recipients are valid or there are + * no recipients, %FALSE otherwise. + */ +gboolean +modest_address_book_check_names (ModestRecptEditor *editor); + + #endif /* __MODEST_ADDRESS_BOOK_H__ */ diff --git a/src/modest-text-utils.c b/src/modest-text-utils.c index de8b38f..2c09387 100644 --- a/src/modest-text-utils.c +++ b/src/modest-text-utils.c @@ -381,6 +381,63 @@ modest_text_utils_convert_to_html_body (const gchar *data) return g_string_free (html, FALSE); } +void +modest_text_utils_get_addresses_indexes (const gchar *addresses, GSList **start_indexes, GSList **end_indexes) +{ + gchar *current, *start, *last_blank; + gint start_offset = 0, current_offset = 0; + + g_return_if_fail (start_indexes != NULL); + g_return_if_fail (end_indexes != NULL); + + start = (gchar *) addresses; + current = start; + last_blank = start; + + while (*current != '\0') { + if ((start == current)&&((*current == ' ')||(*current == ',')||(*current == ';'))) { + start = g_utf8_next_char (start); + start_offset++; + last_blank = current; + } else if ((*current == ',')||(*current == ';')) { + gint *start_index, *end_index; + start_index = g_new0(gint, 1); + end_index = g_new0(gint, 1); + *start_index = start_offset; + *end_index = current_offset; + *start_indexes = g_slist_prepend (*start_indexes, start_index); + *end_indexes = g_slist_prepend (*end_indexes, end_index); + start = g_utf8_next_char (current); + start_offset = current_offset + 1; + last_blank = start; + } else if (*current == '"') { + current = g_utf8_next_char (current); + current_offset ++; + while ((*current != '"')&&(*current != '\0')) { + current = g_utf8_next_char (current); + current_offset ++; + } + } + + current = g_utf8_next_char (current); + current_offset ++; + } + + if (start != current) { + gint *start_index, *end_index; + start_index = g_new0(gint, 1); + end_index = g_new0(gint, 1); + *start_index = start_offset; + *end_index = current_offset; + *start_indexes = g_slist_prepend (*start_indexes, start_index); + *end_indexes = g_slist_prepend (*end_indexes, end_index); + } + + *start_indexes = g_slist_reverse (*start_indexes); + *end_indexes = g_slist_reverse (*end_indexes); + + return; +} GSList * modest_text_utils_split_addresses_list (const gchar *addresses) @@ -393,25 +450,25 @@ modest_text_utils_split_addresses_list (const gchar *addresses) last_blank = start; while (*current != '\0') { - if ((start == current)&&((*current == ' ')||(*current == ','))) { - start++; + if ((start == current)&&((*current == ' ')||(*current == ',')||(*current == ';'))) { + start = g_utf8_next_char (start); last_blank = current; - } else if (*current == ',') { + } else if ((*current == ',')||(*current == ';')) { gchar *new_address = NULL; new_address = g_strndup (start, current - last_blank); result = g_slist_prepend (result, new_address); - start = current + 1; + start = g_utf8_next_char (current); last_blank = start; } else if (*current == '\"') { if (current == start) { - current++; - start++; + current = g_utf8_next_char (current); + start = g_utf8_next_char (start); } while ((*current != '\"')&&(*current != '\0')) - current++; + current = g_utf8_next_char (current); } - current++; + current = g_utf8_next_char (current); } if (start != current) { @@ -979,42 +1036,41 @@ modest_text_utils_validate_email_address (const gchar *email_address) gboolean modest_text_utils_validate_recipient (const gchar *recipient) { - gchar *stripped; + gchar *stripped, *current; gchar *right_part; - gint i = 0; gboolean has_error = FALSE; if (modest_text_utils_validate_email_address (recipient)) return TRUE; stripped = g_strdup (recipient); stripped = g_strstrip (stripped); + current = stripped; - if (stripped[0] == '\0') { + if (*current == '\0') { g_free (stripped); return FALSE; } /* quoted string */ - if (stripped[0] == '\"') { - i = 1; + if (*current == '\"') { + current = g_utf8_next_char (current); has_error = TRUE; - for (i = 1; stripped[i] != '\0'; i++) { - if (stripped[i] == '\\') { - if (stripped[i+1] >=0) { - i++; - } else { + for (; *current != '\0'; current = g_utf8_next_char (current)) { + if (*current == '\\') { + if (current[1] <0) { has_error = TRUE; break; } - } else if (stripped[i] == '\"') { + } else if (*current == '\"') { has_error = FALSE; + current = g_utf8_next_char (current); break; } } } else { has_error = TRUE; - for (i = 0; stripped[i] != '\0'; i++) { - if (stripped[i] == ' ') { + for (current = stripped ; *current != '\0'; current = g_utf8_next_char (current)) { + if (*current == '<') { has_error = FALSE; break; } @@ -1026,9 +1082,10 @@ modest_text_utils_validate_recipient (const gchar *recipient) return FALSE; } - right_part = g_strdup (stripped + i); + right_part = g_strdup (current); g_free (stripped); right_part = g_strstrip (right_part); + if (g_str_has_prefix (right_part, "<") && g_str_has_suffix (right_part, ">")) { gchar *address; @@ -1053,8 +1110,6 @@ modest_text_utils_get_display_size (guint size) const guint MB=1024 * KB; const guint GB=1024 * MB; - g_message ("SIZE: %d",size); - if (0 < size && size < KB) return g_strdup_printf (_FM("sfil_li_size_kb"), 1); else if (KB <= size && size < 100 * KB) diff --git a/src/modest-text-utils.h b/src/modest-text-utils.h index 80e12a0..555e08c 100644 --- a/src/modest-text-utils.h +++ b/src/modest-text-utils.h @@ -279,4 +279,17 @@ gboolean modest_text_utils_validate_recipient (const gchar *recipient); **/ GSList *modest_text_utils_split_addresses_list (const gchar *addresses); +/** + * modest_text_utils_get_addresses_indexes: + * @addresses: a string + * @start_indexes: a #GSList pointer + * @end_indexes: a #GSList pointer + * + * obtains two #GSList of @addresses with the range offsets of the addresses in + * the string + * + * Returns: a GSList of strings + **/ +void modest_text_utils_get_addresses_indexes (const gchar *addresses, GSList **start_indexes, GSList **end_indexes); + #endif /* __MODEST_TEXT_UTILS_H__ */ diff --git a/src/modest-ui-actions.c b/src/modest-ui-actions.c index 748ceb2..2fd335f 100644 --- a/src/modest-ui-actions.c +++ b/src/modest-ui-actions.c @@ -1227,6 +1227,9 @@ modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window) ModestAccountMgr *account_mgr; g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window)); + + if (!modest_msg_edit_window_check_names (edit_window)) + return; data = modest_msg_edit_window_get_msg_data (edit_window); @@ -2034,6 +2037,13 @@ modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *wi modest_msg_edit_window_select_contacts (window); } +void +modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window) +{ + g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window)); + modest_msg_edit_window_check_names (window); +} + static GtkWidget* create_move_to_dialog (ModestWindow *win, diff --git a/src/modest-ui-actions.h b/src/modest-ui-actions.h index 5341e71..3723ace 100644 --- a/src/modest-ui-actions.h +++ b/src/modest-ui-actions.h @@ -53,6 +53,8 @@ void modest_ui_actions_on_add_to_contacts (GtkAction *action, ModestWindow void modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *win); +void modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *win); + void modest_ui_actions_on_new_msg (GtkAction *action, ModestWindow *win); void modest_ui_actions_on_open (GtkAction *action, ModestWindow *win); diff --git a/src/widgets/modest-msg-edit-window-ui.h b/src/widgets/modest-msg-edit-window-ui.h index c216ef8..274096f 100644 --- a/src/widgets/modest-msg-edit-window-ui.h +++ b/src/widgets/modest-msg-edit-window-ui.h @@ -68,6 +68,7 @@ static const GtkActionEntry modest_msg_edit_action_entries [] = { { "SelectAll", NULL, N_("mcen_me_viewer_selectall"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_select_all)}, { "SelectFont", NULL, N_("mcen_me_editor_font"), NULL, NULL, G_CALLBACK (modest_ui_actions_msg_edit_on_select_font)}, { "SelectContacts", NULL, N_("mcen_me_editor_selectrecipients"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_select_contacts)}, + { "CheckNames", NULL, N_("mcen_me_editor_checknames"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_check_names)}, { "CloseWindow", NULL, N_("mcen_me_inbox_close_window"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_close_window)}, { "CloseAllWindows", NULL, N_("mcen_me_inbox_close_windows"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_quit) }, diff --git a/src/widgets/modest-msg-edit-window.h b/src/widgets/modest-msg-edit-window.h index 2fad497..597cfd7 100644 --- a/src/widgets/modest-msg-edit-window.h +++ b/src/widgets/modest-msg-edit-window.h @@ -269,6 +269,17 @@ void modest_msg_edit_window_undo (ModestMsgEditWindow * */ void modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window); +/** + * modest_msg_edit_window_check_names: + * @window: a #ModestMsgEditWindow + * + * Validates all the recipients, and shows (if required) dialogs for adding contacts + * or fixing problems in specific fields. + * + * Returns: %TRUE if all fields were validated, %FALSE otherwise + */ +gboolean modest_msg_edit_window_check_names (ModestMsgEditWindow *window); + G_END_DECLS #endif /* __MODEST_MSG_EDIT_WINDOW_H__ */ diff --git a/src/widgets/modest-recpt-editor.c b/src/widgets/modest-recpt-editor.c index 6f4d1a1..643c2ac 100644 --- a/src/widgets/modest-recpt-editor.c +++ b/src/widgets/modest-recpt-editor.c @@ -99,7 +99,7 @@ static gunichar iter_previous_char (GtkTextIter *iter); static GtkTextTag *prev_iter_has_recipient (GtkTextIter *iter); /* static GtkTextTag *next_iter_has_recipient (GtkTextIter *iter); */ static void select_tag_of_iter (GtkTextIter *iter, GtkTextTag *tag); - +static gboolean quote_opened (GtkTextIter *iter); /** * modest_recpt_editor_new: @@ -231,6 +231,52 @@ modest_recpt_editor_add_resolved_recipient (ModestRecptEditor *recpt_editor, GSL } +void +modest_recpt_editor_replace_with_resolved_recipient (ModestRecptEditor *recpt_editor, + GtkTextIter *start, GtkTextIter *end, + GSList *email_list, const gchar * recipient_id) +{ + ModestRecptEditorPrivate *priv; + GtkTextBuffer *buffer; + GtkTextTag *tag; + GSList *node; + gboolean is_first_recipient = TRUE; + + g_return_if_fail (MODEST_IS_RECPT_EDITOR (recpt_editor)); + priv = MODEST_RECPT_EDITOR_GET_PRIVATE (recpt_editor); + + buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->text_view)); + g_signal_handlers_block_by_func (buffer, modest_recpt_editor_on_insert_text, recpt_editor); + + gtk_text_buffer_delete (buffer, start, end); + + tag = gtk_text_buffer_create_tag (buffer, NULL, + "underline", PANGO_UNDERLINE_SINGLE, + "wrap-mode", GTK_WRAP_NONE, + "editable", TRUE, NULL); + + g_object_set_data (G_OBJECT (tag), "recipient-tag-id", GINT_TO_POINTER (RECIPIENT_TAG_ID)); + g_object_set_data_full (G_OBJECT (tag), "recipient-id", g_strdup (recipient_id), (GDestroyNotify) g_free); + + for (node = email_list; node != NULL; node = g_slist_next (node)) { + gchar *recipient = (gchar *) node->data; + + if ((recipient) && (strlen (recipient) != 0)) { + + if (!is_first_recipient) + gtk_text_buffer_insert (buffer, start, "\n", -1); + + gtk_text_buffer_insert_with_tags (buffer, start, recipient, -1, tag, NULL); + + if (node->next != NULL) + gtk_text_buffer_insert (buffer, start, ";", -1); + is_first_recipient = FALSE; + } + } + g_signal_handlers_unblock_by_func (buffer, modest_recpt_editor_on_insert_text, recpt_editor); + +} + const gchar * modest_recpt_editor_get_recipients (ModestRecptEditor *recpt_editor) @@ -254,9 +300,10 @@ modest_recpt_editor_get_recipients (ModestRecptEditor *recpt_editor) gtk_text_buffer_get_end_iter (buffer, &end); priv->recipients = gtk_text_buffer_get_text (buffer, &start, &end, FALSE); - for (c = priv->recipients; *c == '\0'; c++) { - if (*c == '\n') + for (c = priv->recipients; *c != '\0'; c = g_utf8_next_char (c)) { + if (*c == '\n') { *c = ' '; + } } return priv->recipients; @@ -388,7 +435,6 @@ modest_recpt_editor_on_focus_in (GtkTextView *text_view, ModestRecptEditor *editor) { ModestRecptEditorPrivate *priv = MODEST_RECPT_EDITOR_GET_PRIVATE (editor); - modest_recpt_editor_move_cursor_to_end (editor); gtk_text_view_place_cursor_onscreen (GTK_TEXT_VIEW (priv->text_view)); } @@ -417,7 +463,7 @@ modest_recpt_editor_on_insert_text (GtkTextBuffer *buffer, return; prev_char = gtk_text_iter_get_char (&prev); g_signal_handlers_block_by_func (buffer, modest_recpt_editor_on_insert_text, editor); - if (prev_char == ';'||prev_char == ',') { + if ((prev_char == ';'||prev_char == ',')&&(!quote_opened(location))) { GtkTextMark *insert; gtk_text_buffer_insert (buffer, location, "\n",-1); insert = gtk_text_buffer_get_insert (buffer); @@ -502,6 +548,31 @@ select_tag_of_iter (GtkTextIter *iter, GtkTextTag *tag) gtk_text_buffer_select_range (gtk_text_iter_get_buffer (iter), &start, &end); } +static gboolean +quote_opened (GtkTextIter *iter) +{ + GtkTextIter start; + GtkTextBuffer *buffer; + gboolean opened = FALSE; + + buffer = gtk_text_iter_get_buffer (iter); + gtk_text_buffer_get_start_iter (buffer, &start); + + while (!gtk_text_iter_equal (&start, iter)) { + gunichar current_char = gtk_text_iter_get_char (&start); + if (current_char == '"') + opened = !opened; + else if (current_char == '\\') + gtk_text_iter_forward_char (&start); + if (!gtk_text_iter_equal (&start, iter)) + gtk_text_iter_forward_char (&start); + + } + return opened; + +} + + static gboolean modest_recpt_editor_on_key_press_event (GtkTextView *text_view, GdkEventKey *key, diff --git a/src/widgets/modest-recpt-editor.h b/src/widgets/modest-recpt-editor.h index f84dae8..0956a50 100644 --- a/src/widgets/modest-recpt-editor.h +++ b/src/widgets/modest-recpt-editor.h @@ -68,7 +68,13 @@ GtkWidget* modest_recpt_editor_new (void); void modest_recpt_editor_set_recipients (ModestRecptEditor *recpt_editor, const gchar *recipients); const gchar *modest_recpt_editor_get_recipients (ModestRecptEditor *repct_editor); void modest_recpt_editor_add_recipients (ModestRecptEditor *recpt_editor, const gchar *recipients); -void modest_recpt_editor_add_resolved_recipient (ModestRecptEditor *recpt_editor, GSList *email_list, const gchar * recipient_id); +void modest_recpt_editor_add_resolved_recipient (ModestRecptEditor *recpt_editor, + GSList *email_list, + const gchar * recipient_id); +void modest_recpt_editor_replace_with_resolved_recipient (ModestRecptEditor *recpt_editor, + GtkTextIter *start, GtkTextIter *end, + GSList *email_list, + const gchar *recipient_id); void modest_recpt_editor_set_field_size_group (ModestRecptEditor *recpt_editor, GtkSizeGroup *size_group); GtkTextBuffer *modest_recpt_editor_get_buffer (ModestRecptEditor *recpt_editor);