From 326ddf804e1bc2542650028660f4eb5cc82af96a Mon Sep 17 00:00:00 2001 From: Jose Dapena Paz Date: Thu, 19 Apr 2007 11:01:55 +0000 Subject: [PATCH] * src/modest-address-book.h: * Now modest_address_book_select_addresses adds the selected addresses to the ModestRecptEditor instead of returning them. * src/maemo/modest-address-book.c: * Implementation of the new ..._select_addresses method. This uses the osso abook api to retrieve addresses from device addressbook. * src/gnome/modest-address-book.c: * Updated the stub functions to conform the new API. * src/widgets/modest-msg-edit-window.h: * New method for setting priorities from ui actions. * src/widgets/modest-msg-edit-window-ui.h: * Added actions for handling priorities. * src/widgets/modest-combo-box.c: * Set the widget to ellipsize. * Make selected options expand in the available space. * src/widgets/modest-recpt.editor.[ch]: * Added "open-addressbook" signal, for attaching handlers to the addressbook button click. * Added new add_recipients method, that adds a non resolved recipient to the recipient list. * Added new add_resolved_recipient method, that gets a list of resolved recipients with an ID. It adds them underlined, and with a specific tag id. * Now recipient adders add the recipients one per line, adding \n. It also returns the recipients with the \n characters filtered. * Now it uses the ModestScrollText to support scroll line by line limited to 5 lines. * src/widgets/modest-scroll-text.c: * Fixed a bug, that moved the cursor to the start every time the embedded text view changed its contents. * Correct the size request to take into account the shadow of the scroll. * src/widgets/modest-attachments-view.[ch]: * Refactored to create a new add_attachment method. It's used to add new attachments to the list one by one, and in the existing modest_attachments_view_set_message. * src/maemo/modest-msg-edit-window.c: * Added handler for "open-addressbook" signal in To: recipients editor. It calls the addressbook corresponding method. * Added handling of priority flags (added menu to change the mail priority, priority icon to the left of the subject, and sending mails with the priority field). * Added "add attachment" button to the right of subject. No functionality yet. * Added frame to the body editor. * Use HildonScrollArea to implement full view scroll. * Added attachments view, using ModestAttachmentsView. Also added code to update the view when new images are added. * src/maemo/ui/modest-msg-edit-window-ui.xml: * Added priority handling menu options. * src/modest-ui-actions.[ch]: * (added modest_ui_action_msg_edit_on_change_priority): action to handle priority radio buttons change in editor. * (modest_ui_actions_on_send): added handling for priority field. * src/modest-account-mgr-helpers.c: * Added minor fixes to avoid warnings (GSList method called without assigning their result). * src/modest-mail-operation.[ch]: * Now ..._send_new_mail method receives also the required priority for the mail. * src/modest-main.c: * Small change to use the new priority parameter in _send_new_mail method with default value in CLI invokation. pmo-trunk-r1594 --- src/gnome/modest-address-book.c | 5 +- src/maemo/modest-address-book.c | 418 +++++++++++++++++++++++++++- src/maemo/modest-msg-edit-window.c | 121 +++++++- src/maemo/ui/modest-msg-edit-window-ui.xml | 8 + src/modest-account-mgr-helpers.c | 4 +- src/modest-address-book.h | 8 +- src/modest-mail-operation.c | 6 +- src/modest-mail-operation.h | 3 +- src/modest-main.c | 2 +- src/modest-ui-actions.c | 15 +- src/modest-ui-actions.h | 4 + src/widgets/modest-attachments-view.c | 23 +- src/widgets/modest-attachments-view.h | 2 + src/widgets/modest-combo-box.c | 3 +- src/widgets/modest-msg-edit-window-ui.h | 8 +- src/widgets/modest-msg-edit-window.h | 10 + src/widgets/modest-recpt-editor.c | 133 ++++++++- src/widgets/modest-recpt-editor.h | 6 + src/widgets/modest-scroll-text.c | 16 +- 19 files changed, 752 insertions(+), 43 deletions(-) diff --git a/src/gnome/modest-address-book.c b/src/gnome/modest-address-book.c index 4dbca7d..be2d292 100644 --- a/src/gnome/modest-address-book.c +++ b/src/gnome/modest-address-book.c @@ -37,9 +37,8 @@ modest_address_book_add_address (const gchar *address) g_message (__FUNCTION__); } -gchar * -modest_address_book_select_addresses (void) +void +modest_address_book_select_addresses (ModestRecptEditor *editor) { g_message (__FUNCTION__); - return NULL; } diff --git a/src/maemo/modest-address-book.c b/src/maemo/modest-address-book.c index 9ab25d5..b65fae3 100644 --- a/src/maemo/modest-address-book.c +++ b/src/maemo/modest-address-book.c @@ -29,15 +29,35 @@ /* modest-address-book.c */ +#include +#include #include +#include #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include static OssoABookContactModel *contact_model = NULL; static EBook *book = NULL; static EBookView * book_view = NULL; +static GSList *get_recipients_for_given_contact(EContact * contact); +static void commit_contact(EContact * contact); +static gchar *get_email_addr_from_user(const gchar * given_name); +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 void get_book_view_cb (EBook *book, EBookStatus status, EBookView *bookview, gpointer data) @@ -112,10 +132,400 @@ modest_address_book_add_address (const gchar *address) } -gchar * -modest_address_book_select_addresses (void) +void +modest_address_book_select_addresses (ModestRecptEditor *recpt_editor) +{ + GtkWidget *contact_view = NULL; + GList *contacts_list = NULL; + GtkWidget *contact_dialog; + GSList *email_addrs_per_contact = NULL; + gchar *econtact_id; + + g_return_if_fail (MODEST_IS_RECPT_EDITOR (recpt_editor)); + + contact_model = osso_abook_contact_model_new (); + if (!open_addressbook ()) { + if (contact_model) { + g_object_unref (contact_model); + contact_model = NULL; + } + return; + } + + contact_view = osso_abook_contact_selector_new_basic (contact_model); + osso_abook_contact_selector_set_minimum_selection (OSSO_ABOOK_CONTACT_SELECTOR (contact_view), 1); + + 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_widget_show (contact_dialog); + + if (gtk_dialog_run (GTK_DIALOG (contact_dialog)) == GTK_RESPONSE_OK) { + contacts_list = + osso_abook_contact_selector_get_extended_selection (OSSO_ABOOK_CONTACT_SELECTOR + (contact_view)); + } + + if (contacts_list) { + GList *node; + + for (node = contacts_list; node != NULL; node = g_list_next (node)) { + EContact *contact = (EContact *) node->data; + + email_addrs_per_contact = get_recipients_for_given_contact (contact); + if (email_addrs_per_contact) { + econtact_id = (gchar *) e_contact_get_const (contact, E_CONTACT_UID); + modest_recpt_editor_add_resolved_recipient (MODEST_RECPT_EDITOR (recpt_editor), + email_addrs_per_contact, econtact_id); + g_slist_foreach (email_addrs_per_contact, (GFunc) g_free, NULL); + g_slist_free (email_addrs_per_contact); + email_addrs_per_contact = NULL; + } + } + g_list_free (contacts_list); + } + + if (contact_view) { + g_object_unref (contact_view); + contact_view = NULL; + } + + if (contact_model) { + g_object_unref (contact_model); + contact_model = NULL; + } + + gtk_widget_destroy (contact_dialog); + +} + +/** + * This function returns the resolved recipients for a given EContact. + * If no e-mail address is defined, it launches 'Add e-mail address to contact' + * dialog to obtain one. If multiple e-mail addresses are found, it launches + * 'Select e-mail address' dialog to allow user to select one or more e-mail + * addresses for that contact. + * + * @param Contact of type #EContact + * @return List of resolved recipient strings, to be freed by calling function. + */ +static GSList *get_recipients_for_given_contact(EContact * contact) +{ + gchar *givenname = NULL; + gchar *familyname = NULL; + gchar *nickname = NULL; + gchar *emailid = NULL; + const gchar *display_name = NULL; + GList *list = NULL; + gchar *formatted_string = NULL; + gboolean email_not_present = FALSE; + GSList *formattedlist = NULL, *selected_email_addr_list = NULL, *node = NULL; + + if (!contact) { + return NULL; + } + + givenname = (gchar *) e_contact_get_const(contact, E_CONTACT_GIVEN_NAME); + familyname = (gchar *) e_contact_get_const(contact, E_CONTACT_FAMILY_NAME); + nickname = (gchar *) e_contact_get_const(contact, E_CONTACT_NICKNAME); + if (!nickname) + nickname = ""; + list = (GList *) e_contact_get(contact, E_CONTACT_EMAIL); + + if (!list) { + email_not_present = TRUE; + } + + if (list && g_list_length(list) == 1) { + if (list->data == NULL || g_utf8_strlen(list->data, -1) == 0) { + email_not_present = TRUE; + } else { + emailid = g_strstrip(g_strdup(list->data)); + if (g_utf8_strlen(emailid, -1) == 0) { + g_free(emailid); + email_not_present = TRUE; + } + } + } + + /*Launch the 'Add e-mail addr to contact' dialog if required */ + if (email_not_present) { + display_name = osso_abook_contact_get_display_name(contact); + emailid = get_email_addr_from_user(display_name); + + if (emailid) { + e_contact_set(contact, E_CONTACT_EMAIL_1, emailid); + commit_contact(contact); + } + } + + if (emailid) { + if (givenname || familyname) + formatted_string = + ui_get_formatted_email_id(givenname, familyname, emailid); + else + formatted_string = g_strdup(emailid); + formattedlist = g_slist_append(formattedlist, formatted_string); + g_free(emailid); + } + + /*Launch the 'Select e-mail address' dialog if required */ + if (g_list_length(list) > 1) { + selected_email_addr_list = select_email_addrs_for_contact(list); + for (node = selected_email_addr_list; node != NULL; node = node->next) { + if (givenname || familyname) + formatted_string = + ui_get_formatted_email_id(givenname, familyname, node->data); + else + formatted_string = g_strdup(node->data); + formattedlist = g_slist_append(formattedlist, formatted_string); + } + if (selected_email_addr_list) { + g_slist_foreach(selected_email_addr_list, (GFunc) g_free, NULL); + g_slist_free(selected_email_addr_list); + } + } + + if (list) { + g_list_foreach(list, (GFunc) g_free, NULL); + g_list_free(list); + } + + return formattedlist; +} + +/** + * This is a helper function to commit a EContact to Address_Book application. + * + * @param contact Contact of type #EContact + * @return void + */ +static void +commit_contact(EContact * contact) +{ + if (!contact || !book) + return; + + osso_abook_contact_commit(contact, FALSE, book); +} + +/** + * This is a helper function used to launch 'Add e-mail address to contact' dialog + * after showing appropriate notification, when there is no e-mail address defined + * for a selected contact. + * + * @param given_name Given name of the contact + * @param family_name Family name of the contact + * @return E-mail address string entered by user, to be freed by calling function. + */ +static gchar * +get_email_addr_from_user(const gchar * given_name) +{ + gchar *notification = NULL; + gchar *email_addr = NULL; + GtkWidget *note; + gboolean note_response; + + + notification = g_strdup_printf(_("mcen_nc_email_address_not_defined"), given_name); + + note = hildon_note_new_confirmation (NULL, notification); + note_response = gtk_dialog_run (GTK_DIALOG(note)); + gtk_widget_destroy (note); + g_free(notification); + + if (note_response == GTK_RESPONSE_OK) { + email_addr = run_add_email_addr_to_contact_dlg(given_name); + } + + return email_addr; +} + +/** +This function is used to get the formated email id with given name and sur name +in the format "GIVENNAME SURNAME ". +@param current_given_name to hold the given name +@param current_sur_name to hold the sur name +@param current_email_id to hold the email id. +@return gchar* string to be freed by calling function +*/ +static gchar * +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); + } 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); + } 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_free(email_id_str, TRUE); + email_id_str = NULL; + return (email_id); +} + +/** + * This is a helper function used to create & run 'Add e-mail address to contact' dialog. + * It allows user to enter an e-mail address, and shows appropriate infonote if the + * entered string is not a valid e-mail address. + * + * @param contact_name Full name of the contact + * @return E-mail address string entered by user, to be freed by calling function. + */ +static gchar * +run_add_email_addr_to_contact_dlg(const gchar * contact_name) { - g_message (__FUNCTION__); - return NULL; + GtkWidget *add_email_addr_to_contact_dlg = NULL; + GtkSizeGroup *size_group = NULL; + GtkWidget *cptn_cntrl = NULL; + GtkWidget *name_label = NULL; + GtkWidget *email_entry = NULL; + gint result = -1; + gchar *new_email_addr = NULL; + gboolean run_dialog = TRUE; + + add_email_addr_to_contact_dlg = + gtk_dialog_new_with_buttons(_("mcen_ti_add_email_title"), NULL, + GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, + _("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT, + _("mcen_bd_dialog_cancel"), GTK_RESPONSE_REJECT, NULL); + gtk_dialog_set_has_separator(GTK_DIALOG(add_email_addr_to_contact_dlg), FALSE); + /*Set app_name & state_save related tags to the window */ + + size_group = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); + name_label = gtk_label_new(contact_name); + gtk_misc_set_alignment(GTK_MISC(name_label), 0, 0); + cptn_cntrl = + hildon_caption_new(size_group, _("mcen_ia_add_email_name"), name_label, NULL, + HILDON_CAPTION_OPTIONAL); + gtk_box_pack_start(GTK_BOX(GTK_DIALOG(add_email_addr_to_contact_dlg)->vbox), cptn_cntrl, + FALSE, FALSE, 0); + + email_entry = gtk_entry_new(); + cptn_cntrl = + hildon_caption_new(size_group, _("mcen_fi_add_email_name"), email_entry, NULL, + HILDON_CAPTION_OPTIONAL); + hildon_gtk_entry_set_input_mode(GTK_ENTRY(email_entry), HILDON_GTK_INPUT_MODE_FULL); + gtk_box_pack_start(GTK_BOX(GTK_DIALOG(add_email_addr_to_contact_dlg)->vbox), cptn_cntrl, + TRUE, TRUE, 0); + + gtk_widget_show_all(add_email_addr_to_contact_dlg); + + while (run_dialog) { + run_dialog = FALSE; + gtk_widget_grab_focus(email_entry); + result = gtk_dialog_run(GTK_DIALOG(add_email_addr_to_contact_dlg)); + + if (result == GTK_RESPONSE_ACCEPT) { + new_email_addr = g_strdup(gtk_entry_get_text(GTK_ENTRY(email_entry))); + new_email_addr = g_strstrip(new_email_addr); + if (!modest_text_utils_validate_email_address (new_email_addr)) { + gtk_widget_grab_focus(email_entry); + gtk_editable_select_region((GtkEditable *) email_entry, 0, -1); + hildon_banner_show_information (add_email_addr_to_contact_dlg, NULL, _("mcen_ib_invalid_email")); + run_dialog = TRUE; + g_free(new_email_addr); + new_email_addr = NULL; + } + } + } + + gtk_widget_destroy(add_email_addr_to_contact_dlg); + + return new_email_addr; } +/** + * This is helper function to create & run 'Select e-mail address' dialog, used when + * multiple e-mail addresses are found for a selected contact. It allows user to select + * one or more e-mail addresses for that contact. + * + * @param email_addr_list List of e-mail addresses for that contact + * @return List of user selected e-mail addresses, to be freed by calling function. + */ +static GSList * +select_email_addrs_for_contact(GList * email_addr_list) +{ + GtkWidget *select_email_addr_dlg = NULL; + GtkWidget *view = NULL, *scrolledwindow = NULL; + GtkTreeSelection *selection = NULL; + GtkCellRenderer *renderer = NULL; + GtkTreeViewColumn *col = NULL; + GtkListStore *list_store = NULL; + GtkTreeModel *model = NULL; + GtkTreeIter iter; + GList *pathslist = NULL, *node = NULL; + gint result = -1; + gchar *email_addr = NULL; + GSList *selected_email_addr_list = NULL; + + if (!email_addr_list) + return NULL; + + select_email_addr_dlg = + gtk_dialog_new_with_buttons(_("mcen_ti_select_email_title"), + NULL, + GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, + _("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT, + _("mcen_bd_dialog_cancel"), GTK_RESPONSE_REJECT, NULL); + gtk_dialog_set_has_separator(GTK_DIALOG(select_email_addr_dlg), FALSE); + + scrolledwindow = gtk_scrolled_window_new(NULL, NULL); + gtk_box_pack_start(GTK_BOX(GTK_DIALOG(select_email_addr_dlg)->vbox), scrolledwindow, TRUE, + TRUE, 0); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledwindow), GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC); + + view = gtk_tree_view_new(); + col = gtk_tree_view_column_new(); + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_append_column(GTK_TREE_VIEW(view), col); + gtk_tree_view_column_pack_start(col, renderer, TRUE); + gtk_tree_view_column_add_attribute(col, renderer, "text", 0); + selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view)); + gtk_tree_selection_set_mode(selection, GTK_SELECTION_MULTIPLE); + gtk_container_add(GTK_CONTAINER(scrolledwindow), view); + + list_store = gtk_list_store_new(1, G_TYPE_STRING); + model = GTK_TREE_MODEL(list_store); + gtk_tree_view_set_model(GTK_TREE_VIEW(view), model); + + for (node = email_addr_list; node != NULL && node->data != NULL; node = node->next) { + email_addr = g_strstrip(g_strdup(node->data)); + gtk_list_store_append(list_store, &iter); + gtk_list_store_set(list_store, &iter, 0, email_addr, -1); + g_free(email_addr); + } + + gtk_widget_show_all(select_email_addr_dlg); + result = gtk_dialog_run(GTK_DIALOG(select_email_addr_dlg)); + + if (result == GTK_RESPONSE_ACCEPT) { + pathslist = gtk_tree_selection_get_selected_rows(selection, NULL); + for (node = pathslist; node != NULL; node = node->next) { + if (gtk_tree_model_get_iter(model, &iter, (GtkTreePath *) node->data)) { + gtk_tree_model_get(model, &iter, 0, &email_addr, -1); + selected_email_addr_list = + g_slist_append(selected_email_addr_list, g_strdup(email_addr)); + g_free(email_addr); + } + } + } + + gtk_list_store_clear(list_store); + gtk_widget_destroy(select_email_addr_dlg); + return selected_email_addr_list; +} diff --git a/src/maemo/modest-msg-edit-window.c b/src/maemo/modest-msg-edit-window.c index 8d6987b..053e2bf 100644 --- a/src/maemo/modest-msg-edit-window.c +++ b/src/maemo/modest-msg-edit-window.c @@ -43,6 +43,7 @@ #include #include #include +#include #include @@ -53,6 +54,7 @@ #include "modest-mail-operation.h" #include "modest-tny-platform-factory.h" #include "modest-tny-msg.h" +#include "modest-address-book.h" #include #include #include @@ -60,6 +62,7 @@ #include #include #include +#include #include "widgets/modest-msg-edit-window-ui.h" #ifdef MODEST_HILDON_VERSION_0 @@ -94,6 +97,8 @@ static void modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window); static gboolean modest_msg_edit_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata); +static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window, + ModestRecptEditor *editor); /* ModestWindow methods implementation */ static void modest_msg_edit_window_set_zoom (ModestWindow *window, gdouble zoom); @@ -120,9 +125,13 @@ struct _ModestMsgEditWindowPrivate { GtkWidget *cc_field; GtkWidget *bcc_field; GtkWidget *subject_field; + GtkWidget *attachments_view; + GtkWidget *priority_icon; + GtkWidget *add_attachment_button; GtkWidget *cc_caption; GtkWidget *bcc_caption; + GtkWidget *attachments_caption; GtkTextBuffer *text_buffer; @@ -137,6 +146,8 @@ struct _ModestMsgEditWindowPrivate { gint last_cid; GList *attachments; + TnyHeaderFlags priority_flags; + gdouble zoom_level; }; @@ -213,6 +224,8 @@ modest_msg_edit_window_init (ModestMsgEditWindow *obj) priv->cc_caption = NULL; priv->bcc_caption = NULL; + + priv->priority_flags = 0; } @@ -309,6 +322,10 @@ init_window (ModestMsgEditWindow *obj) ModestMsgEditWindowPrivate *priv; ModestPairList *protos; GtkSizeGroup *size_group; + GtkWidget *frame; + GtkWidget *scroll_area; + GtkWidget *subject_box; + GtkWidget *attachment_icon; priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj); @@ -321,7 +338,20 @@ init_window (ModestMsgEditWindow *obj) priv->to_field = modest_recpt_editor_new (); priv->cc_field = modest_recpt_editor_new (); priv->bcc_field = modest_recpt_editor_new (); + subject_box = gtk_hbox_new (FALSE, 0); + priv->priority_icon = gtk_image_new (); + gtk_box_pack_start (GTK_BOX (subject_box), priv->priority_icon, FALSE, FALSE, 0); priv->subject_field = gtk_entry_new_with_max_length (SUBJECT_MAX_LENGTH); + g_object_set (G_OBJECT (priv->subject_field), "hildon-input-mode", HILDON_GTK_INPUT_MODE_FULL, NULL); + gtk_box_pack_start (GTK_BOX (subject_box), priv->subject_field, TRUE, TRUE, 0); + priv->add_attachment_button = gtk_button_new (); + gtk_button_set_relief (GTK_BUTTON (priv->add_attachment_button), GTK_RELIEF_NONE); + gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE); + gtk_button_set_alignment (GTK_BUTTON (priv->add_attachment_button), 1.0, 1.0); + attachment_icon = gtk_image_new_from_icon_name ("qgn_list_gene_attacpap", GTK_ICON_SIZE_BUTTON); + gtk_container_add (GTK_CONTAINER (priv->add_attachment_button), attachment_icon); + gtk_box_pack_start (GTK_BOX (subject_box), priv->add_attachment_button, FALSE, FALSE, 0); + priv->attachments_view = modest_attachments_view_new (NULL); priv->header_box = gtk_vbox_new (FALSE, 0); @@ -329,7 +359,8 @@ init_window (ModestMsgEditWindow *obj) to_caption = hildon_caption_new (size_group, _("To:"), priv->to_field, NULL, 0); priv->cc_caption = hildon_caption_new (size_group, _("Cc:"), priv->cc_field, NULL, 0); priv->bcc_caption = hildon_caption_new (size_group, _("Bcc:"), priv->bcc_field, NULL, 0); - subject_caption = hildon_caption_new (size_group, _("Subject:"), priv->subject_field, NULL, 0); + subject_caption = hildon_caption_new (size_group, _("Subject:"), subject_box, NULL, 0); + priv->attachments_caption = hildon_caption_new (size_group, _("Attachments:"), priv->attachments_view, NULL, 0); g_object_unref (size_group); size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); @@ -337,6 +368,7 @@ init_window (ModestMsgEditWindow *obj) modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), size_group); modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), size_group); gtk_size_group_add_widget (size_group, priv->subject_field); + gtk_size_group_add_widget (size_group, priv->attachments_view); g_object_unref (size_group); gtk_box_pack_start (GTK_BOX (priv->header_box), from_caption, FALSE, FALSE, 0); @@ -344,6 +376,8 @@ init_window (ModestMsgEditWindow *obj) gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0); + gtk_widget_set_no_show_all (priv->attachments_caption, TRUE); priv->msg_body = wp_text_view_new (); @@ -353,6 +387,7 @@ init_window (ModestMsgEditWindow *obj) wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE); /* gtk_text_buffer_set_can_paste_rich_text (priv->text_buffer, TRUE); */ wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE); + g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes", G_CALLBACK (text_buffer_refresh_attributes), obj); g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set", @@ -360,6 +395,8 @@ init_window (ModestMsgEditWindow *obj) g_signal_connect (G_OBJECT (obj), "window-state-event", G_CALLBACK (modest_msg_edit_window_window_state_event), NULL); + g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook", + G_CALLBACK (modest_msg_edit_window_open_addressbook), obj); priv->scroll = gtk_scrolled_window_new (NULL, NULL); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); @@ -368,7 +405,8 @@ init_window (ModestMsgEditWindow *obj) main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING); gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0); - gtk_box_pack_start (GTK_BOX(main_vbox), priv->msg_body, TRUE, TRUE, 0); + frame = gtk_frame_new (NULL); + gtk_box_pack_start (GTK_BOX(main_vbox), frame, TRUE, TRUE, 0); gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (priv->scroll), main_vbox); gtk_container_set_focus_vadjustment (GTK_CONTAINER (main_vbox), gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll))); @@ -380,6 +418,10 @@ init_window (ModestMsgEditWindow *obj) gtk_widget_hide (priv->bcc_field); gtk_container_add (GTK_CONTAINER(obj), priv->scroll); + scroll_area = hildon_scroll_area_new (priv->scroll, priv->msg_body); + gtk_container_add (GTK_CONTAINER (frame), scroll_area); + gtk_container_set_focus_vadjustment (GTK_CONTAINER (scroll_area), + gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll))); } @@ -476,7 +518,8 @@ set_msg (ModestMsgEditWindow *self, TnyMsg *msg) wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &fmt); } - if (!to) { + /* Set the default focus depending on having already a To: field or not */ + if ((!to)||(*to == '\0')) { gtk_widget_grab_focus (priv->to_field); } else { gtk_widget_grab_focus (priv->msg_body); @@ -486,7 +529,10 @@ set_msg (ModestMsgEditWindow *self, TnyMsg *msg) value that comes from msg <- not sure, should it be allowed? */ - /* TODO: set attachments */ + /* Add attachments to the view */ + modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg); + if (priv->attachments == NULL) + gtk_widget_hide_all (priv->attachments_caption); } static void @@ -700,6 +746,12 @@ modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name) 100, G_CALLBACK (modest_ui_actions_on_change_zoom), obj); + gtk_action_group_add_radio_actions (action_group, + modest_msg_edit_priority_action_entries, + G_N_ELEMENTS (modest_msg_edit_priority_action_entries), + 0, + G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority), + obj); gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0); g_object_unref (action_group); @@ -799,6 +851,7 @@ modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window) data->plain_body = (gchar *) gtk_text_buffer_get_text (priv->text_buffer, &b, &e, FALSE); data->html_body = get_formatted_data (edit_window); data->attachments = priv->attachments; + data->priority_flags = priv->priority_flags; return data; } @@ -1177,6 +1230,10 @@ modest_msg_edit_window_insert_image (ModestMsgEditWindow *window) gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark); wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (image_part)), pixbuf); priv->attachments = g_list_prepend (priv->attachments, image_part); + modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), + image_part); + gtk_widget_set_no_show_all (priv->attachments_caption, FALSE); + gtk_widget_show_all (priv->attachments_caption); } else if (image_file_id == -1) { close (image_file_id); } @@ -1408,6 +1465,31 @@ modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window, } static void +modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window, + ModestRecptEditor *editor) +{ + ModestMsgEditWindowPrivate *priv; + + g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window)); + g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor))); + priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window); + + if (editor == NULL) { + GtkWidget *view_focus; + view_focus = gtk_window_get_focus (GTK_WINDOW (window)); + + if (gtk_widget_get_parent (view_focus) && + MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (view_focus))) { + editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (view_focus)); + } else { + editor = MODEST_RECPT_EDITOR (priv->to_field); + } + } + + modest_address_book_select_addresses (editor); + +} +static void modest_msg_edit_window_show_toolbar (ModestWindow *self, gboolean show_toolbar) { @@ -1424,3 +1506,34 @@ modest_msg_edit_window_show_toolbar (ModestWindow *self, else gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar)); } + +void +modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window, + TnyHeaderFlags priority_flags) +{ + ModestMsgEditWindowPrivate *priv; + + g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window)); + + priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window); + priority_flags = priority_flags & (TNY_HEADER_FLAG_HIGH_PRIORITY); + + if (priv->priority_flags != priority_flags) { + + priv->priority_flags = priority_flags; + + switch (priority_flags) { + case TNY_HEADER_FLAG_HIGH_PRIORITY: + gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_high", GTK_ICON_SIZE_MENU); + gtk_widget_show (priv->priority_icon); + break; + case TNY_HEADER_FLAG_LOW_PRIORITY: + gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_low", GTK_ICON_SIZE_MENU); + gtk_widget_show (priv->priority_icon); + break; + default: + gtk_widget_hide (priv->priority_icon); + break; + } + } +} diff --git a/src/maemo/ui/modest-msg-edit-window-ui.xml b/src/maemo/ui/modest-msg-edit-window-ui.xml index c28028f..8987bc1 100644 --- a/src/maemo/ui/modest-msg-edit-window-ui.xml +++ b/src/maemo/ui/modest-msg-edit-window-ui.xml @@ -68,6 +68,14 @@ + + + + + + + + diff --git a/src/modest-account-mgr-helpers.c b/src/modest-account-mgr-helpers.c index fbbbc51..8a7e320 100644 --- a/src/modest-account-mgr-helpers.c +++ b/src/modest-account-mgr-helpers.c @@ -134,7 +134,7 @@ gboolean modest_account_mgr_set_connection_specific_smtp (ModestAccountMgr *self /* The server account is in the item after the connection name: */ GSList *list_connection = g_slist_append (list, (gpointer)connection_name); - g_slist_append (list_connection, (gpointer)server_account_name); + list_connection = g_slist_append (list_connection, (gpointer)server_account_name); /* Reset the changed list: */ modest_account_mgr_set_list (self, account_name, @@ -171,7 +171,7 @@ gboolean modest_account_mgr_remove_connection_specific_smtp (ModestAccountMgr *s if (list_connection) { /* remove both items: */ GSList *temp = g_slist_delete_link(list_connection, list_connection); - g_slist_delete_link(temp, g_slist_next(temp)); + temp = g_slist_delete_link(temp, g_slist_next(temp)); } /* Reset the changed list: */ diff --git a/src/modest-address-book.h b/src/modest-address-book.h index 75a1a9a..9231f96 100644 --- a/src/modest-address-book.h +++ b/src/modest-address-book.h @@ -33,6 +33,7 @@ #define __MODEST_ADDRESS_BOOK_H__ #include +#include /** * modest_address_book_add_address: @@ -47,12 +48,11 @@ modest_address_book_add_address (const gchar *address); * modest_address_book_select_addresses: * * Shows a dialog to select some addresses from the - * address book. + * address book. It adds them to the recipient editor * - * Returns: a string with the addresses */ -gchar * -modest_address_book_select_addresses (void); +void +modest_address_book_select_addresses (ModestRecptEditor *editor); #endif /* __MODEST_ADDRESS_BOOK_H__ */ diff --git a/src/modest-mail-operation.c b/src/modest-mail-operation.c index b496141..2bfd135 100644 --- a/src/modest-mail-operation.c +++ b/src/modest-mail-operation.c @@ -229,7 +229,8 @@ modest_mail_operation_send_new_mail (ModestMailOperation *self, const gchar *cc, const gchar *bcc, const gchar *subject, const gchar *plain_body, const gchar *html_body, - const GList *attachments_list) + const GList *attachments_list, + TnyHeaderFlags priority_flags) { TnyMsg *new_msg; ModestMailOperationPrivate *priv = NULL; @@ -258,6 +259,9 @@ modest_mail_operation_send_new_mail (ModestMailOperation *self, return; } + /* TODO: add priority handling. It's received in the priority_flags operator, and + it should have effect in the sending operation */ + /* Call mail operation */ modest_mail_operation_send_mail (self, transport_account, new_msg); diff --git a/src/modest-mail-operation.h b/src/modest-mail-operation.h index a2c318d..b08bf16 100644 --- a/src/modest-mail-operation.h +++ b/src/modest-mail-operation.h @@ -123,7 +123,8 @@ void modest_mail_operation_send_new_mail (ModestMailOperation *self, const gchar *subject, const gchar *plain_body, const gchar *html_body, - const GList *attachments_list); + const GList *attachments_list, + TnyHeaderFlags priority_flags); /** * modest_mail_operation_update_account: diff --git a/src/modest-main.c b/src/modest-main.c index 2021504..3da5ae3 100644 --- a/src/modest-main.c +++ b/src/modest-main.c @@ -286,7 +286,7 @@ send_mail (const gchar* account_name, modest_mail_operation_send_new_mail (mail_operation, account, from_string, mailto, cc, bcc, subject, body, NULL, - NULL); + NULL, 0); if (modest_mail_operation_get_status (mail_operation) == MODEST_MAIL_OPERATION_STATUS_FAILED) { retval = MODEST_ERR_SEND; diff --git a/src/modest-ui-actions.c b/src/modest-ui-actions.c index ceb90be..f8889fe 100644 --- a/src/modest-ui-actions.c +++ b/src/modest-ui-actions.c @@ -1058,7 +1058,8 @@ modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window) data->subject, data->plain_body, data->html_body, - data->attachments); + data->attachments, + data->priority_flags); /* Frees */ g_free (from); g_free (account_name); @@ -1507,6 +1508,18 @@ modest_ui_actions_on_change_zoom (GtkRadioAction *action, } } +void modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action, + GtkRadioAction *selected, + ModestWindow *window) +{ + TnyHeaderFlags flags; + g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window)); + + flags = gtk_radio_action_get_current_value (selected); + modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags); +} + + void modest_ui_actions_on_zoom_plus (GtkAction *action, ModestWindow *window) diff --git a/src/modest-ui-actions.h b/src/modest-ui-actions.h index 6ac3ba6..6333cf8 100644 --- a/src/modest-ui-actions.h +++ b/src/modest-ui-actions.h @@ -208,6 +208,10 @@ void modest_ui_actions_on_change_zoom (GtkRadioAction *action, GtkRadioAction *selected, ModestWindow *window); +void modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action, + GtkRadioAction *selected, + ModestWindow *window); + /** * modest_ui_actions_on_toggle_toolbar: * @toggle: diff --git a/src/widgets/modest-attachments-view.c b/src/widgets/modest-attachments-view.c index d07635e..7c15c79 100644 --- a/src/widgets/modest-attachments-view.c +++ b/src/widgets/modest-attachments-view.c @@ -101,7 +101,6 @@ modest_attachments_view_set_message (ModestAttachmentsView *attachments_view, Tn ModestAttachmentsViewPriv *priv = MODEST_ATTACHMENTS_VIEW_GET_PRIVATE (attachments_view); TnyList *parts; TnyIterator *iter; - gboolean has_first = FALSE; if (priv->msg) g_object_unref (priv->msg); @@ -125,12 +124,7 @@ modest_attachments_view_set_message (ModestAttachmentsView *attachments_view, Tn part = TNY_MIME_PART (tny_iterator_get_current (iter)); if (tny_mime_part_is_attachment (part)) { - GtkWidget *att_view = NULL; - att_view = modest_attachment_view_new (part); - gtk_box_pack_end (GTK_BOX (attachments_view), att_view, FALSE, FALSE, 0); - gtk_widget_show_all (att_view); - g_signal_connect (G_OBJECT (att_view), "activate", G_CALLBACK (activate_attachment), (gpointer) attachments_view); - has_first = TRUE; + modest_attachments_view_add_attachment (attachments_view, part); } g_object_unref (part); tny_iterator_next (iter); @@ -140,6 +134,21 @@ modest_attachments_view_set_message (ModestAttachmentsView *attachments_view, Tn } +void +modest_attachments_view_add_attachment (ModestAttachmentsView *attachments_view, TnyMimePart *part) +{ + GtkWidget *att_view = NULL; + + g_return_if_fail (MODEST_IS_ATTACHMENTS_VIEW (attachments_view)); + g_return_if_fail (TNY_IS_MIME_PART (part)); + g_return_if_fail (tny_mime_part_is_attachment (part)); + + att_view = modest_attachment_view_new (part); + gtk_box_pack_end (GTK_BOX (attachments_view), att_view, FALSE, FALSE, 0); + gtk_widget_show_all (att_view); + g_signal_connect (G_OBJECT (att_view), "activate", G_CALLBACK (activate_attachment), (gpointer) attachments_view); +} + static void modest_attachments_view_instance_init (GTypeInstance *instance, gpointer g_class) { diff --git a/src/widgets/modest-attachments-view.h b/src/widgets/modest-attachments-view.h index c4472e1..5555901 100644 --- a/src/widgets/modest-attachments-view.h +++ b/src/widgets/modest-attachments-view.h @@ -63,6 +63,8 @@ GType modest_attachments_view_get_type (void); GtkWidget* modest_attachments_view_new (TnyMsg *msg); void modest_attachments_view_set_message (ModestAttachmentsView *attachments_view, TnyMsg *msg); +void modest_attachments_view_add_attachment (ModestAttachmentsView *attachments_view, TnyMimePart *part); + G_END_DECLS diff --git a/src/widgets/modest-combo-box.c b/src/widgets/modest-combo-box.c index 3e0fc0e..e44aef1 100644 --- a/src/widgets/modest-combo-box.c +++ b/src/widgets/modest-combo-box.c @@ -168,8 +168,9 @@ modest_combo_box_new (const ModestPairList *pairs, GEqualFunc id_equal_func) gtk_cell_layout_clear (GTK_CELL_LAYOUT(obj)); renderer = gtk_cell_renderer_text_new (); + g_object_set (G_OBJECT (renderer), "ellipsize", PANGO_ELLIPSIZE_END, NULL); gtk_cell_layout_pack_start (GTK_CELL_LAYOUT(obj), - renderer, FALSE); + renderer, TRUE); gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT(obj), renderer, "text", COLUMN_DISPLAY_NAME, NULL); diff --git a/src/widgets/modest-msg-edit-window-ui.h b/src/widgets/modest-msg-edit-window-ui.h index 3e299b3..98a7d4d 100644 --- a/src/widgets/modest-msg-edit-window-ui.h +++ b/src/widgets/modest-msg-edit-window-ui.h @@ -47,6 +47,8 @@ static const GtkActionEntry modest_msg_edit_action_entries [] = { { "Alignment", NULL, N_("_Alignment") }, { "Attachments", NULL, N_("Attachments") }, { "Zoom", NULL, N_("Zoom") }, + { "MessagePriority", NULL, N_("Message priority") }, + { "Tools", NULL, N_("Tools") }, /* ACTIONS */ { "ActionsSend", MODEST_STOCK_MAIL_SEND, N_("Send"), NULL, N_("Send a message"), G_CALLBACK (modest_ui_actions_on_send) }, @@ -93,7 +95,11 @@ static const GtkRadioActionEntry modest_msg_edit_zoom_action_entries [] = { { "Zoom200", NULL, N_("mcen_me_viewer_200"), NULL, NULL, 200 } }; - +static const GtkRadioActionEntry modest_msg_edit_priority_action_entries [] = { + { "MessagePriorityHigh", NULL, N_("High"), NULL, NULL, TNY_HEADER_FLAG_HIGH_PRIORITY }, + { "MessagePriorityNormal", NULL, N_("Normal"), NULL, NULL, TNY_HEADER_FLAG_NORMAL_PRIORITY }, + { "MessagePriorityLow", NULL, N_("Low"), NULL, NULL, TNY_HEADER_FLAG_LOW_PRIORITY }, +}; G_END_DECLS #endif /* __MODEST_MSG_EDIT_WINDOW_UI_H__ */ diff --git a/src/widgets/modest-msg-edit-window.h b/src/widgets/modest-msg-edit-window.h index d5942ef..e8a9a64 100644 --- a/src/widgets/modest-msg-edit-window.h +++ b/src/widgets/modest-msg-edit-window.h @@ -73,6 +73,7 @@ typedef enum { typedef struct { gchar *from, *to, *cc, *bcc, *subject, *plain_body, *html_body; GList *attachments; + TnyHeaderFlags priority_flags; } MsgData; typedef struct { @@ -222,6 +223,15 @@ void modest_msg_edit_window_show_bcc (ModestMsg */ void modest_msg_edit_window_toggle_fullscreen (ModestMsgEditWindow *window); +/** + * modest_msg_edit_window_set_priority_flags: + * @window: a #ModestMsgEditWindow + * @priority_flags: a #TnyHeaderFlags with priority information + * + * Updates the icon and priority flag to send. + */ +void modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window, + TnyHeaderFlags priority_flags); G_END_DECLS diff --git a/src/widgets/modest-recpt-editor.c b/src/widgets/modest-recpt-editor.c index 6e66489..5449a57 100644 --- a/src/widgets/modest-recpt-editor.c +++ b/src/widgets/modest-recpt-editor.c @@ -38,13 +38,19 @@ #include #include +#include +#include +#include static GObjectClass *parent_class = NULL; -/* /\* signals *\/ */ -/* enum { */ -/* LAST_SIGNAL */ -/* }; */ +#define RECIPIENT_TAG_ID "recpt-id" + +/* signals */ +enum { + OPEN_ADDRESSBOOK_SIGNAL, + LAST_SIGNAL +}; typedef struct _ModestRecptEditorPrivate ModestRecptEditorPrivate; @@ -59,13 +65,17 @@ struct _ModestRecptEditorPrivate #define MODEST_RECPT_EDITOR_GET_PRIVATE(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), MODEST_TYPE_RECPT_EDITOR, ModestRecptEditorPrivate)) -/* static guint signals[LAST_SIGNAL] = {0}; */ +static guint signals[LAST_SIGNAL] = {0}; /* static functions: GObject */ static void modest_recpt_editor_instance_init (GTypeInstance *instance, gpointer g_class); static void modest_recpt_editor_finalize (GObject *object); static void modest_recpt_editor_class_init (ModestRecptEditorClass *klass); +/* widget events */ +static void modest_recpt_editor_on_abook_clicked (GtkButton *button, + ModestRecptEditor *editor); + /** * modest_recpt_editor_new: * @@ -99,12 +109,90 @@ modest_recpt_editor_set_recipients (ModestRecptEditor *recpt_editor, const gchar } +void +modest_recpt_editor_add_recipients (ModestRecptEditor *recpt_editor, const gchar *recipients) +{ + ModestRecptEditorPrivate *priv; + GtkTextBuffer *buffer = NULL; + GtkTextIter iter; + gchar * string_to_add; + + g_return_if_fail (MODEST_IS_RECPT_EDITOR (recpt_editor)); + priv = MODEST_RECPT_EDITOR_GET_PRIVATE (recpt_editor); + + if (recipients == NULL) + return; + + buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->text_view)); + + if (gtk_text_buffer_get_char_count (buffer) > 0) { + string_to_add = g_strconcat (";\n", recipients, NULL); + } else { + string_to_add = g_strdup (recipients); + } + + gtk_text_buffer_get_end_iter (buffer, &iter); + + gtk_text_buffer_insert (buffer, &iter, recipients, -1); + if (GTK_WIDGET_REALIZED (recpt_editor)) + gtk_widget_queue_resize (GTK_WIDGET (recpt_editor)); + +} + +void +modest_recpt_editor_add_resolved_recipient (ModestRecptEditor *recpt_editor, GSList *email_list, const gchar * recipient_id) +{ + ModestRecptEditorPrivate *priv; + GtkTextBuffer *buffer = NULL; + GtkTextIter start, end, iter; + GtkTextTag *tag = NULL; + gboolean is_first_recipient = TRUE; + GSList *node; + + 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)); + + gtk_text_buffer_get_bounds (buffer, &start, &end); + if (!gtk_text_iter_equal (&start, &end)) + gtk_text_buffer_insert (buffer, &end, ";\n", -1); + + gtk_text_buffer_get_end_iter (buffer, &iter); + + 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 *) email_list->data; + + if ((recipient) && (strlen (recipient) != 0)) { + + if (!is_first_recipient) { + gtk_text_buffer_insert (buffer, &iter, ";\n", -1); + } else { + is_first_recipient = FALSE; + } + + gtk_text_buffer_insert_with_tags (buffer, &iter, recipient, -1, tag, NULL); + } + } + +} + + const gchar * modest_recpt_editor_get_recipients (ModestRecptEditor *recpt_editor) { ModestRecptEditorPrivate *priv; GtkTextBuffer *buffer = NULL; GtkTextIter start, end; + gchar *c; g_return_val_if_fail (MODEST_IS_RECPT_EDITOR (recpt_editor), NULL); priv = MODEST_RECPT_EDITOR_GET_PRIVATE (recpt_editor); @@ -120,6 +208,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') + *c = ' '; + } return priv->recipients; @@ -141,19 +233,25 @@ modest_recpt_editor_instance_init (GTypeInstance *instance, gpointer g_class) gtk_container_add (GTK_CONTAINER (priv->abook_button), abook_icon); priv->text_view = gtk_text_view_new (); - priv->scrolled_window = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->scrolled_window), GTK_POLICY_NEVER, GTK_POLICY_NEVER); + priv->scrolled_window = modest_scroll_text_new (GTK_TEXT_VIEW (priv->text_view), 5); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->scrolled_window), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (priv->scrolled_window), GTK_SHADOW_IN); - gtk_container_add (GTK_CONTAINER (priv->scrolled_window), priv->text_view); +/* gtk_container_add (GTK_CONTAINER (priv->scrolled_window), priv->text_view); */ gtk_box_pack_start (GTK_BOX (instance), priv->scrolled_window, TRUE, TRUE, 0); +/* gtk_box_pack_start (GTK_BOX (instance), priv->text_view, TRUE, TRUE, 0); */ gtk_box_pack_end (GTK_BOX (instance), priv->abook_button, FALSE, FALSE, 0); gtk_text_view_set_accepts_tab (GTK_TEXT_VIEW (priv->text_view), FALSE); gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (priv->text_view), TRUE); gtk_text_view_set_editable (GTK_TEXT_VIEW (priv->text_view), TRUE); + gtk_text_view_set_justification (GTK_TEXT_VIEW (priv->text_view), GTK_JUSTIFY_LEFT); - gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->text_view), GTK_WRAP_WORD_CHAR); + gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->text_view), GTK_WRAP_CHAR); + + gtk_widget_set_size_request (priv->text_view, 75, -1); + + g_signal_connect (G_OBJECT (priv->abook_button), "clicked", G_CALLBACK (modest_recpt_editor_on_abook_clicked), instance); return; } @@ -171,6 +269,14 @@ modest_recpt_editor_set_field_size_group (ModestRecptEditor *recpt_editor, GtkSi } static void +modest_recpt_editor_on_abook_clicked (GtkButton *button, ModestRecptEditor *editor) +{ + g_return_if_fail (MODEST_IS_RECPT_EDITOR (editor)); + + g_signal_emit_by_name (G_OBJECT (editor), "open-addressbook"); +} + +static void modest_recpt_editor_finalize (GObject *object) { (*parent_class->finalize) (object); @@ -192,6 +298,15 @@ modest_recpt_editor_class_init (ModestRecptEditorClass *klass) g_type_class_add_private (object_class, sizeof (ModestRecptEditorPrivate)); + signals[OPEN_ADDRESSBOOK_SIGNAL] = + g_signal_new ("open-addressbook", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (ModestRecptEditorClass, open_addressbook), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + return; } diff --git a/src/widgets/modest-recpt-editor.h b/src/widgets/modest-recpt-editor.h index 989dc65..7ef9d04 100644 --- a/src/widgets/modest-recpt-editor.h +++ b/src/widgets/modest-recpt-editor.h @@ -54,6 +54,10 @@ struct _ModestRecptEditor struct _ModestRecptEditorClass { GtkHBoxClass parent_class; + + /* signals */ + + void (*open_addressbook) (ModestRecptEditor *editor); }; GType modest_recpt_editor_get_type (void); @@ -62,6 +66,8 @@ 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_set_field_size_group (ModestRecptEditor *recpt_editor, GtkSizeGroup *size_group); diff --git a/src/widgets/modest-scroll-text.c b/src/widgets/modest-scroll-text.c index e24520b..25f6426 100644 --- a/src/widgets/modest-scroll-text.c +++ b/src/widgets/modest-scroll-text.c @@ -80,12 +80,17 @@ size_request (GtkWidget *widget, guint line_limit; GdkRectangle iter_rectangle; GtkAdjustment *adj = NULL; + GtkTextMark *insert_mark; + GtkTextIter insert_iter; text_view = modest_scroll_text_get_text_view (MODEST_SCROLL_TEXT (widget)); line_limit = priv->line_limit; buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text_view)); + insert_mark = gtk_text_buffer_get_insert (buffer); + gtk_text_buffer_get_iter_at_mark (buffer, &insert_iter, insert_mark); + /* get the first line and the height of the line */ gtk_text_buffer_get_start_iter (buffer, &iter); gtk_text_view_get_iter_location (GTK_TEXT_VIEW (text_view), &iter, &iter_rectangle); @@ -97,24 +102,27 @@ size_request (GtkWidget *widget, } /* Put again the cursor in the first character. Also scroll to first line */ - gtk_text_buffer_get_start_iter (buffer, &iter); - gtk_text_buffer_place_cursor (buffer, &iter); + gtk_text_buffer_place_cursor (buffer, &insert_iter); gtk_text_view_place_cursor_onscreen (GTK_TEXT_VIEW (text_view)); /* Change the adjustment properties for one line per step behavior */ adj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (widget)); if (adj != NULL) { - g_object_set (G_OBJECT (adj), "page-increment", (gdouble) iter_rectangle.height, "step-increment", (gdouble) iter_rectangle.height, NULL); + g_object_set (G_OBJECT (adj), "page-increment", (gdouble) iter_rectangle.height + 1, "step-increment", (gdouble) iter_rectangle.height + 1, NULL); gtk_adjustment_changed (adj); } /* Set the requisition height to the get the limit of lines or less */ if (line > 0) { - requisition->height = iter_rectangle.height * MAX (line, line_limit); + requisition->height = iter_rectangle.height * MIN (line + 1, line_limit); } else { requisition->height = iter_rectangle.height; } + if (gtk_scrolled_window_get_shadow_type (GTK_SCROLLED_WINDOW (widget)) != GTK_SHADOW_NONE) { + requisition->height += GTK_WIDGET (widget)->style->ythickness * 2; + } + priv->line_height = iter_rectangle.height; } -- 1.7.9.5