1 /* Copyright (c) 2006, Nokia Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of the Nokia Corporation nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include <glib/gi18n.h>
33 #include <glib/gstdio.h>
35 #include <tny-account-store.h>
36 #include <tny-fs-stream.h>
37 #include <tny-vfs-stream.h>
38 #include <tny-camel-mem-stream.h>
39 #include <modest-account-protocol.h>
43 #include <modest-account-mgr.h>
44 #include <modest-account-mgr-helpers.h>
46 #include <widgets/modest-msg-edit-window.h>
47 #include <widgets/modest-recpt-editor.h>
48 #include <widgets/modest-attachments-view.h>
50 #include <modest-runtime.h>
52 #include "modest-platform.h"
53 #include "modest-icon-names.h"
54 #include "modest-widget-memory.h"
55 #include "modest-window-priv.h"
56 #include "modest-mail-operation.h"
57 #include "modest-tny-platform-factory.h"
58 #include "modest-tny-msg.h"
59 #include "modest-tny-folder.h"
60 #include "modest-tny-account.h"
61 #include "modest-address-book.h"
62 #include "modest-text-utils.h"
63 #include <tny-simple-list.h>
64 #include <modest-wp-text-view.h>
65 #include <wptextbuffer.h>
66 #include <modest-scrollable.h>
67 #include <modest-isearch-toolbar.h>
68 #include "modest-msg-edit-window-ui-dimming.h"
70 #include "widgets/modest-msg-edit-window-ui.h"
71 #include <libgnomevfs/gnome-vfs-mime.h>
72 #include <modest-utils.h>
73 #include <modest-ui-constants.h>
74 #include <modest-toolkit-utils.h>
76 #ifdef MODEST_USE_CALENDAR_WIDGETS
77 #include <calendar-ui-widgets.h>
79 #ifdef MODEST_TOOLKIT_HILDON2
80 #include <hildon/hildon.h>
81 #include "modest-maemo-utils.h"
82 #include "modest-hildon-includes.h"
83 #include "modest-color-button.h"
86 #define DEFAULT_MAIN_VBOX_SPACING 0
87 #define SUBJECT_MAX_LENGTH 1000
88 #define IMAGE_MAX_WIDTH 560
89 #ifdef MODEST_TOOLKIT_HILDON2
90 #define DEFAULT_SIZE_BUTTON_FONT_FAMILY "Sans"
91 #define DEFAULT_FONT_SCALE 1.5
92 #define DEFAULT_FONT_SIZE 3
93 #define DEFAULT_FONT 2
95 #define DEFAULT_SIZE_BUTTON_FONT_FAMILY "Sans"
96 #define DEFAULT_FONT_SCALE 1.0
97 #define DEFAULT_FONT_SIZE 2
98 #define DEFAULT_FONT 2
100 #define ATTACHMENT_BUTTON_WIDTH 118
101 #define MAX_FROM_VALUE 36
102 #define MAX_BODY_LENGTH 128*1024
103 #define MAX_BODY_LINES 2048
105 static gboolean is_wp_text_buffer_started = FALSE;
107 static void modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass);
108 static void modest_msg_edit_window_init (ModestMsgEditWindow *obj);
109 static void modest_msg_edit_window_finalize (GObject *obj);
111 static gboolean msg_body_focus (GtkWidget *focus, GdkEventFocus *event, gpointer userdata);
112 static void body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
113 static void recpt_field_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
115 static void text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window);
116 static void text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window);
117 static void text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window);
118 static void text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
119 GtkTextIter *start, GtkTextIter *end,
121 static void text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id);
122 static void body_insert_text (GtkTextBuffer *buffer,
123 GtkTextIter *location,
126 ModestMsgEditWindow *window);
127 static void subject_field_changed (GtkEditable *editable, ModestMsgEditWindow *window);
128 static void subject_field_insert_text (GtkEditable *editable,
130 gint new_text_length,
132 ModestMsgEditWindow *window);
133 static void modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
135 #ifdef MODEST_TOOLKIT_HILDON2
136 static void font_face_clicked (GtkToolButton *button,
137 ModestMsgEditWindow *window);
139 static void modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
142 static void modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
144 static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
145 ModestRecptEditor *editor);
146 static void modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
147 ModestMsgEditWindow *window);
149 /* ModestWindow methods implementation */
150 static void modest_msg_edit_window_disconnect_signals (ModestWindow *window);
151 static void modest_msg_edit_window_show_toolbar (ModestWindow *window,
152 gboolean show_toolbar);
153 static void modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
155 ModestMsgEditWindow *window);
156 static void modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window);
157 static void subject_field_move_cursor (GtkEntry *entry,
158 GtkMovementStep step,
162 static void update_window_title (ModestMsgEditWindow *window);
165 static void modest_msg_edit_window_isearch_toolbar_search (GtkWidget *widget,
166 ModestMsgEditWindow *window);
167 static void modest_msg_edit_window_isearch_toolbar_close (GtkWidget *widget,
168 ModestMsgEditWindow *window);
169 static gboolean gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
171 GtkTextIter *match_start,
172 GtkTextIter *match_end);
174 static void remove_tags (WPTextBuffer *buffer);
176 static void on_account_removed (TnyAccountStore *account_store,
180 static void init_window (ModestMsgEditWindow *obj);
182 gboolean scroll_drag_timeout (gpointer userdata);
183 static void correct_scroll (ModestMsgEditWindow *w);
184 static void correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused);
185 static void text_buffer_end_user_action (GtkTextBuffer *buffer,
186 ModestMsgEditWindow *userdata);
187 static void text_buffer_mark_set (GtkTextBuffer *buffer,
190 ModestMsgEditWindow *userdata);
191 static void on_message_settings (GtkAction *action,
192 ModestMsgEditWindow *window);
193 static void setup_menu (ModestMsgEditWindow *self);
195 static void from_field_changed (GtkWidget *button,
196 ModestMsgEditWindow *self);
197 static void font_size_clicked (GtkToolButton *button,
198 ModestMsgEditWindow *window);
199 static void update_signature (ModestMsgEditWindow *self,
200 const gchar *old_account,
201 const gchar *new_account);
202 static void update_branding (ModestMsgEditWindow *self,
203 const gchar *new_account);
204 static GtkWidget *_create_addressbook_box (GtkSizeGroup *title_size_group, GtkSizeGroup *value_size_group,
205 const gchar *label, GtkWidget *control);
206 static void max_chars_banner_unref (ModestMsgEditWindow *self, GObject *old_ref);
207 static void DEBUG_BUFFER (WPTextBuffer *buffer)
211 g_debug ("BEGIN BUFFER OF SIZE %d", gtk_text_buffer_get_char_count (GTK_TEXT_BUFFER (buffer)));
213 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &iter);
214 while (!gtk_text_iter_is_end (&iter)) {
215 GString *output = g_string_new ("");
216 GSList *toggled_tags;
219 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
220 g_string_append_printf (output, "%d: CLOSED [ ", gtk_text_iter_get_offset (&iter));
221 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
222 GtkTextTag *tag = (GtkTextTag *) node->data;
224 g_object_get (G_OBJECT (tag), "name", &name, NULL);
225 output = g_string_append (output, name);
226 g_string_append (output, " ");
228 output = g_string_append (output, "] OPENED [ ");
229 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
230 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
231 GtkTextTag *tag = (GtkTextTag *) node->data;
233 g_object_get (G_OBJECT (tag), "name", &name, NULL);
234 output = g_string_append (output, name);
235 g_string_append (output, " ");
237 output = g_string_append (output, "]\n");
238 g_debug ("%s", output->str);
239 g_string_free (output, TRUE);
240 gtk_text_iter_forward_to_tag_toggle (&iter, NULL);
242 g_debug ("END BUFFER");
246 static const GtkActionEntry hildon2_msg_edit_action_entries [] = {
247 { "MessageSettings", NULL, N_("mcen_me_message_settings"), NULL, NULL, G_CALLBACK (on_message_settings)},
251 /* static gboolean */
252 /* on_key_pressed (GtkWidget *self, */
253 /* GdkEventKey *event, */
254 /* gpointer user_data); */
256 /* list my signals */
263 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
264 struct _ModestMsgEditWindowPrivate {
266 GtkWidget *header_box;
268 ModestPairList *from_field_protos;
269 GtkWidget *from_field;
270 gchar *last_from_account;
271 gchar *original_account_name;
276 gchar *original_mailbox;
280 GtkWidget *bcc_field;
281 GtkWidget *subject_field;
282 GtkWidget *attachments_view;
283 GtkWidget *priority_icon;
284 GtkWidget *subject_box;
285 GtkWidget *send_button;
287 GtkWidget *cc_caption;
288 GtkWidget *bcc_caption;
289 gboolean update_caption_visibility;
290 GtkWidget *attachments_caption;
292 GtkTextBuffer *text_buffer;
294 GtkWidget *font_size_toolitem;
295 GtkWidget *font_face_toolitem;
296 GtkWidget *font_color_button;
297 GtkWidget *font_color_toolitem;
298 GSList *font_items_group;
299 GtkTreeModel *faces_model;
300 gint current_face_index;
301 GtkWidget *font_tool_button_label;
302 GtkTreeModel *sizes_model;
303 gint current_size_index;
304 GtkWidget *size_tool_button_label;
306 GtkWidget *isearch_toolbar;
309 GtkWidget *font_dialog;
311 GtkWidget *scrollable;
312 guint correct_scroll_idle;
313 guint scroll_drag_timeout_id;
317 TnyList *attachments;
322 TnyHeaderFlags priority_flags;
324 gboolean can_undo, can_redo;
325 gulong clipboard_change_handler_id;
326 gulong default_clipboard_change_handler_id;
327 gulong account_removed_handler_id;
328 guint clipboard_owner_idle;
329 gchar *clipboard_text;
338 GtkWidget *cc_button;
339 GtkWidget *bcc_button;
341 GtkWidget *max_chars_banner;
343 GtkWidget *brand_icon;
344 GtkWidget *brand_label;
345 GtkWidget *brand_container;
348 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
349 MODEST_TYPE_MSG_EDIT_WINDOW, \
350 ModestMsgEditWindowPrivate))
352 static GtkWindowClass *parent_class = NULL;
354 /* uncomment the following if you have defined any signals */
355 /* static guint signals[LAST_SIGNAL] = {0}; */
358 modest_msg_edit_window_get_type (void)
360 static GType my_type = 0;
362 static const GTypeInfo my_info = {
363 sizeof(ModestMsgEditWindowClass),
364 NULL, /* base init */
365 NULL, /* base finalize */
366 (GClassInitFunc) modest_msg_edit_window_class_init,
367 NULL, /* class finalize */
368 NULL, /* class data */
369 sizeof(ModestMsgEditWindow),
371 (GInstanceInitFunc) modest_msg_edit_window_init,
374 my_type = g_type_register_static (
375 #ifdef MODEST_TOOLKIT_HILDON2
376 MODEST_TYPE_HILDON2_WINDOW,
378 MODEST_TYPE_SHELL_WINDOW,
380 "ModestMsgEditWindow",
388 save_state (ModestWindow *self)
390 modest_widget_memory_save (modest_runtime_get_conf(),
391 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
396 restore_settings (ModestMsgEditWindow *self)
398 ModestConf *conf = NULL;
400 conf = modest_runtime_get_conf ();
402 /* Dim at start clipboard actions */
403 modest_widget_memory_restore (conf, G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
408 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
410 GObjectClass *gobject_class;
411 ModestWindowClass *modest_window_class;
412 gobject_class = (GObjectClass*) klass;
413 modest_window_class = (ModestWindowClass*) klass;
415 parent_class = g_type_class_peek_parent (klass);
416 gobject_class->finalize = modest_msg_edit_window_finalize;
418 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
419 modest_window_class->save_state_func = save_state;
420 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
422 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
426 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
428 ModestMsgEditWindowPrivate *priv;
429 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
431 priv->msg_body = NULL;
432 priv->from_field = NULL;
433 priv->to_field = NULL;
434 priv->cc_field = NULL;
435 priv->bcc_field = NULL;
436 priv->subject_field = NULL;
437 priv->attachments = TNY_LIST (tny_simple_list_new ());
438 priv->images = TNY_LIST (tny_simple_list_new ());
439 priv->images_size = 0;
440 priv->images_count = 0;
443 priv->cc_caption = NULL;
444 priv->bcc_caption = NULL;
445 priv->update_caption_visibility = FALSE;
447 priv->priority_flags = 0;
449 priv->isearch_toolbar = NULL;
450 priv->last_search = NULL;
452 priv->draft_msg = NULL;
453 priv->outbox_msg = NULL;
454 priv->msg_uid = NULL;
456 priv->can_undo = FALSE;
457 priv->can_redo = FALSE;
458 priv->clipboard_change_handler_id = 0;
459 priv->default_clipboard_change_handler_id = 0;
460 priv->account_removed_handler_id = 0;
461 priv->clipboard_owner_idle = 0;
462 priv->clipboard_text = NULL;
465 priv->scroll_drag_timeout_id = 0;
466 priv->correct_scroll_idle = 0;
467 priv->last_upper = 0.0;
469 priv->font_dialog = NULL;
470 priv->app_menu = NULL;
472 priv->references = NULL;
473 priv->in_reply_to = NULL;
474 priv->max_chars_banner = NULL;
476 if (!is_wp_text_buffer_started) {
477 is_wp_text_buffer_started = TRUE;
478 wp_text_buffer_library_init ();
482 #ifdef MODEST_TOOLKIT_HILDON2
483 hildon_program_add_window (hildon_program_get_instance(),
489 multimailbox_get_default_mailbox (const gchar *account_name)
491 gchar *transport_account;
492 gchar *result = NULL;
494 transport_account = modest_account_mgr_get_server_account_name (modest_runtime_get_account_mgr (),
496 TNY_ACCOUNT_TYPE_TRANSPORT);
497 if (transport_account) {
499 ModestProtocolRegistry *registry;
501 registry = modest_runtime_get_protocol_registry ();
503 proto = modest_account_mgr_get_string (modest_runtime_get_account_mgr (), transport_account,
504 MODEST_ACCOUNT_PROTO, TRUE);
506 ModestProtocol *protocol =
507 modest_protocol_registry_get_protocol_by_name (registry,
508 MODEST_PROTOCOL_REGISTRY_TRANSPORT_PROTOCOLS,
510 if (MODEST_ACCOUNT_PROTOCOL (protocol)) {
511 ModestPairList *pair_list;
513 pair_list = modest_account_protocol_get_from_list (MODEST_ACCOUNT_PROTOCOL (protocol),
516 ModestPair *pair = (ModestPair *) pair_list->data;
517 result = g_strdup ((const gchar *) pair->first);
518 modest_pair_list_free (pair_list);
529 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
531 static ModestPairList*
532 get_transports (void)
534 GSList *transports = NULL;
536 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
537 GSList *accounts = modest_account_mgr_account_names (account_mgr,
538 TRUE /* only enabled accounts. */);
540 GSList *cursor = accounts;
542 gchar *account_name = cursor->data;
545 gchar *transport_account;
546 gboolean multi_mailbox = FALSE;
547 ModestProtocol *protocol = NULL;
549 if (modest_account_mgr_account_is_multimailbox (account_mgr, account_name, &protocol)) {
551 transport_account = modest_account_mgr_get_server_account_name
552 (modest_runtime_get_account_mgr (),
554 TNY_ACCOUNT_TYPE_TRANSPORT);
555 if (protocol && MODEST_IS_ACCOUNT_PROTOCOL (protocol)) {
556 ModestPairList *pair_list;
557 pair_list = modest_account_protocol_get_from_list (MODEST_ACCOUNT_PROTOCOL (protocol),
560 transports = g_slist_concat (transports, pair_list);
561 multi_mailbox = TRUE;
566 if (!multi_mailbox) {
567 gchar *from_string = NULL;
569 from_string = modest_account_mgr_get_from_string (account_mgr,
571 if (from_string && account_name) {
572 gchar *name = account_name;
573 ModestPair *pair = modest_pair_new ((gpointer) name,
574 (gpointer) from_string , TRUE);
575 transports = g_slist_prepend (transports, pair);
580 cursor = cursor->next;
582 g_slist_free (accounts); /* only free the accounts, not the elements,
583 * because they are used in the pairlist */
587 static void window_focus (GtkWindow *window,
591 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
595 scroll_drag_timeout (gpointer userdata)
597 ModestMsgEditWindow *win = (ModestMsgEditWindow *) userdata;
598 ModestMsgEditWindowPrivate *priv;
600 /* It could happen that the window was already closed */
601 if (!GTK_WIDGET_VISIBLE (win))
604 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(win);
606 correct_scroll_without_drag_check (win, TRUE);
608 priv->scroll_drag_timeout_id = 0;
614 correct_scroll_without_drag_check_idle (gpointer userdata)
616 ModestMsgEditWindow *w = (ModestMsgEditWindow *) userdata;
617 ModestMsgEditWindowPrivate *priv;
619 GdkRectangle rectangle;
620 gint offset_min, offset_max;
624 /* It could happen that the window was already closed */
625 if (!GTK_WIDGET_VISIBLE (w))
628 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
630 insert = gtk_text_buffer_get_insert (priv->text_buffer);
631 gtk_text_buffer_get_iter_at_mark (priv->text_buffer, &iter, insert);
633 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &iter, &rectangle);
634 offset_min = priv->msg_body->allocation.y + rectangle.y;
635 offset_max = offset_min + rectangle.height;
637 vadj = modest_scrollable_get_vadjustment (MODEST_SCROLLABLE (priv->scrollable));
638 offset_min = MAX (offset_min - 48, 0);
639 offset_max = MIN (offset_max + 48, vadj->upper);
641 gtk_adjustment_clamp_page (vadj, (gdouble) offset_min, (gdouble) offset_max);
643 priv->correct_scroll_idle = 0;
648 correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused)
650 ModestMsgEditWindowPrivate *priv;
652 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
654 if (only_if_focused && !gtk_widget_is_focus (priv->msg_body))
657 if (priv->correct_scroll_idle > 0) {
661 priv->correct_scroll_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
662 (GSourceFunc) correct_scroll_without_drag_check_idle,
668 correct_scroll (ModestMsgEditWindow *w)
670 ModestMsgEditWindowPrivate *priv;
672 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
673 if (gtk_grab_get_current () == priv->msg_body) {
674 if (priv->scroll_drag_timeout_id == 0) {
675 priv->scroll_drag_timeout_id = g_timeout_add_full (G_PRIORITY_DEFAULT,
677 (GSourceFunc) scroll_drag_timeout,
684 correct_scroll_without_drag_check (w, TRUE);
688 text_buffer_end_user_action (GtkTextBuffer *buffer,
689 ModestMsgEditWindow *userdata)
692 correct_scroll (userdata);
696 text_buffer_mark_set (GtkTextBuffer *buffer,
699 ModestMsgEditWindow *userdata)
701 gtk_text_buffer_begin_user_action (buffer);
702 gtk_text_buffer_end_user_action (buffer);
706 cut_clipboard_check (GtkTextView *text_view,
709 GtkTextBuffer *buffer;
711 buffer = gtk_text_view_get_buffer (text_view);
712 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
713 g_signal_stop_emission_by_name ((gpointer )text_view, "cut-clipboard");
718 copy_clipboard_check (GtkTextView *text_view,
721 GtkTextBuffer *buffer;
723 buffer = gtk_text_view_get_buffer (text_view);
724 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
725 g_signal_stop_emission_by_name ((gpointer )text_view, "copy-clipboard");
730 attachment_deleted (ModestAttachmentsView *attachments_view,
733 modest_msg_edit_window_remove_attachments (MODEST_MSG_EDIT_WINDOW (user_data),
738 body_size_request (GtkWidget *body,
742 /* Make sure the body always get at least 70 pixels */
743 if (req->height < 70)
748 connect_signals (ModestMsgEditWindow *obj)
750 ModestMsgEditWindowPrivate *priv;
752 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
754 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
755 G_CALLBACK (text_buffer_refresh_attributes), obj);
756 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
757 G_CALLBACK (text_buffer_can_undo), obj);
758 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
759 G_CALLBACK (text_buffer_can_redo), obj);
760 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
761 G_CALLBACK (body_changed), obj);
762 g_signal_connect (G_OBJECT (priv->text_buffer), "insert-text",
763 G_CALLBACK (body_insert_text), obj);
764 g_signal_connect (G_OBJECT (priv->text_buffer), "modified-changed",
765 G_CALLBACK (body_changed), obj);
766 g_signal_connect (G_OBJECT (priv->text_buffer), "end-user-action",
767 G_CALLBACK (text_buffer_end_user_action), obj);
768 g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
769 G_CALLBACK (text_buffer_mark_set), obj);
770 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
771 G_CALLBACK (text_buffer_apply_tag), obj);
772 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
773 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
774 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
775 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
776 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
777 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
779 g_signal_connect (G_OBJECT (priv->send_button), "clicked",
780 G_CALLBACK (modest_ui_actions_on_send), obj);
782 if (GTK_IS_COMBO_BOX (priv->from_field)) {
783 g_signal_connect (G_OBJECT (priv->from_field), "changed",
784 G_CALLBACK (from_field_changed), obj);
786 g_signal_connect (G_OBJECT (priv->from_field), "value-changed",
787 G_CALLBACK (from_field_changed), obj);
790 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
791 G_CALLBACK (msg_body_focus), obj);
792 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
793 G_CALLBACK (msg_body_focus), obj);
794 g_signal_connect (G_OBJECT (priv->msg_body), "size-request",
795 G_CALLBACK (body_size_request), obj);
796 g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
797 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
798 "changed", G_CALLBACK (recpt_field_changed), obj);
799 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
800 "changed", G_CALLBACK (recpt_field_changed), obj);
801 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
802 "changed", G_CALLBACK (recpt_field_changed), obj);
803 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
804 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
805 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
807 g_signal_connect (G_OBJECT (priv->isearch_toolbar), "isearch-search",
808 G_CALLBACK (modest_msg_edit_window_isearch_toolbar_search), obj);
809 g_signal_connect (G_OBJECT (priv->isearch_toolbar), "isearch-close",
810 G_CALLBACK (modest_msg_edit_window_isearch_toolbar_close), obj);
812 priv->clipboard_change_handler_id =
813 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
814 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
815 priv->default_clipboard_change_handler_id =
816 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
817 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
819 g_signal_connect (G_OBJECT (priv->msg_body), "cut-clipboard", G_CALLBACK (cut_clipboard_check), NULL);
820 g_signal_connect (G_OBJECT (priv->msg_body), "copy-clipboard", G_CALLBACK (copy_clipboard_check), NULL);
821 g_signal_connect (G_OBJECT (priv->attachments_view), "delete", G_CALLBACK (attachment_deleted), obj);
825 init_wp_text_view_style ()
827 static gboolean initialized = FALSE;
830 gtk_rc_parse_string ("class \"WPTextView\" style \"fremantle-textview\"");
836 init_window (ModestMsgEditWindow *obj)
838 GtkWidget *to_caption, *subject_caption;
839 GtkWidget *main_vbox;
840 ModestMsgEditWindowPrivate *priv;
841 GtkActionGroup *action_group;
842 ModestWindowPrivate *parent_priv;
843 GError *error = NULL;
845 GtkSizeGroup *title_size_group;
846 GtkSizeGroup *value_size_group;
847 GtkWidget *window_box;
848 GtkWidget *window_align;
849 #if (GTK_MINOR_VERSION >= 10)
850 GdkAtom deserialize_type;
852 GtkWidget *from_send_hbox;
853 GtkWidget *send_icon;
854 GtkWidget *attachments_label;
855 GtkWidget *branding_box;
856 GtkWidget *from_caption;
858 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
859 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
861 parent_priv->ui_manager = gtk_ui_manager_new();
862 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
863 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
865 /* Add common actions */
866 gtk_action_group_add_actions (action_group,
867 modest_msg_edit_action_entries,
868 G_N_ELEMENTS (modest_msg_edit_action_entries),
870 gtk_action_group_add_actions (action_group,
871 hildon2_msg_edit_action_entries,
872 G_N_ELEMENTS (hildon2_msg_edit_action_entries),
874 gtk_action_group_add_toggle_actions (action_group,
875 modest_msg_edit_toggle_action_entries,
876 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
878 gtk_action_group_add_radio_actions (action_group,
879 modest_msg_edit_alignment_radio_action_entries,
880 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
882 G_CALLBACK (modest_ui_actions_on_change_justify),
884 gtk_action_group_add_radio_actions (action_group,
885 modest_msg_edit_priority_action_entries,
886 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
888 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
890 gtk_action_group_add_radio_actions (action_group,
891 modest_msg_edit_file_format_action_entries,
892 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
893 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
894 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
896 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
897 g_object_unref (action_group);
899 /* Load the UI definition */
900 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
903 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
904 g_clear_error (&error);
907 parent_priv->menubar = NULL;
909 title_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
910 value_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
912 /* Note: This ModestPairList* must exist for as long as the picker
913 * that uses it, because the ModestSelectorPicker uses the ID opaquely,
914 * so it can't know how to manage its memory. */
915 priv->from_field = modest_toolkit_factory_create_selector (modest_runtime_get_toolkit_factory (),
917 modest_selector_set_value_max_chars (priv->from_field, MAX_FROM_VALUE);
918 if (GTK_IS_COMBO_BOX (priv->from_field)) {
919 from_caption = modest_toolkit_utils_create_captioned (title_size_group, NULL,
920 _("mail_va_from"), FALSE,
922 gtk_widget_show (from_caption);
924 #ifdef MODEST_TOOLKIT_HILDON2
925 modest_toolkit_utils_set_hbutton_layout (title_size_group, NULL,
926 _("mail_va_from"), priv->from_field);
927 hildon_button_set_alignment (HILDON_BUTTON (priv->from_field), 0.0, 0.5, 1.0, 1.0);
928 hildon_button_set_title_alignment (HILDON_BUTTON (priv->from_field), 0.0, 0.5);
929 hildon_button_set_value_alignment (HILDON_BUTTON (priv->from_field), 1.0, 0.5);
930 from_caption = priv->from_field;
934 priv->to_field = modest_recpt_editor_new ();
935 priv->cc_field = modest_recpt_editor_new ();
936 priv->bcc_field = modest_recpt_editor_new ();
937 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->to_field), FALSE);
938 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->cc_field), FALSE);
939 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->bcc_field), FALSE);
940 priv->subject_box = gtk_hbox_new (FALSE, MODEST_MARGIN_NONE);
941 priv->priority_icon = gtk_image_new ();
942 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->priority_icon, FALSE, FALSE, 0);
943 priv->subject_field = modest_toolkit_factory_create_entry (modest_runtime_get_toolkit_factory ());
944 gtk_entry_set_max_length (GTK_ENTRY (priv->subject_field) ,SUBJECT_MAX_LENGTH);
945 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
946 modest_entry_set_hint (priv->subject_field, _("mail_va_no_subject"));
948 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
949 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
951 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->subject_field, TRUE, TRUE, 0);
952 priv->attachments_view = modest_attachments_view_new (NULL);
953 modest_attachments_view_set_style (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
954 MODEST_ATTACHMENTS_VIEW_STYLE_NO_FOCUS);
956 priv->header_box = gtk_vbox_new (FALSE, 0);
958 to_caption = _create_addressbook_box
959 (title_size_group, value_size_group,
960 _("mail_va_to"), priv->to_field);
961 priv->cc_caption = _create_addressbook_box
962 (title_size_group, value_size_group,
963 _("mail_va_cc"), priv->cc_field);
964 priv->bcc_caption = _create_addressbook_box
965 (title_size_group, value_size_group,
966 _("mail_va_hotfix1"), priv->bcc_field);
967 subject_caption = modest_toolkit_utils_create_captioned (title_size_group, value_size_group,
968 _("mail_va_subject"), FALSE, priv->subject_box);
969 priv->attachments_caption = modest_toolkit_utils_create_captioned_with_size_type (NULL, NULL,
970 _("mail_va_attachment"),
972 priv->attachments_view,
973 #ifdef MODEST_TOOLKIT_HILDON2
974 HILDON_SIZE_AUTO_WIDTH |
975 HILDON_SIZE_AUTO_HEIGHT
980 attachments_label = modest_toolkit_utils_captioned_get_label_widget (priv->attachments_caption);
982 hildon_gtk_widget_set_theme_size (attachments_label, HILDON_SIZE_AUTO_HEIGHT);
986 #ifdef MODEST_TOOLKIT_HILDON2
987 priv->send_button = hildon_gtk_button_new (HILDON_SIZE_FINGER_HEIGHT);
988 send_icon = gtk_image_new_from_icon_name (MODEST_TOOLBAR_ICON_MAIL_SEND, HILDON_ICON_SIZE_FINGER);
990 priv->send_button = gtk_button_new ();
991 send_icon = gtk_image_new_from_icon_name (MODEST_TOOLBAR_ICON_MAIL_SEND, GTK_ICON_SIZE_BUTTON);
993 gtk_container_add (GTK_CONTAINER (priv->send_button), send_icon);
994 gtk_widget_set_size_request (GTK_WIDGET (priv->send_button), 148, -1);
996 g_object_unref (title_size_group);
997 g_object_unref (value_size_group);
999 priv->brand_icon = gtk_image_new ();
1000 gtk_misc_set_alignment (GTK_MISC (priv->brand_icon), 0.5, 0.5);
1001 priv->brand_label = gtk_label_new (NULL);
1002 #ifdef MODEST_TOOLKIT_HILDON2
1003 hildon_helper_set_logical_font (priv->brand_label, "SmallSystemFont");
1005 gtk_misc_set_alignment (GTK_MISC (priv->brand_label), 0.0, 0.5);
1006 gtk_widget_set_no_show_all (priv->brand_icon, TRUE);
1007 gtk_widget_set_no_show_all (priv->brand_label, TRUE);
1009 from_send_hbox = gtk_hbox_new (FALSE, 0);
1010 gtk_box_pack_start (GTK_BOX (from_send_hbox), from_caption, TRUE, TRUE, 0);
1011 gtk_box_pack_start (GTK_BOX (from_send_hbox), priv->send_button, FALSE, FALSE, 0);
1013 branding_box = gtk_hbox_new (FALSE, MODEST_MARGIN_DEFAULT);
1014 gtk_widget_show (branding_box);
1015 gtk_box_pack_start (GTK_BOX (branding_box), priv->brand_label, FALSE, FALSE, 0);
1016 gtk_box_pack_start (GTK_BOX (branding_box), priv->brand_icon, FALSE, FALSE, 0);
1018 priv->brand_container = gtk_alignment_new (0.0, 0.5, 0.0, 1.0);
1019 gtk_alignment_set_padding (GTK_ALIGNMENT (priv->brand_container), 0, 0, MODEST_MARGIN_DOUBLE, 0);
1020 gtk_container_add (GTK_CONTAINER (priv->brand_container), branding_box);
1021 gtk_widget_set_no_show_all (priv->brand_container, TRUE);
1024 gtk_box_pack_start (GTK_BOX (priv->header_box), from_send_hbox, FALSE, FALSE, 0);
1025 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
1026 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
1027 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
1028 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
1029 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
1030 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->brand_container, FALSE, FALSE, 0);
1031 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
1033 init_wp_text_view_style ();
1035 priv->msg_body = modest_wp_text_view_new ();
1038 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
1039 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1040 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
1041 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1042 #if (GTK_MINOR_VERSION >= 10)
1043 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
1044 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
1046 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
1047 deserialize_type, TRUE);
1049 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1051 priv->isearch_toolbar = modest_toolkit_factory_create_isearch_toolbar (modest_runtime_get_toolkit_factory (),
1053 gtk_widget_set_no_show_all (priv->isearch_toolbar, TRUE);
1055 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
1057 priv->scrollable = modest_toolkit_factory_create_scrollable (modest_runtime_get_toolkit_factory ());
1059 g_object_set (G_OBJECT (priv->scrollable), "horizontal-policy", GTK_POLICY_NEVER, NULL);
1061 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
1062 window_align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
1063 gtk_alignment_set_padding (GTK_ALIGNMENT (window_align), 0, 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DEFAULT);
1065 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
1066 gtk_box_pack_start (GTK_BOX(main_vbox), priv->msg_body, TRUE, TRUE, 0);
1067 gtk_container_add (GTK_CONTAINER (window_align), main_vbox);
1069 modest_scrollable_add_with_viewport (MODEST_SCROLLABLE (priv->scrollable), window_align);
1070 gtk_widget_show_all (GTK_WIDGET(priv->scrollable));
1072 window_box = gtk_vbox_new (FALSE, 0);
1073 gtk_container_add (GTK_CONTAINER(obj), window_box);
1075 gtk_box_pack_start (GTK_BOX (window_box), priv->scrollable, TRUE, TRUE, 0);
1080 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
1082 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1084 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
1085 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
1086 priv->clipboard_change_handler_id))
1087 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
1088 priv->clipboard_change_handler_id);
1089 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
1090 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
1091 priv->default_clipboard_change_handler_id))
1092 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
1093 priv->default_clipboard_change_handler_id);
1095 if (priv->account_removed_handler_id &&
1096 g_signal_handler_is_connected (modest_runtime_get_account_store (),
1097 priv->account_removed_handler_id))
1098 g_signal_handler_disconnect(modest_runtime_get_account_store (),
1099 priv->account_removed_handler_id);
1103 modest_msg_edit_window_finalize (GObject *obj)
1105 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1107 if (priv->max_chars_banner) {
1108 g_object_weak_unref (G_OBJECT (priv->max_chars_banner), (GWeakNotify) max_chars_banner_unref, obj);
1109 priv->max_chars_banner = FALSE;
1112 /* Sanity check: shouldn't be needed, the window mgr should
1113 call this function before */
1114 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
1116 if (priv->font_dialog != NULL) {
1117 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
1120 if (priv->clipboard_text != NULL) {
1121 g_free (priv->clipboard_text);
1122 priv->clipboard_text = NULL;
1125 if (priv->draft_msg != NULL) {
1126 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
1127 if (TNY_IS_HEADER (header)) {
1128 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1129 modest_window_mgr_unregister_header (mgr, header);
1131 g_object_unref (priv->draft_msg);
1132 priv->draft_msg = NULL;
1134 if (priv->outbox_msg != NULL) {
1135 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
1136 if (TNY_IS_HEADER (header)) {
1137 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1138 modest_window_mgr_unregister_header (mgr, header);
1140 g_object_unref (priv->outbox_msg);
1141 priv->outbox_msg = NULL;
1143 if (priv->correct_scroll_idle > 0) {
1144 g_source_remove (priv->correct_scroll_idle);
1145 priv->correct_scroll_idle = 0;
1147 if (priv->scroll_drag_timeout_id > 0) {
1148 g_source_remove (priv->scroll_drag_timeout_id);
1149 priv->scroll_drag_timeout_id = 0;
1151 if (priv->clipboard_owner_idle > 0) {
1152 g_source_remove (priv->clipboard_owner_idle);
1153 priv->clipboard_owner_idle = 0;
1155 if (priv->original_account_name)
1156 g_free (priv->original_account_name);
1157 if (priv->original_mailbox)
1158 g_free (priv->original_mailbox);
1159 g_free (priv->msg_uid);
1160 g_free (priv->last_search);
1161 g_slist_free (priv->font_items_group);
1162 g_free (priv->references);
1163 g_free (priv->in_reply_to);
1164 g_object_unref (priv->attachments);
1165 g_object_unref (priv->images);
1167 /* This had to stay alive for as long as the picker that used it: */
1168 modest_pair_list_free (priv->from_field_protos);
1170 G_OBJECT_CLASS(parent_class)->finalize (obj);
1174 pixbuf_size_prepared (GdkPixbufLoader *loader,
1177 ModestMsgEditWindow *self)
1179 gint new_height, new_width;
1182 new_height = height;
1186 if (width > IMAGE_MAX_WIDTH) {
1187 new_height = height * IMAGE_MAX_WIDTH / width;
1188 new_width = IMAGE_MAX_WIDTH;
1191 gdk_pixbuf_loader_set_size (loader, new_width, new_height);
1195 pixbuf_from_stream (TnyStream *stream,
1196 const gchar *mime_type,
1197 guint64 *stream_size,
1198 ModestMsgEditWindow *self)
1200 GdkPixbufLoader *loader;
1203 GError *error = NULL;
1207 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
1209 if (loader == NULL) {
1214 g_signal_connect (G_OBJECT (loader), "size-prepared", G_CALLBACK (pixbuf_size_prepared), self);
1216 modest_window_show_progress (MODEST_WINDOW (self), TRUE);
1218 tny_stream_reset (TNY_STREAM (stream));
1219 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
1220 unsigned char read_buffer[128];
1222 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
1224 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
1227 /* Allow some UI responsiveness */
1228 while (gtk_events_pending ())
1229 gtk_main_iteration ();
1231 modest_window_show_progress (MODEST_WINDOW (self), FALSE);
1233 gdk_pixbuf_loader_close (loader, &error);
1236 g_error_free (error);
1237 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1239 g_object_ref (pixbuf);
1240 g_object_unref (loader);
1245 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1246 GdkPixbuf *new_pixbuf;
1248 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1249 gdk_pixbuf_get_width (pixbuf);
1250 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1251 g_object_unref (pixbuf);
1252 pixbuf = new_pixbuf;
1256 *stream_size = size;
1262 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1264 ModestMsgEditWindowPrivate *priv;
1267 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1269 g_object_ref (self);
1270 for (iter = tny_list_create_iterator (attachments);
1271 !tny_iterator_is_done (iter);
1272 tny_iterator_next (iter)) {
1273 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1274 const gchar *cid = tny_mime_part_get_content_id (part);
1275 const gchar *mime_type = tny_mime_part_get_content_type (part);
1276 if ((cid != NULL)&&(mime_type != NULL)) {
1277 guint64 stream_size;
1278 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1279 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, self);
1282 g_object_unref (stream);
1284 if (pixbuf != NULL) {
1285 priv->images_count ++;
1286 priv->images_size += stream_size;
1287 #ifndef MODEST_HAVE_LIBWPEDITOR_PLUS
1288 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1290 g_object_unref (pixbuf);
1293 g_object_unref (part);
1295 g_object_unref (iter);
1296 g_object_unref (self);
1300 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1302 TnyMimePart *parent = NULL;
1303 const gchar *content_type = NULL;
1304 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1306 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1308 if (content_type && !g_ascii_strcasecmp (content_type, "multipart/related")) {
1309 parent = g_object_ref (msg);
1310 } else if (content_type && !g_ascii_strcasecmp (content_type, "multipart/mixed")) {
1311 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1314 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1315 iter = tny_list_create_iterator (parts);
1316 while (!tny_iterator_is_done (iter)) {
1318 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1319 content_type = tny_mime_part_get_content_type (part);
1320 if (content_type && !g_ascii_strcasecmp (content_type, "multipart/related")) {
1324 g_object_unref (part);
1326 tny_iterator_next (iter);
1328 g_object_unref (iter);
1329 g_object_unref (parts);
1332 if (parent != NULL) {
1333 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1336 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1337 iter = tny_list_create_iterator (parts);
1338 while (!tny_iterator_is_done (iter)) {
1340 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1341 content_type = tny_mime_part_get_content_type (part);
1342 if (content_type && g_str_has_prefix (content_type, "image/")) {
1343 tny_list_prepend (priv->images, (GObject *) part);
1345 g_object_unref (part);
1346 tny_iterator_next (iter);
1348 g_object_unref (iter);
1349 g_object_unref (parts);
1350 g_object_unref (parent);
1355 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1358 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1360 for (iter = tny_list_create_iterator (attachments) ;
1361 !tny_iterator_is_done (iter);
1362 tny_iterator_next (iter)) {
1363 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1364 const gchar *cid = tny_mime_part_get_content_id (part);
1366 char *invalid = NULL;
1367 gint int_cid = strtol (cid, &invalid, 10);
1368 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1369 priv->next_cid = int_cid + 1;
1372 g_object_unref (part);
1374 g_object_unref (iter);
1378 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1381 gchar *to, *cc, *bcc, *subject;
1383 ModestMsgEditWindowPrivate *priv;
1384 ModestWindowPrivate *parent_priv;
1386 TnyHeaderFlags priority_flags;
1387 TnyFolder *msg_folder;
1388 gboolean is_html = FALSE;
1389 gboolean field_view_set;
1391 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1392 g_return_if_fail (TNY_IS_MSG (msg));
1394 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1395 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1397 header = tny_msg_get_header (msg);
1398 to = tny_header_dup_to (header);
1399 cc = tny_header_dup_cc (header);
1400 bcc = tny_header_dup_bcc (header);
1401 subject = tny_header_dup_subject (header);
1403 modest_tny_msg_get_references (TNY_MSG (msg), NULL, &(priv->references), &(priv->in_reply_to));
1404 priority_flags = tny_header_get_priority (header);
1407 gchar *quoted_names = modest_text_utils_quote_names (to);
1408 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), quoted_names);
1409 g_free (quoted_names);
1412 field_view_set = TRUE;
1414 gchar *quoted_names = modest_text_utils_quote_names (cc);
1415 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), quoted_names);
1416 g_free (quoted_names);
1417 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1418 gtk_widget_show (priv->cc_caption);
1419 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1420 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1421 gtk_widget_hide (priv->cc_caption);
1422 field_view_set = FALSE;
1424 modest_togglable_set_active (priv->cc_button, field_view_set);
1426 field_view_set = TRUE;
1428 gchar *quoted_names = modest_text_utils_quote_names (bcc);
1429 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), quoted_names);
1430 g_free (quoted_names);
1431 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1432 gtk_widget_show (priv->bcc_caption);
1433 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1434 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1435 gtk_widget_hide (priv->bcc_caption);
1436 field_view_set = FALSE;
1438 modest_togglable_set_active (priv->bcc_button, field_view_set);
1442 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1443 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1446 update_window_title (self);
1448 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1449 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1451 if ((body == NULL)||(body[0] == '\0')) {
1453 body = modest_text_utils_convert_to_html ("");
1456 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1457 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1460 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1463 /* Add attachments to the view */
1464 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1465 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1466 if (tny_list_get_length (priv->attachments) == 0) {
1467 gtk_widget_hide (priv->attachments_caption);
1469 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1470 gtk_widget_show_all (priv->attachments_caption);
1472 get_related_images (self, msg);
1473 update_next_cid (self, priv->attachments);
1474 update_next_cid (self, priv->images);
1475 replace_with_images (self, priv->images);
1477 if (preserve_is_rich && !is_html) {
1478 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1479 /* Get the default format required from configuration */
1480 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1481 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1484 /* Set the default focus depending on having already a To: field or not */
1485 if ((!to)||(*to == '\0')) {
1486 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1488 gtk_widget_grab_focus (priv->msg_body);
1491 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1493 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1494 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1496 modest_msg_edit_window_set_modified (self, FALSE);
1498 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1499 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1500 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1501 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1503 if (priv->msg_uid) {
1504 g_free (priv->msg_uid);
1505 priv->msg_uid = NULL;
1508 /* we should set a reference to the incoming message if it is a draft */
1509 msg_folder = tny_msg_get_folder (msg);
1511 if (modest_tny_folder_is_local_folder (msg_folder)) {
1512 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1513 if (type == TNY_FOLDER_TYPE_INVALID)
1514 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1516 if (type == TNY_FOLDER_TYPE_DRAFTS)
1517 priv->draft_msg = g_object_ref(msg);
1518 if (type == TNY_FOLDER_TYPE_OUTBOX)
1519 priv->outbox_msg = g_object_ref(msg);
1520 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1522 g_object_unref (msg_folder);
1531 #ifndef MODEST_TOOLKIT_HILDON2
1533 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
1536 GList *item_children, *node;
1537 GtkWidget *bin_child;
1539 bin_child = gtk_bin_get_child (GTK_BIN(item));
1541 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
1543 for (node = item_children; node != NULL; node = g_list_next (node)) {
1544 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
1545 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
1548 g_list_free (item_children);
1552 menu_tool_button_dont_expand (GtkMenuToolButton *item)
1555 GList *item_children, *node;
1557 box = gtk_bin_get_child (GTK_BIN (item));
1558 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
1559 item_children = gtk_container_get_children (GTK_CONTAINER (box));
1561 for (node = item_children; node != NULL; node = g_list_next (node)) {
1562 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
1563 if (GTK_IS_TOGGLE_BUTTON (node->data))
1564 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
1565 else if (GTK_IS_BUTTON (node->data))
1566 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
1568 g_list_free (item_children);
1573 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1575 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1576 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1577 GtkWidget *placeholder;
1578 GtkWidget *tool_item;
1583 GtkWidget *sizes_menu;
1584 GtkWidget *fonts_menu;
1588 #ifndef MODEST_TOOLKIT_HILDON2
1589 GSList *radio_group, *node;
1593 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1594 gtk_toolbar_set_show_arrow (GTK_TOOLBAR (parent_priv->toolbar), FALSE);
1595 gtk_toolbar_set_icon_size (GTK_TOOLBAR (parent_priv->toolbar),
1596 #ifdef MODEST_TOOLKIT_HILDON2
1597 HILDON_ICON_SIZE_FINGER
1599 GTK_ICON_SIZE_LARGE_TOOLBAR
1602 modest_window_add_toolbar (MODEST_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1604 /* Font color placeholder */
1605 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1606 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1609 priv->font_color_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1610 #ifdef MODEST_TOOLKIT_HILDON2
1611 priv->font_color_button = modest_color_button_new ();
1613 priv->font_color_button = gtk_color_button_new ();
1615 gtk_widget_set_size_request (priv->font_color_button, -1, 48);
1616 GTK_WIDGET_UNSET_FLAGS (priv->font_color_toolitem, GTK_CAN_FOCUS);
1617 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1618 gtk_container_add (GTK_CONTAINER (priv->font_color_toolitem), priv->font_color_button);
1619 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1620 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1621 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->font_color_toolitem), insert_index);
1622 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1624 G_CALLBACK (modest_msg_edit_window_color_button_change),
1627 /* Font size and face placeholder */
1628 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1629 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1631 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, ""));
1632 priv->size_tool_button_label = gtk_label_new (NULL);
1633 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1634 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1635 size_text, "</span>", NULL);
1636 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1637 gtk_misc_set_alignment (GTK_MISC (priv->size_tool_button_label), 1.0, 0.5);
1639 #ifdef MODEST_TOOLKIT_HILDON2
1640 hildon_helper_set_logical_font (priv->size_tool_button_label, "LargeSystemFont");
1642 hbox = gtk_hbox_new (MODEST_MARGIN_DEFAULT, FALSE);
1643 gtk_box_pack_start (GTK_BOX (hbox), priv->size_tool_button_label, TRUE, TRUE, 0);
1644 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1645 gtk_misc_set_alignment (GTK_MISC (arrow), 0.0, 0.5);
1646 gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
1647 gtk_widget_set_sensitive (arrow, FALSE);
1648 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), hbox);
1649 sizes_menu = gtk_menu_new ();
1650 priv->sizes_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1651 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1654 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1655 gtk_list_store_append (GTK_LIST_STORE (priv->sizes_model), &iter);
1657 gtk_list_store_set (GTK_LIST_STORE (priv->sizes_model), &iter,
1661 if (wp_font_size[size_index] == 12)
1662 priv->current_size_index = size_index;
1666 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_size_clicked), window);
1667 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1668 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1669 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1670 priv->font_size_toolitem = tool_item;
1672 #ifdef MODEST_TOOLKIT_HILDON2
1674 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, ""));
1675 priv->font_tool_button_label = gtk_label_new (NULL);
1676 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1677 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1678 gtk_misc_set_alignment (GTK_MISC (priv->font_tool_button_label), 1.0, 0.5);
1680 hildon_helper_set_logical_font (priv->font_tool_button_label, "LargeSystemFont");
1681 hbox = gtk_hbox_new (MODEST_MARGIN_DEFAULT, FALSE);
1682 gtk_box_pack_start (GTK_BOX (hbox), priv->font_tool_button_label, TRUE, TRUE, 0);
1683 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1684 gtk_misc_set_alignment (GTK_MISC (arrow), 0.0, 0.5);
1685 gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
1686 gtk_widget_set_sensitive (arrow, FALSE);
1687 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), hbox);
1689 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1690 priv->font_tool_button_label = gtk_label_new (NULL);
1691 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1692 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1694 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1695 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
1696 gtk_widget_show (priv->font_tool_button_label);
1697 gtk_widget_show (GTK_WIDGET (tool_item));
1698 fonts_menu = gtk_menu_new ();
1701 #ifdef MODEST_TOOLKIT_HILDON2
1702 priv->faces_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1703 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1706 gtk_list_store_append (GTK_LIST_STORE (priv->faces_model), &iter);
1708 gtk_list_store_set (GTK_LIST_STORE (priv->faces_model), &iter,
1709 0, wp_get_font_name (font_index),
1712 if (font_index == DEFAULT_FONT)
1713 priv->current_face_index = font_index;
1715 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_face_clicked), window);
1716 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1717 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1718 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1719 priv->font_face_toolitem = tool_item;
1721 priv->font_items_group = NULL;
1723 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1724 GtkWidget *font_menu_item;
1725 GtkWidget *child_label;
1727 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
1728 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
1729 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
1730 wp_get_font_name (font_index), "</span>", NULL);
1731 gtk_label_set_markup (GTK_LABEL (child_label), markup);
1734 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
1735 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
1736 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
1737 gtk_widget_show (font_menu_item);
1739 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
1742 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1743 GtkWidget *item = (GtkWidget *) node->data;
1744 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
1747 priv->font_items_group = g_slist_reverse (priv->font_items_group);
1748 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
1749 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1750 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1751 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1752 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1753 priv->font_face_toolitem = tool_item;
1756 /* Set expand and homogeneous for remaining items */
1757 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1758 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1759 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1760 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1761 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1762 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1764 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1765 will not show the tool items added to the placeholders) */
1766 gtk_widget_show_all (parent_priv->toolbar);
1768 /* Set the no show all *after* showing all items. We do not
1769 want the toolbar to be shown with a show all because it
1770 could go agains the gconf setting regarding showing or not
1771 the toolbar of the editor window */
1772 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1778 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, const gchar *mailbox, gboolean preserve_is_rich)
1781 ModestWindowPrivate *parent_priv;
1782 ModestMsgEditWindowPrivate *priv;
1783 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1784 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1785 ModestWindowMgr *mgr = NULL;
1787 g_return_val_if_fail (msg, NULL);
1788 g_return_val_if_fail (account_name, NULL);
1790 mgr = modest_runtime_get_window_mgr ();
1792 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1794 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1795 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1797 /* Menubar. Update the state of some toggles */
1798 priv->from_field_protos = get_transports ();
1799 priv->original_mailbox = NULL;
1800 modest_selector_set_pair_list (priv->from_field, priv->from_field_protos);
1801 modest_selector_set_active_id (priv->from_field, (gpointer) account_name);
1802 priv->last_from_account = modest_selector_get_active_id (priv->from_field);
1803 if (mailbox && modest_pair_list_find_by_first_as_string (priv->from_field_protos, mailbox)) {
1804 modest_selector_set_active_id (priv->from_field, (gpointer) mailbox);
1805 priv->original_mailbox = g_strdup (mailbox);
1806 } else if (modest_account_mgr_account_is_multimailbox (modest_runtime_get_account_mgr (), account_name, NULL)) {
1807 /* We set the first mailbox as the active mailbox */
1808 priv->original_mailbox = multimailbox_get_default_mailbox (account_name);
1809 if (priv->original_mailbox != NULL)
1810 modest_selector_set_active_id (priv->from_field,
1811 (gpointer) priv->original_mailbox);
1813 modest_selector_set_active_id (priv->from_field,
1814 (gpointer) account_name);
1816 modest_selector_set_active_id (priv->from_field, (gpointer) account_name);
1818 priv->last_from_account = modest_selector_get_active_id (priv->from_field);
1819 update_branding (MODEST_MSG_EDIT_WINDOW (obj), priv->last_from_account);
1820 if (!GTK_IS_COMBO_BOX (priv->from_field)) {
1821 #ifdef HILDON_TOOLKIT_HILDON2
1822 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1824 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1825 hildon_touch_selector_get_current_text
1826 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1829 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1830 modest_window_add_toolbar (MODEST_WINDOW (obj), GTK_TOOLBAR (priv->isearch_toolbar));
1833 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1835 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1837 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1838 modest_window_set_active_mailbox (MODEST_WINDOW(obj), priv->original_mailbox);
1840 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1842 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1843 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1844 /* Add common dimming rules */
1845 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1846 modest_msg_edit_window_toolbar_dimming_entries,
1847 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1848 MODEST_WINDOW (obj));
1849 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_toolitem,
1850 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1851 MODEST_WINDOW (obj));
1852 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1853 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1854 MODEST_WINDOW (obj));
1855 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1856 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1857 MODEST_WINDOW (obj));
1858 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->send_button,
1859 G_CALLBACK (modest_ui_dimming_rules_on_send),
1860 MODEST_WINDOW (obj));
1861 /* Insert dimming rules group for this window */
1862 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1863 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1865 /* Setup app menu */
1866 setup_menu (MODEST_MSG_EDIT_WINDOW (obj));
1868 /* Checks the dimming rules */
1869 g_object_unref (toolbar_rules_group);
1870 g_object_unref (clipboard_rules_group);
1871 gtk_widget_hide (priv->priority_icon);
1872 gtk_widget_queue_resize (priv->subject_box);
1873 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1875 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1877 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1878 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1879 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1880 priv->update_caption_visibility = TRUE;
1882 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1884 /* Track account-removed signal, this window should be closed
1885 in the case we're creating a mail associated to the account
1887 priv->account_removed_handler_id =
1888 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1890 G_CALLBACK(on_account_removed),
1893 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1895 return (ModestWindow*) obj;
1899 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1901 GString **string_buffer = (GString **) user_data;
1903 *string_buffer = g_string_append (*string_buffer, buffer);
1909 * @result: A new string which should be freed with g_free().
1912 get_formatted_data (ModestMsgEditWindow *edit_window)
1914 ModestMsgEditWindowPrivate *priv;
1915 GString *string_buffer = g_string_new ("");
1917 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1919 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1921 modest_text_utils_hyperlinkify (string_buffer);
1923 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1925 return g_string_free (string_buffer, FALSE);
1930 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1933 const gchar *account_name;
1934 ModestMsgEditWindowPrivate *priv;
1935 TnyIterator *att_iter;
1936 const gchar *picker_active_id;
1938 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1940 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1942 picker_active_id = modest_selector_get_active_id (priv->from_field);
1943 g_return_val_if_fail (picker_active_id, NULL);
1944 account_name = modest_utils_get_account_name_from_recipient (picker_active_id, NULL);
1946 /* don't free these (except from) */
1947 data = g_slice_new0 (MsgData);
1948 data->from = g_strdup ((gchar *) modest_selector_get_active_display_name (priv->from_field));
1949 data->account_name = g_strdup (account_name);
1950 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1951 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1952 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1953 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1954 data->references = g_strdup (priv->references);
1955 data->in_reply_to = g_strdup (priv->in_reply_to);
1956 if (priv->draft_msg) {
1957 data->draft_msg = g_object_ref (priv->draft_msg);
1958 } else if (priv->outbox_msg) {
1959 data->draft_msg = g_object_ref (priv->outbox_msg);
1961 data->draft_msg = NULL;
1964 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1966 gtk_text_buffer_get_bounds (buf, &b, &e);
1967 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1969 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1970 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1972 data->html_body = NULL;
1974 /* deep-copy the data */
1975 att_iter = tny_list_create_iterator (priv->attachments);
1976 data->attachments = NULL;
1977 while (!tny_iterator_is_done (att_iter)) {
1978 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1979 if (!(TNY_IS_MIME_PART(part))) {
1980 g_warning ("strange data in attachment list");
1981 g_object_unref (part);
1982 tny_iterator_next (att_iter);
1985 data->attachments = g_list_append (data->attachments,
1987 tny_iterator_next (att_iter);
1989 g_object_unref (att_iter);
1991 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1992 att_iter = tny_list_create_iterator (priv->images);
1993 data->images = NULL;
1994 while (!tny_iterator_is_done (att_iter)) {
1995 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1997 if (!(TNY_IS_MIME_PART(part))) {
1998 g_warning ("strange data in attachment list");
1999 g_object_unref (part);
2000 tny_iterator_next (att_iter);
2003 cid = tny_mime_part_get_content_id (part);
2005 gchar *image_tag_id;
2006 GtkTextTag *image_tag;
2008 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
2009 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
2010 g_free (image_tag_id);
2012 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
2014 ((gtk_text_iter_has_tag (&iter, image_tag))||
2015 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
2016 data->images = g_list_append (data->images,
2017 g_object_ref (part));
2019 g_object_unref (part);
2020 tny_iterator_next (att_iter);
2022 g_object_unref (att_iter);
2024 data->priority_flags = priv->priority_flags;
2031 unref_gobject (GObject *obj, gpointer data)
2033 if (!G_IS_OBJECT(obj))
2035 g_object_unref (obj);
2039 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
2042 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
2050 g_free (data->from);
2051 g_free (data->subject);
2052 g_free (data->plain_body);
2053 g_free (data->html_body);
2054 g_free (data->account_name);
2055 g_free (data->references);
2056 g_free (data->in_reply_to);
2058 if (data->draft_msg != NULL) {
2059 g_object_unref (data->draft_msg);
2060 data->draft_msg = NULL;
2063 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
2064 g_list_free (data->attachments);
2065 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
2066 g_list_free (data->images);
2068 g_slice_free (MsgData, data);
2072 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
2074 guint64 *parts_size)
2076 ModestMsgEditWindowPrivate *priv;
2078 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2080 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
2082 /* TODO: add images */
2083 *parts_size += priv->images_size;
2084 *parts_count += priv->images_count;
2089 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
2092 ModestMsgEditWindowPrivate *priv = NULL;
2093 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
2095 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
2097 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2099 return MODEST_MSG_EDIT_FORMAT_HTML;
2101 return MODEST_MSG_EDIT_FORMAT_TEXT;
2105 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
2106 ModestMsgEditFormat format)
2108 ModestMsgEditWindowPrivate *priv;
2109 ModestWindowPrivate *parent_priv;
2111 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2112 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
2113 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
2116 case MODEST_MSG_EDIT_FORMAT_HTML:
2117 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2118 update_signature (self, priv->last_from_account, priv->last_from_account);
2119 if (parent_priv->toolbar) gtk_widget_show (parent_priv->toolbar);
2121 case MODEST_MSG_EDIT_FORMAT_TEXT:
2122 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2123 if (parent_priv->toolbar) gtk_widget_hide (parent_priv->toolbar);
2126 g_return_if_reached ();
2130 ModestMsgEditFormatState *
2131 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
2133 ModestMsgEditFormatState *format_state = NULL;
2134 ModestMsgEditWindowPrivate *priv;
2135 WPTextBufferFormat *buffer_format;
2137 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
2139 buffer_format = g_new0 (WPTextBufferFormat, 1);
2140 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
2142 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
2144 format_state = g_new0 (ModestMsgEditFormatState, 1);
2145 format_state->bold = buffer_format->bold&0x1;
2146 format_state->italics = buffer_format->italic&0x1;
2147 format_state->bullet = buffer_format->bullet&0x1;
2148 format_state->color = buffer_format->color;
2149 format_state->font_size = buffer_format->font_size;
2150 format_state->font_family = wp_get_font_name (buffer_format->font);
2151 format_state->justification = buffer_format->justification;
2152 g_free (buffer_format);
2154 return format_state;
2159 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
2160 const ModestMsgEditFormatState *format_state)
2162 ModestMsgEditWindowPrivate *priv;
2163 WPTextBufferFormat *buffer_format;
2164 WPTextBufferFormat *current_format;
2166 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2167 g_return_if_fail (format_state != NULL);
2169 buffer_format = g_new0 (WPTextBufferFormat, 1);
2170 current_format = g_new0 (WPTextBufferFormat, 1);
2172 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
2173 gtk_widget_grab_focus (priv->msg_body);
2174 buffer_format->bold = (format_state->bold != FALSE);
2175 buffer_format->italic = (format_state->italics != FALSE);
2176 buffer_format->color = format_state->color;
2177 buffer_format->font_size = format_state->font_size;
2178 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
2179 buffer_format->justification = format_state->justification;
2180 buffer_format->bullet = format_state->bullet;
2182 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
2184 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
2185 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
2186 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
2187 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
2188 buffer_format->cs.font = (buffer_format->font != current_format->font);
2189 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
2190 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
2192 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
2193 if (buffer_format->cs.bold) {
2194 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
2195 GINT_TO_POINTER (buffer_format->bold&0x1));
2197 if (buffer_format->cs.italic) {
2198 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
2199 GINT_TO_POINTER (buffer_format->italic&0x1));
2201 if (buffer_format->cs.color) {
2202 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2203 GINT_TO_POINTER (&(buffer_format->color)));
2205 if (buffer_format->cs.font_size) {
2206 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2207 GINT_TO_POINTER (buffer_format->font_size));
2209 if (buffer_format->cs.justification) {
2210 switch (buffer_format->justification) {
2211 case GTK_JUSTIFY_LEFT:
2212 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
2213 GINT_TO_POINTER(TRUE));
2215 case GTK_JUSTIFY_CENTER:
2216 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
2217 GINT_TO_POINTER(TRUE));
2219 case GTK_JUSTIFY_RIGHT:
2220 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
2221 GINT_TO_POINTER(TRUE));
2228 if (buffer_format->cs.font) {
2229 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2230 GINT_TO_POINTER (buffer_format->font));
2232 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
2233 if (buffer_format->cs.bullet) {
2234 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
2235 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
2237 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
2239 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
2241 g_free (buffer_format);
2242 g_free (current_format);
2244 /* Check dimming rules */
2245 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
2246 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
2250 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
2252 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2254 ModestWindowPrivate *parent_priv;
2255 ModestMsgEditWindowPrivate *priv;
2257 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2258 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2260 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
2261 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu");
2262 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2263 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
2265 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatPlainTextMenu");
2266 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2267 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
2270 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2272 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2273 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
2275 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2276 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
2278 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
2279 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
2282 switch (buffer_format->justification)
2284 case GTK_JUSTIFY_LEFT:
2285 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2287 case GTK_JUSTIFY_CENTER:
2288 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2290 case GTK_JUSTIFY_RIGHT:
2291 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2298 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
2300 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
2301 G_CALLBACK (modest_msg_edit_window_color_button_change),
2303 #ifdef MODEST_TOOLKIT_HILDON2
2304 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
2306 gtk_color_button_set_color (GTK_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
2308 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
2309 G_CALLBACK (modest_msg_edit_window_color_button_change),
2312 if (priv->current_size_index != buffer_format->font_size) {
2316 path = gtk_tree_path_new_from_indices (buffer_format->font_size, -1);
2317 if (gtk_tree_model_get_iter (priv->sizes_model, &iter, path)) {
2321 priv->current_size_index = buffer_format->font_size;
2323 gtk_tree_model_get (priv->sizes_model, &iter, 0, &size_text, -1);
2324 markup = g_strconcat ("<span font_family='Sans'>",
2325 size_text, "</span>", NULL);
2327 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2331 gtk_tree_path_free (path);
2334 #ifdef MODEST_TOOLKIT_HILDON2
2335 if (priv->current_face_index != buffer_format->font) {
2339 path = gtk_tree_path_new_from_indices (buffer_format->font, -1);
2340 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2344 priv->current_face_index = buffer_format->font;
2345 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2346 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2347 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2354 GtkWidget *new_font_menuitem;
2355 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
2356 buffer_format->font))->data);
2357 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
2361 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
2362 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2363 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2365 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
2366 G_CALLBACK (modest_msg_edit_window_font_change),
2368 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
2369 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
2370 G_CALLBACK (modest_msg_edit_window_font_change),
2375 g_free (buffer_format);
2381 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2383 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2384 ModestMsgEditWindowPrivate *priv;
2385 GtkWidget *dialog = NULL;
2387 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2388 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2390 #ifdef MODEST_TOOLKIT_HILDON2
2391 dialog = hildon_color_chooser_new ();
2392 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2393 g_free (buffer_format);
2395 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2397 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2398 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2401 gtk_widget_destroy (dialog);
2403 dialog = gtk_color_selection_dialog_new (NULL);
2404 GtkWidget *selection;
2406 g_object_get (G_OBJECT (dialog), "color_selection", &selection, NULL);
2407 gtk_color_selection_set_current_color (GTK_COLOR_SELECTION (selection), &(buffer_format->color));
2408 gtk_color_selection_set_previous_color (GTK_COLOR_SELECTION (selection), &(buffer_format->color));
2409 g_free (buffer_format);
2411 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2413 gtk_color_selection_get_current_color (GTK_COLOR_SELECTION(selection), &col);
2414 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2417 gtk_widget_destroy (dialog);
2424 create_stream_for_uri (const gchar* uri)
2429 TnyStream *result = NULL;
2431 GnomeVFSHandle *handle = NULL;
2432 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2433 if (test == GNOME_VFS_OK) {
2434 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2435 /* Streams over OBEX (Bluetooth) are not seekable but
2436 * we expect them to be (we might need to read them
2437 * several times). So if this is a Bluetooth URI just
2438 * read the whole file into memory (this is not a fast
2439 * protocol so we can assume that these files are not
2440 * going to be very big) */
2441 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2442 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2443 TnyStream *memstream = tny_camel_mem_stream_new ();
2444 tny_stream_write_to_stream (vfssstream, memstream);
2445 g_object_unref (vfssstream);
2448 result = vfssstream;
2456 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2459 ModestMsgEditWindowPrivate *priv;
2460 GtkWidget *dialog = NULL;
2462 GSList *uris = NULL;
2463 GSList *uri_node = NULL;
2465 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2467 dialog = modest_toolkit_factory_create_file_chooser_dialog (modest_runtime_get_toolkit_factory (),
2468 _("mcen_ia_select_inline_image_title"),
2469 (GtkWindow *) window,
2470 GTK_FILE_CHOOSER_ACTION_OPEN);
2471 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2473 #ifdef MODEST_TOOLKIT_HILDON2
2474 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2477 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2478 GTK_WINDOW (dialog), GTK_WINDOW (window));
2480 response = gtk_dialog_run (GTK_DIALOG (dialog));
2482 case GTK_RESPONSE_OK:
2484 gchar *current_folder;
2485 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2486 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2487 if (current_folder && current_folder != '\0') {
2489 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_INSERT_IMAGE_PATH,
2490 current_folder, &err);
2492 g_debug ("Error storing latest used folder: %s", err->message);
2496 g_free (current_folder);
2502 gtk_widget_destroy (dialog);
2504 g_object_ref (window);
2505 /* The operation could take some time so allow the dialog to be closed */
2506 while (gtk_events_pending ())
2507 gtk_main_iteration ();
2509 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2511 GnomeVFSHandle *handle = NULL;
2512 GnomeVFSResult result;
2513 GtkTextIter position;
2514 GtkTextMark *insert_mark;
2516 uri = (const gchar *) uri_node->data;
2517 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2518 if (result == GNOME_VFS_OK) {
2520 GnomeVFSFileInfo *info;
2521 gchar *filename, *basename, *escaped_filename;
2522 TnyMimePart *mime_part;
2524 const gchar *mime_type = NULL;
2525 GnomeVFSURI *vfs_uri;
2526 guint64 stream_size;
2528 gnome_vfs_close (handle);
2529 vfs_uri = gnome_vfs_uri_new (uri);
2531 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2532 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2533 g_free (escaped_filename);
2534 gnome_vfs_uri_unref (vfs_uri);
2535 info = gnome_vfs_file_info_new ();
2537 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2538 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2540 mime_type = gnome_vfs_file_info_get_mime_type (info);
2542 mime_part = tny_platform_factory_new_mime_part
2543 (modest_runtime_get_platform_factory ());
2545 TnyStream *stream = create_stream_for_uri (uri);
2547 if (stream == NULL) {
2549 modest_platform_information_banner (NULL, NULL,
2550 _FM_OPENING_NOT_ALLOWED);
2552 g_object_unref (mime_part);
2553 gnome_vfs_file_info_unref (info);
2557 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2559 content_id = g_strdup_printf ("%d", priv->next_cid);
2560 tny_mime_part_set_content_id (mime_part, content_id);
2561 g_free (content_id);
2564 basename = g_path_get_basename (filename);
2565 tny_mime_part_set_filename (mime_part, basename);
2568 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, window);
2570 if (pixbuf != NULL) {
2571 priv->images_size += stream_size;
2572 priv->images_count ++;
2573 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2574 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2575 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position,
2576 tny_mime_part_get_content_id (mime_part), pixbuf);
2577 g_object_unref (pixbuf);
2579 tny_list_prepend (priv->images, (GObject *) mime_part);
2580 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2582 modest_platform_information_banner (NULL, NULL,
2583 _("mail_ib_file_operation_failed"));
2587 g_object_unref (mime_part);
2588 gnome_vfs_file_info_unref (info);
2592 g_object_unref (window);
2596 on_attach_file_response (GtkDialog *dialog,
2600 GSList *uris = NULL;
2602 GnomeVFSFileSize total_size, allowed_size;
2603 ModestMsgEditWindow *window;
2604 ModestMsgEditWindowPrivate *priv;
2609 case GTK_RESPONSE_OK:
2611 gchar *current_folder;
2613 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2614 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2615 if (current_folder && current_folder != '\0') {
2617 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_ATTACH_FILE_PATH,
2618 current_folder, &err);
2620 g_debug ("Error storing latest used folder: %s", err->message);
2624 g_free (current_folder);
2631 window = MODEST_MSG_EDIT_WINDOW (user_data);
2632 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2634 /* allowed size is the maximum size - what's already there */
2635 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2636 &att_num, &att_size);
2637 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2640 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2642 const gchar *uri = (const gchar *) uri_node->data;
2645 modest_msg_edit_window_attach_file_one (window, uri, allowed_size);
2647 if (total_size > allowed_size) {
2648 g_debug ("%s: total size: %u",
2649 __FUNCTION__, (unsigned int)total_size);
2652 allowed_size -= total_size;
2654 g_slist_foreach (uris, (GFunc) g_free, NULL);
2655 g_slist_free (uris);
2657 gtk_widget_destroy (GTK_WIDGET (dialog));
2661 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2663 GtkWidget *dialog = NULL;
2664 ModestMsgEditWindowPrivate *priv;
2667 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2669 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2671 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2674 dialog = modest_toolkit_factory_create_file_chooser_dialog (modest_runtime_get_toolkit_factory (),
2675 _("mcen_ia_select_attachment_title"),
2676 (GtkWindow *) window,
2677 GTK_FILE_CHOOSER_ACTION_OPEN);
2678 conf_folder = modest_conf_get_string (modest_runtime_get_conf (),
2679 MODEST_CONF_LATEST_ATTACH_FILE_PATH, NULL);
2680 if (conf_folder && conf_folder[0] != '\0') {
2681 gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (dialog), conf_folder);
2684 /* Set the default folder to documents folder */
2685 docs_folder = (gchar *) g_strdup(g_get_user_special_dir (G_USER_DIRECTORY_DOCUMENTS));
2686 #ifdef MODEST_TOOLKIT_HILDON2
2689 docs_folder = g_build_filename (g_getenv (MODEST_MAEMO_UTILS_MYDOCS_ENV),
2690 ".documents", NULL);
2693 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), docs_folder);
2694 g_free (docs_folder);
2696 g_free (conf_folder);
2697 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2698 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2699 GTK_WINDOW (dialog), GTK_WINDOW (window));
2701 /* Connect to response & show */
2702 g_signal_connect (dialog, "response",
2703 G_CALLBACK (on_attach_file_response), window);
2704 gtk_widget_show (dialog);
2709 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2711 GnomeVFSFileSize allowed_size)
2714 GnomeVFSHandle *handle = NULL;
2715 ModestMsgEditWindowPrivate *priv;
2716 GnomeVFSResult result;
2717 GnomeVFSFileSize size = 0;
2718 g_return_val_if_fail (window, 0);
2719 g_return_val_if_fail (uri, 0);
2721 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2723 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2724 if (result == GNOME_VFS_OK) {
2725 TnyMimePart *mime_part;
2727 const gchar *mime_type = NULL;
2729 gchar *escaped_filename;
2732 GnomeVFSFileInfo *info;
2733 GnomeVFSURI *vfs_uri;
2735 gnome_vfs_close (handle);
2736 vfs_uri = gnome_vfs_uri_new (uri);
2739 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2740 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2741 g_free (escaped_filename);
2742 gnome_vfs_uri_unref (vfs_uri);
2744 info = gnome_vfs_file_info_new ();
2746 if (gnome_vfs_get_file_info (uri,
2748 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2750 mime_type = gnome_vfs_file_info_get_mime_type (info);
2751 mime_part = tny_platform_factory_new_mime_part
2752 (modest_runtime_get_platform_factory ());
2754 /* try to get the attachment's size; this may fail for weird
2755 * file systems, like obex, upnp... */
2756 if (allowed_size != 0 &&
2757 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2759 if (size > allowed_size) {
2760 modest_platform_information_banner (NULL, NULL,
2761 _("mail_ib_error_attachment_size"));
2766 g_debug ("%s: could not get attachment size", __FUNCTION__);
2768 stream = create_stream_for_uri (uri);
2770 if (stream == NULL) {
2772 modest_platform_information_banner (NULL, NULL, _FM_OPENING_NOT_ALLOWED);
2774 g_object_unref (mime_part);
2776 gnome_vfs_file_info_unref (info);
2780 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2781 g_object_unref (stream);
2783 content_id = g_strdup_printf ("%d", priv->next_cid);
2784 tny_mime_part_set_content_id (mime_part, content_id);
2785 g_free (content_id);
2788 basename = g_path_get_basename (filename);
2789 tny_mime_part_set_filename (mime_part, basename);
2792 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2793 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2795 info->size == 0, info->size);
2796 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2797 gtk_widget_show_all (priv->attachments_caption);
2798 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2800 g_object_unref (mime_part);
2801 gnome_vfs_file_info_unref (info);
2808 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2811 ModestMsgEditWindowPrivate *priv;
2814 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2815 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2817 if (att_list == NULL) {
2818 att_list = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2819 if (!modest_toolkit_utils_select_attachments (GTK_WINDOW (window), att_list, TRUE)) {
2820 g_object_unref (att_list);
2824 g_object_ref (att_list);
2827 if (tny_list_get_length (att_list) == 0) {
2828 modest_platform_system_banner (NULL, NULL, _("TODO: no attachments selected to remove"));
2830 gboolean dialog_response;
2831 gchar *message = NULL;
2832 gchar *filename = NULL;
2834 if (tny_list_get_length (att_list) == 1) {
2836 iter = tny_list_create_iterator (att_list);
2837 part = (TnyMimePart *) tny_iterator_get_current (iter);
2838 g_object_unref (iter);
2839 if (TNY_IS_MSG (part)) {
2840 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2842 filename = tny_header_dup_subject (header);
2843 g_object_unref (header);
2845 if (filename == NULL) {
2846 filename = g_strdup (_("mail_va_no_subject"));
2849 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2851 g_object_unref (part);
2853 filename = g_strdup ("");
2855 message = g_strdup_printf (ngettext("emev_nc_delete_attachment",
2856 "emev_nc_delete_attachments",
2857 tny_list_get_length (att_list)), filename);
2860 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
2864 if (dialog_response != GTK_RESPONSE_OK) {
2865 g_object_unref (att_list);
2869 for (iter = tny_list_create_iterator (att_list);
2870 !tny_iterator_is_done (iter);
2871 tny_iterator_next (iter)) {
2872 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2873 const gchar *att_id;
2874 tny_list_remove (priv->attachments, (GObject *) mime_part);
2876 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2878 if (tny_list_get_length (priv->attachments) == 0)
2879 gtk_widget_hide (priv->attachments_caption);
2880 att_id = tny_mime_part_get_content_id (mime_part);
2882 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2884 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2885 g_object_unref (mime_part);
2887 g_object_unref (iter);
2890 g_object_unref (att_list);
2892 /* if the last attachment has been removed, focus the Subject: field */
2893 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2894 gtk_widget_grab_focus (priv->subject_field);
2898 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2901 ModestMsgEditWindowPrivate *priv;
2904 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2906 gtk_color_button_get_color (GTK_COLOR_BUTTON(priv->font_color_button), &new_color);
2908 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) &new_color);
2910 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2913 #ifndef MODEST_TOOLKIT_HILDON2
2915 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
2918 ModestMsgEditWindowPrivate *priv;
2919 gint new_font_index;
2920 ModestMsgEditWindow *window;
2923 window = MODEST_MSG_EDIT_WINDOW (userdata);
2924 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2925 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2927 if (gtk_check_menu_item_get_active (menu_item)) {
2930 label = gtk_bin_get_child (GTK_BIN (menu_item));
2932 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
2934 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2935 GINT_TO_POINTER(new_font_index)))
2936 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2938 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2939 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2940 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2947 font_size_clicked (GtkToolButton *button,
2948 ModestMsgEditWindow *window)
2950 #ifdef MODEST_TOOLKIT_HILDON2
2951 ModestMsgEditWindowPrivate *priv;
2952 GtkWidget *selector, *dialog;
2954 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2956 selector = hildon_touch_selector_new ();
2957 hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector), priv->sizes_model, TRUE);
2958 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_size_index);
2960 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2961 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2962 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_size"));
2964 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2968 WPTextBufferFormat format;
2970 new_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2972 memset (&format, 0, sizeof (format));
2973 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2975 format.cs.font_size = TRUE;
2976 format.cs.text_position = TRUE;
2977 format.cs.font = TRUE;
2978 format.font_size = new_index;
2979 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2981 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2982 GINT_TO_POINTER (new_index)))
2983 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2985 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2986 size_text = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (selector));
2987 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
2988 size_text, "</span>", NULL);
2990 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2994 gtk_widget_destroy (dialog);
2996 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
3000 #ifdef MODEST_TOOLKIT_HILDON2
3002 font_face_clicked (GtkToolButton *button,
3003 ModestMsgEditWindow *window)
3005 ModestMsgEditWindowPrivate *priv;
3006 GtkWidget *selector, *dialog;
3007 GtkCellRenderer *renderer;
3009 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3011 selector = hildon_touch_selector_new ();
3012 renderer = gtk_cell_renderer_text_new ();
3013 g_object_set (G_OBJECT (renderer), "alignment", PANGO_ALIGN_CENTER, "xalign", 0.5, NULL);
3014 hildon_touch_selector_append_column (HILDON_TOUCH_SELECTOR (selector), priv->faces_model,
3015 renderer, "family", 0, "text", 0, NULL);
3016 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_face_index);
3018 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
3019 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
3020 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_face"));
3022 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
3023 gint new_font_index;
3027 new_font_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
3028 path = gtk_tree_path_new_from_indices (new_font_index, -1);
3029 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
3033 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
3035 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
3036 GINT_TO_POINTER(new_font_index)))
3037 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
3039 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
3040 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
3042 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
3046 gtk_tree_path_free (path);
3049 gtk_widget_destroy (dialog);
3051 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
3056 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
3059 ModestMsgEditWindowPrivate *priv = NULL;
3060 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3062 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3063 if (!priv->update_caption_visibility)
3066 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
3068 gtk_widget_show (priv->cc_caption);
3070 gtk_widget_hide (priv->cc_caption);
3072 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
3076 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
3079 ModestMsgEditWindowPrivate *priv = NULL;
3080 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3082 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3083 if (!priv->update_caption_visibility)
3086 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
3088 gtk_widget_show (priv->bcc_caption);
3090 gtk_widget_hide (priv->bcc_caption);
3092 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
3096 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
3097 ModestRecptEditor *editor)
3099 ModestMsgEditWindowPrivate *priv;
3101 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3102 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
3104 /* we check for low-mem; in that case, show a warning, and don't allow
3105 * for the addressbook
3107 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
3110 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3112 if (editor == NULL) {
3113 GtkWidget *view_focus, *parent;
3114 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
3116 /* This code should be kept in sync with ModestRecptEditor. The
3117 textview inside the recpt editor is the one that really gets the
3118 focus. As it's inside a scrolled window, and this one inside the
3119 hbox recpt editor inherits from, we'll need to go up in the
3120 hierarchy to know if the text view is part of the recpt editor
3121 or if it's a different text entry */
3122 parent = gtk_widget_get_parent (view_focus);
3123 if (parent && MODEST_IS_RECPT_EDITOR (parent))
3124 editor = MODEST_RECPT_EDITOR (parent);
3127 editor = MODEST_RECPT_EDITOR (priv->to_field);
3130 modest_address_book_select_addresses (editor, GTK_WINDOW (window));
3134 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
3136 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3138 modest_msg_edit_window_open_addressbook (window, NULL);
3142 modest_msg_edit_window_show_toolbar (ModestWindow *self,
3143 gboolean show_toolbar)
3145 ModestWindowPrivate *parent_priv;
3146 ModestMsgEditWindowPrivate *priv;
3148 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
3149 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3150 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
3152 /* We can not just use the code of
3153 modest_msg_edit_window_setup_toolbar because it has a
3154 mixture of both initialization and creation code. */
3156 gint current_format;
3157 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
3158 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
3159 if (current_format == MODEST_FILE_FORMAT_PLAIN_TEXT) {
3160 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
3162 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
3165 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
3170 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
3171 TnyHeaderFlags priority_flags)
3173 ModestMsgEditWindowPrivate *priv;
3174 ModestWindowPrivate *parent_priv;
3176 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3178 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3179 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3181 if (priv->priority_flags != priority_flags) {
3182 GtkAction *priority_action = NULL;
3184 priv->priority_flags = priority_flags;
3186 switch (priority_flags) {
3187 case TNY_HEADER_FLAG_HIGH_PRIORITY:
3188 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
3189 MODEST_HEADER_ICON_HIGH,
3190 #ifdef MODEST_TOOLKIT_HILDON2
3191 HILDON_ICON_SIZE_SMALL
3193 GTK_ICON_SIZE_BUTTON
3196 gtk_widget_show (priv->priority_icon);
3197 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
3198 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
3200 case TNY_HEADER_FLAG_LOW_PRIORITY:
3201 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
3202 MODEST_HEADER_ICON_LOW,
3203 #ifdef MODEST_TOOLKIT_HILDON2
3204 HILDON_ICON_SIZE_SMALL
3206 GTK_ICON_SIZE_BUTTON
3209 gtk_widget_show (priv->priority_icon);
3210 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
3211 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
3214 gtk_widget_hide (priv->priority_icon);
3215 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
3216 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
3219 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
3220 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3222 gtk_widget_queue_resize (priv->subject_box);
3226 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
3229 ModestMsgEditWindowPrivate *priv;
3230 ModestWindowPrivate *parent_priv;
3231 gint current_format;
3233 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3235 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3236 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3238 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
3239 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
3241 gtk_widget_set_no_show_all (GTK_WIDGET (parent_priv->toolbar), TRUE);
3243 if (current_format != file_format) {
3244 switch (file_format) {
3245 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
3246 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
3247 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
3248 update_signature (window, priv->last_from_account, priv->last_from_account);
3249 if (parent_priv->toolbar)
3250 gtk_widget_show (parent_priv->toolbar);
3252 case MODEST_FILE_FORMAT_PLAIN_TEXT:
3255 response = modest_platform_run_confirmation_dialog (NULL, _("emev_nc_formatting_lost"));
3256 if (response == GTK_RESPONSE_OK) {
3257 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
3258 if (parent_priv->toolbar)
3259 gtk_widget_hide (parent_priv->toolbar);
3261 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
3262 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
3267 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3268 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3269 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3274 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
3276 #ifdef MODEST_TOOLKIT_HILDON2
3278 ModestMsgEditWindowPrivate *priv;
3279 WPTextBufferFormat oldfmt, fmt;
3280 gint old_position = 0;
3284 GdkColor *color = NULL;
3285 gboolean bold, bold_set, italic, italic_set;
3286 gboolean underline, underline_set;
3287 gboolean strikethrough, strikethrough_set;
3288 gboolean position_set;
3289 gboolean font_size_set, font_set, color_set;
3292 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3293 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3295 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
3296 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
3297 GTK_WINDOW(dialog), GTK_WINDOW (window));
3299 /* First we get the currently selected font information */
3300 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
3302 switch (oldfmt.text_position) {
3303 case TEXT_POSITION_NORMAL:
3306 case TEXT_POSITION_SUPERSCRIPT:
3314 g_object_set (G_OBJECT (dialog),
3315 "bold", oldfmt.bold != FALSE,
3316 "bold-set", !oldfmt.cs.bold,
3317 "underline", oldfmt.underline != FALSE,
3318 "underline-set", !oldfmt.cs.underline,
3319 "italic", oldfmt.italic != FALSE,
3320 "italic-set", !oldfmt.cs.italic,
3321 "strikethrough", oldfmt.strikethrough != FALSE,
3322 "strikethrough-set", !oldfmt.cs.strikethrough,
3323 "color", &oldfmt.color,
3324 "color-set", !oldfmt.cs.color,
3325 "size", wp_font_size[oldfmt.font_size],
3326 "size-set", !oldfmt.cs.font_size,
3327 "position", old_position,
3328 "position-set", !oldfmt.cs.text_position,
3329 "family", wp_get_font_name (oldfmt.font),
3330 "family-set", !oldfmt.cs.font,
3333 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
3334 GTK_WINDOW (dialog), GTK_WINDOW (window));
3335 gtk_widget_show_all (dialog);
3336 priv->font_dialog = dialog;
3337 response = gtk_dialog_run (GTK_DIALOG (dialog));
3338 priv->font_dialog = NULL;
3339 if (response == GTK_RESPONSE_OK) {
3341 g_object_get( dialog,
3343 "bold-set", &bold_set,
3344 "underline", &underline,
3345 "underline-set", &underline_set,
3347 "italic-set", &italic_set,
3348 "strikethrough", &strikethrough,
3349 "strikethrough-set", &strikethrough_set,
3351 "color-set", &color_set,
3353 "size-set", &font_size_set,
3354 "family", &font_name,
3355 "family-set", &font_set,
3356 "position", &position,
3357 "position-set", &position_set,
3362 if (response == GTK_RESPONSE_OK) {
3363 memset(&fmt, 0, sizeof(fmt));
3369 fmt.italic = italic;
3370 fmt.cs.italic = TRUE;
3372 if (underline_set) {
3373 fmt.underline = underline;
3374 fmt.cs.underline = TRUE;
3376 if (strikethrough_set) {
3377 fmt.strikethrough = strikethrough;
3378 fmt.cs.strikethrough = TRUE;
3383 ? TEXT_POSITION_NORMAL
3384 : ( ( position == 1 )
3385 ? TEXT_POSITION_SUPERSCRIPT
3386 : TEXT_POSITION_SUBSCRIPT );
3387 fmt.cs.text_position = TRUE;
3388 fmt.font_size = oldfmt.font_size;
3392 fmt.cs.color = TRUE;
3395 fmt.font = wp_get_font_index(font_name,
3400 if (font_size_set) {
3401 fmt.cs.font_size = TRUE;
3402 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
3404 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
3405 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3407 gtk_widget_destroy (dialog);
3409 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
3414 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
3416 ModestMsgEditWindowPrivate *priv;
3417 ModestWindowPrivate *parent_priv;
3418 gboolean was_rich_text, is_rich_text;
3420 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3421 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3422 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3424 was_rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
3426 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
3428 is_rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
3430 if (parent_priv->toolbar && was_rich_text != is_rich_text) {
3432 gtk_widget_show (parent_priv->toolbar);
3434 gtk_widget_hide (parent_priv->toolbar);
3437 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3438 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3442 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
3444 ModestMsgEditWindowPrivate *priv;
3446 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3447 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3449 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
3451 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3452 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3457 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
3459 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3461 priv->can_undo = can_undo;
3465 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
3467 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3469 priv->can_redo = can_redo;
3473 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3475 ModestMsgEditWindowPrivate *priv;
3476 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3477 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3479 return priv->can_undo;
3483 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3485 ModestMsgEditWindowPrivate *priv;
3486 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3487 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3489 return priv->can_redo;
3494 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3497 GtkTextIter match_start, match_end;
3499 if (image_id == NULL)
3502 gtk_text_buffer_get_start_iter (buffer, &iter);
3504 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3505 GSList *tags = gtk_text_iter_get_tags (&match_start);
3507 for (node = tags; node != NULL; node = g_slist_next (node)) {
3508 GtkTextTag *tag = (GtkTextTag *) node->data;
3509 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3510 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3511 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3513 offset = gtk_text_iter_get_offset (&match_start);
3514 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3515 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3519 gtk_text_iter_forward_char (&iter);
3524 message_is_empty (ModestMsgEditWindow *window)
3526 ModestMsgEditWindowPrivate *priv = NULL;
3528 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3529 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3531 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3532 * so we can ignore markup.
3534 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3537 count = gtk_text_buffer_get_char_count (buf);
3543 msg_body_focus (GtkWidget *focus,
3544 GdkEventFocus *event,
3548 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3549 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3550 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3555 recpt_field_changed (GtkTextBuffer *buffer,
3556 ModestMsgEditWindow *editor)
3558 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3559 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3563 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3565 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3566 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3570 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3573 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3574 GtkTextBuffer *buffer;
3576 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3577 gtk_text_buffer_set_modified (buffer, modified);
3578 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3579 gtk_text_buffer_set_modified (buffer, modified);
3580 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3581 gtk_text_buffer_set_modified (buffer, modified);
3582 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3586 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3588 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3589 const char *account_name;
3590 GtkTextBuffer *buffer;
3592 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3593 if (gtk_text_buffer_get_modified (buffer))
3595 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3596 if (gtk_text_buffer_get_modified (buffer))
3598 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3599 if (gtk_text_buffer_get_modified (buffer))
3601 if (gtk_text_buffer_get_modified (priv->text_buffer))
3604 account_name = modest_selector_get_active_id (priv->from_field);
3605 if (priv->original_mailbox) {
3606 if (!account_name || strcmp (account_name, priv->original_mailbox))
3608 } else if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3619 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3621 ModestMsgEditWindowPrivate *priv = NULL;
3622 GSList *address_list = NULL;
3624 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3625 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3627 /* check if there's no recipient added */
3628 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3629 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3630 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3631 /* no recipient contents, then select contacts */
3632 modest_msg_edit_window_open_addressbook (window, NULL);
3637 g_object_ref (window);
3638 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field),
3639 (add_to_addressbook) ? &address_list : NULL)) {
3640 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3641 g_object_unref (window);
3644 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field),
3645 (add_to_addressbook) ? &address_list : NULL)) {
3646 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3647 g_object_unref (window);
3650 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field),
3651 (add_to_addressbook) ? &address_list : NULL)) {
3652 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3653 g_object_unref (window);
3657 /* Add contacts to address book */
3658 if (add_to_addressbook && address_list)
3659 modest_address_book_add_address_list (address_list);
3661 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3662 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3663 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3664 g_object_unref (window);
3671 modest_msg_edit_window_add_to_contacts (ModestMsgEditWindow *self)
3673 GSList *recipients = NULL;
3674 ModestMsgEditWindowPrivate *priv;
3675 gchar *joined, *after_remove, *to, *cc, *bcc;
3677 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3679 /* First of all check names */
3680 if (!modest_msg_edit_window_check_names (self, FALSE))
3683 if (!modest_msg_edit_window_has_pending_addresses (self))
3686 /* Don't add the from obviously */
3687 to = g_strdup (modest_recpt_editor_get_recipients ((ModestRecptEditor *) priv->to_field));
3688 cc = g_strdup (modest_recpt_editor_get_recipients ((ModestRecptEditor *) priv->cc_field));
3689 bcc = g_strdup (modest_recpt_editor_get_recipients ((ModestRecptEditor *) priv->bcc_field));
3691 joined = modest_text_utils_join_addresses (NULL, to, cc, bcc);
3696 after_remove = modest_text_utils_remove_duplicate_addresses (joined);
3699 recipients = modest_text_utils_split_addresses_list (after_remove);
3700 g_free (after_remove);
3703 /* Offer the user to add recipients to the address book */
3704 modest_address_book_add_address_list_with_selector (recipients, (GtkWindow *) self);
3705 g_slist_foreach (recipients, (GFunc) g_free, NULL); g_slist_free (recipients);
3710 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3711 ModestMsgEditWindow *window)
3713 modest_msg_edit_window_offer_attach_file (window);
3717 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3719 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3721 return priv->clipboard_text;
3725 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3727 ModestMsgEditWindow *window)
3729 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3730 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3733 /* It could happen that the window was already closed */
3734 if (!GTK_WIDGET_VISIBLE (window))
3737 g_object_ref (window);
3738 text = gtk_clipboard_wait_for_text (selection_clipboard);
3740 if (priv->clipboard_text != NULL) {
3741 g_free (priv->clipboard_text);
3743 priv->clipboard_text = text;
3745 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3747 g_object_unref (window);
3750 static gboolean clipboard_owner_change_idle (gpointer userdata)
3752 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3753 ModestMsgEditWindowPrivate *priv;
3755 gdk_threads_enter ();
3756 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3757 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3759 priv->clipboard_owner_idle = 0;
3760 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3761 gdk_threads_leave ();
3767 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3769 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3770 if (priv->clipboard_owner_idle == 0) {
3771 priv->clipboard_owner_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
3772 clipboard_owner_change_idle,
3773 g_object_ref (window),
3779 subject_field_move_cursor (GtkEntry *entry,
3780 GtkMovementStep step,
3785 /* It could happen that the window was already closed */
3786 if (!GTK_WIDGET_VISIBLE (window))
3789 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3793 update_window_title (ModestMsgEditWindow *window)
3795 ModestMsgEditWindowPrivate *priv = NULL;
3796 const gchar *subject;
3798 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3799 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3800 if (subject == NULL || subject[0] == '\0')
3801 subject = _("mail_va_new_email");
3803 modest_window_set_title (MODEST_WINDOW (window), subject);
3809 body_insert_text (GtkTextBuffer *buffer,
3810 GtkTextIter *location,
3813 ModestMsgEditWindow *window)
3815 GtkTextIter end_iter;
3822 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3824 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end_iter);
3826 offset = gtk_text_iter_get_offset (&end_iter);
3827 line = gtk_text_iter_get_line (&end_iter);
3831 while (text_offset < text + len) {
3832 if (*text_offset == '\n')
3834 if (text_lines + line >= MAX_BODY_LINES) {
3835 len = text_offset - text;
3841 utf8_len = g_utf8_strlen (text, len);
3843 if (line > MAX_BODY_LINES || offset + utf8_len > MAX_BODY_LENGTH) {
3844 g_signal_stop_emission_by_name (G_OBJECT (buffer), "insert-text");
3845 if (line <= MAX_BODY_LINES && offset < MAX_BODY_LENGTH)
3850 utf8_end = g_utf8_offset_to_pointer (text, MAX_BODY_LENGTH - offset);
3852 /* Prevent endless recursion */
3853 result = g_strndup (text, utf8_end - text);
3854 g_signal_handlers_block_by_func (G_OBJECT (buffer), G_CALLBACK (body_insert_text), window);
3855 g_signal_emit_by_name (G_OBJECT (buffer), "insert-text", location,
3856 (gpointer) result, (gpointer) (utf8_end - text),
3858 g_signal_handlers_unblock_by_func (G_OBJECT (buffer), G_CALLBACK (body_insert_text), window);
3862 if (line > MAX_BODY_LINES || offset + utf8_len > MAX_BODY_LENGTH) {
3863 if (priv->max_chars_banner == NULL) {
3864 #ifdef MODEST_TOOLKIT_HILDON2
3865 priv->max_chars_banner = hildon_banner_show_information (GTK_WIDGET (window), NULL,
3866 _CS_MAXIMUM_CHARACTERS_REACHED);
3867 g_object_weak_ref (G_OBJECT (priv->max_chars_banner), (GWeakNotify) max_chars_banner_unref, window);
3874 subject_field_changed (GtkEditable *editable,
3875 ModestMsgEditWindow *window)
3877 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3878 update_window_title (window);
3879 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3880 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3881 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3884 subject_field_insert_text (GtkEditable *editable,
3886 gint new_text_length,
3888 ModestMsgEditWindow *window)
3890 GString *result = g_string_new ("");
3892 gint result_len = 0;
3893 const gchar *entry_text = NULL;
3896 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3897 old_length = g_utf8_strlen (entry_text, -1);
3899 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3900 gunichar c = g_utf8_get_char_validated (current, 8);
3901 /* Invalid unichar, stop */
3907 result = g_string_append_unichar (result, c);
3911 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3912 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3915 /* Prevent endless recursion */
3916 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3917 g_signal_emit_by_name (editable, "insert-text",
3918 (gpointer) result->str, (gpointer) result->len,
3919 (gpointer) position, (gpointer) window);
3920 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3924 if (result_len + old_length > 1000) {
3925 modest_platform_system_banner (GTK_WIDGET (window), NULL,
3926 _CS_MAXIMUM_CHARACTERS_REACHED);
3928 g_string_free (result, TRUE);
3932 modest_msg_edit_window_toggle_isearch_toolbar (ModestMsgEditWindow *window,
3935 ModestMsgEditWindowPrivate *priv = NULL;
3937 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3938 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3940 gtk_widget_set_no_show_all (priv->isearch_toolbar, FALSE);
3943 gtk_widget_show_all (priv->isearch_toolbar);
3944 modest_isearch_toolbar_highlight_entry (MODEST_ISEARCH_TOOLBAR (priv->isearch_toolbar), TRUE);
3946 gtk_widget_hide_all (priv->isearch_toolbar);
3947 gtk_widget_grab_focus (priv->msg_body);
3952 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3954 GtkTextIter *match_start,
3955 GtkTextIter *match_end)
3957 GtkTextIter end_iter;
3958 gchar *str_casefold;
3961 gchar *range_casefold;
3964 gboolean result = FALSE;
3971 gtk_text_iter_forward_to_end (&end_iter);
3973 str_casefold = g_utf8_casefold (str, -1);
3974 str_chars_n = strlen (str);
3976 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3977 range_casefold = g_utf8_casefold (range_text, -1);
3978 range_chars_n = strlen (range_casefold);
3980 if (range_chars_n < str_chars_n) {
3981 g_free (str_casefold);
3982 g_free (range_text);
3983 g_free (range_casefold);
3987 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3988 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3989 if (!g_utf8_collate (range_subtext, str_casefold)) {
3990 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3992 if (!gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3993 match_start, match_end, NULL)) {
3994 g_debug ("Matched string with collate, but not matched in model");
3996 g_free (found_text);
3998 g_free (range_subtext);
4002 g_free (str_casefold);
4003 g_free (range_text);
4004 g_free (range_casefold);
4011 modest_msg_edit_window_isearch_toolbar_search (GtkWidget *widget,
4012 ModestMsgEditWindow *window)
4014 const gchar *current_search = NULL;
4015 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
4017 GtkTextIter selection_start, selection_end;
4018 GtkTextIter match_start, match_end;
4019 gboolean continue_search = FALSE;
4021 if (message_is_empty (window)) {
4022 g_free (priv->last_search);
4023 priv->last_search = NULL;
4024 modest_platform_system_banner (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
4028 current_search = modest_isearch_toolbar_get_search (MODEST_ISEARCH_TOOLBAR (widget));
4029 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
4030 g_free (priv->last_search);
4031 priv->last_search = NULL;
4032 /* Information banner about empty search */
4033 modest_platform_system_banner (NULL, NULL, _CS_FIND_REP_ENTER_TEXT);
4037 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
4038 continue_search = TRUE;
4040 g_free (priv->last_search);
4041 priv->last_search = g_strdup (current_search);
4044 if (continue_search) {
4045 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
4046 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
4047 &match_start, &match_end);
4049 modest_platform_system_banner (NULL, NULL, _HL_IB_FIND_COMPLETE);
4051 GtkTextIter buffer_start;
4052 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
4053 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
4054 &match_start, &match_end);
4056 modest_platform_system_banner (NULL, NULL, _HL_IB_FIND_NO_MATCHES);
4059 /* Mark as selected the string found in search */
4061 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
4062 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
4063 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
4065 g_free (priv->last_search);
4066 priv->last_search = NULL;
4071 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
4073 ModestMsgEditWindowPrivate *priv;
4075 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
4080 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
4083 ModestMsgEditWindowPrivate *priv;
4085 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
4090 modest_msg_edit_window_isearch_toolbar_close (GtkWidget *widget,
4091 ModestMsgEditWindow *window)
4093 modest_msg_edit_window_toggle_isearch_toolbar (window, FALSE);
4097 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
4100 ModestMsgEditWindowPrivate *priv;
4101 TnyHeader *header = NULL;
4103 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4104 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
4106 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
4108 if (priv->draft_msg != NULL) {
4109 g_object_unref (priv->draft_msg);
4112 if (draft != NULL) {
4113 g_object_ref (draft);
4114 header = tny_msg_get_header (draft);
4115 if (priv->msg_uid) {
4116 g_free (priv->msg_uid);
4117 priv->msg_uid = NULL;
4119 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
4122 priv->draft_msg = draft;
4126 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
4127 GtkTextIter *start, GtkTextIter *end,
4130 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
4131 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
4134 if (tag == NULL) return;
4135 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
4136 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
4137 replace_with_images (window, priv->images);
4142 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
4145 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
4147 g_return_if_fail (TNY_IS_MIME_PART (part));
4148 tny_list_prepend (priv->attachments, (GObject *) part);
4149 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
4150 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
4151 gtk_widget_show_all (priv->attachments_caption);
4152 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
4156 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
4158 ModestMsgEditWindowPrivate *priv;
4160 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
4161 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
4163 return priv->msg_uid;
4167 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
4168 ModestMsgEditWindowWidgetType widget_type)
4170 ModestMsgEditWindowPrivate *priv;
4172 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
4173 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
4175 switch (widget_type) {
4176 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
4177 return priv->msg_body;
4179 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
4180 return priv->to_field;
4182 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
4183 return priv->cc_field;
4185 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
4186 return priv->bcc_field;
4188 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
4189 return priv->subject_field;
4191 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
4192 return priv->attachments_view;
4200 remove_tags (WPTextBuffer *buffer)
4202 GtkTextIter start, end;
4204 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
4205 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
4207 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
4211 on_account_removed (TnyAccountStore *account_store,
4212 TnyAccount *account,
4215 /* Do nothing if it's a store account, because we use the
4216 transport to send the messages */
4217 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
4218 const gchar *parent_acc = NULL;
4219 const gchar *our_acc = NULL;
4221 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
4222 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
4223 /* Close this window if I'm showing a message of the removed account */
4224 if (strcmp (parent_acc, our_acc) == 0)
4225 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
4230 update_signature (ModestMsgEditWindow *self,
4231 const gchar *old_account,
4232 const gchar *new_account)
4234 ModestMsgEditWindowPrivate *priv;
4235 gboolean has_old_signature, has_new_signature;
4237 ModestAccountMgr *mgr;
4240 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4242 gtk_text_buffer_begin_user_action (priv->text_buffer);
4244 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
4245 mgr = modest_runtime_get_account_mgr ();
4249 signature = modest_account_mgr_get_signature_from_recipient (mgr, old_account, &has_old_signature);
4250 if (has_old_signature) {
4251 GtkTextIter match_start, match_end;
4253 MODEST_TEXT_UTILS_SIGNATURE_MARKER as it
4254 seems that the search has some problems
4255 with the blank space at the end */
4256 if (gtk_text_iter_forward_search (&iter, "--",
4257 GTK_TEXT_SEARCH_TEXT_ONLY,
4258 &match_start, NULL, NULL)) {
4259 gtk_text_buffer_get_end_iter (priv->text_buffer ,&match_end);
4260 gtk_text_buffer_delete (priv->text_buffer, &match_start, &match_end);
4262 } else if (gtk_text_iter_forward_search (&iter, _("mcen_ia_editor_original_message"), 0,
4263 &match_start, &match_end, NULL)) {
4267 gtk_text_buffer_get_end_iter (priv->text_buffer, &iter);
4272 priv->last_from_account = modest_selector_get_active_id (priv->from_field);
4273 signature = modest_account_mgr_get_signature_from_recipient (mgr, new_account, &has_new_signature);
4274 if (has_new_signature) {
4277 gchar *full_signature = g_strconcat ((gtk_text_iter_starts_line (&iter)) ? "" : "\n",
4278 MODEST_TEXT_UTILS_SIGNATURE_MARKER, "\n",
4280 is_rich = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
4282 WPTextBufferFormat *fmt;
4283 GdkColor style_color;
4284 if (!gtk_style_lookup_color (GTK_WIDGET (self)->style, "SecondaryTextColor", &style_color)) {
4285 gdk_color_parse ("grey", &style_color);
4287 fmt = g_new0 (WPTextBufferFormat, 1);
4288 fmt->color = style_color;
4289 fmt->cs.color = 0x1;
4290 wp_text_buffer_insert_with_attribute (WP_TEXT_BUFFER (priv->text_buffer), &iter,
4294 g_free (full_signature);
4296 gtk_text_buffer_insert (priv->text_buffer, &iter, full_signature, -1);
4300 gtk_text_buffer_end_user_action (priv->text_buffer);
4303 static void update_branding (ModestMsgEditWindow *self,
4304 const gchar *new_account)
4306 ModestMsgEditWindowPrivate *priv;
4307 ModestAccountMgr *mgr;
4308 const GdkPixbuf *new_icon = NULL;
4309 gchar *new_label = NULL;
4310 gboolean show = FALSE;
4312 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4314 mgr = modest_runtime_get_account_mgr ();
4316 modest_account_mgr_get_branding_from_recipient (mgr, new_account, &new_label, &new_icon, MODEST_ICON_SIZE_SMALL);
4318 gtk_image_set_from_pixbuf (GTK_IMAGE (priv->brand_icon), (GdkPixbuf *) new_icon);
4319 gtk_widget_show (priv->brand_icon);
4322 gtk_widget_hide (priv->brand_icon);
4325 gtk_label_set_text (GTK_LABEL (priv->brand_label), new_label);
4326 gtk_widget_show (priv->brand_label);
4330 gtk_widget_hide (priv->brand_label);
4334 gtk_widget_show (priv->brand_container);
4336 gtk_widget_hide (priv->brand_container);
4340 from_field_changed (GtkWidget *button,
4341 ModestMsgEditWindow *self)
4343 ModestMsgEditWindowPrivate *priv;
4344 gchar *old_account, *new_account;
4346 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4348 old_account = priv->last_from_account;
4349 new_account = modest_selector_get_active_id (priv->from_field);
4352 g_warning ("%s, could not get the new account", __FUNCTION__);
4356 /* If the From is the same do nothing */
4357 if (old_account && new_account && !strcmp (old_account, new_account))
4360 priv->last_from_account = new_account;
4362 update_signature (self, old_account, new_account);
4363 update_branding (self, new_account);
4367 typedef struct _MessageSettingsHelper {
4368 ModestMsgEditWindow *window;
4369 GSList *priority_group;
4370 GSList *format_group;
4371 GtkToggleButton *current_priority;
4372 GtkToggleButton *current_format;
4373 } MessageSettingsHelper;
4376 on_priority_toggle (GtkToggleButton *button,
4377 MessageSettingsHelper *helper)
4380 ModestMsgEditWindowPrivate *priv;
4382 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
4383 if (gtk_toggle_button_get_active (button)) {
4385 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
4386 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4387 if ((node_button != button) &&
4388 gtk_toggle_button_get_active (node_button)) {
4389 gtk_toggle_button_set_active (node_button, FALSE);
4392 helper->current_priority = button;
4394 gboolean found = FALSE;
4395 /* If no one is active, activate it again */
4396 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
4397 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4398 if (gtk_toggle_button_get_active (node_button)) {
4404 gtk_toggle_button_set_active (button, TRUE);
4410 on_format_toggle (GtkToggleButton *button,
4411 MessageSettingsHelper *helper)
4414 ModestMsgEditWindowPrivate *priv;
4416 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
4417 if (gtk_toggle_button_get_active (button)) {
4419 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
4420 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4421 if ((node_button != button) &&
4422 gtk_toggle_button_get_active (node_button)) {
4423 gtk_toggle_button_set_active (node_button, FALSE);
4426 helper->current_format = button;
4428 gboolean found = FALSE;
4429 /* If no one is active, activate it again */
4430 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
4431 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4432 if (gtk_toggle_button_get_active (node_button)) {
4438 gtk_toggle_button_set_active (button, TRUE);
4445 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
4450 GtkWidget *priority_hbox;
4451 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
4452 GtkWidget *captioned;
4453 GtkSizeGroup *title_sizegroup, *value_sizegroup;
4454 GtkWidget *format_hbox;
4455 GtkWidget *html_toggle, *text_toggle;
4456 ModestMsgEditWindowPrivate *priv;
4457 MessageSettingsHelper helper = {0,};
4459 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4460 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
4461 helper.window = window;
4462 helper.priority_group = NULL;
4463 helper.format_group = NULL;
4465 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4466 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4468 dialog = gtk_dialog_new_with_buttons (_("mcen_me_message_settings"), NULL,
4469 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
4470 _HL_DONE, GTK_RESPONSE_ACCEPT, NULL);
4471 vbox = gtk_vbox_new (FALSE, 0);
4472 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
4473 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DOUBLE, 0);
4474 gtk_container_add (GTK_CONTAINER (align), vbox);
4475 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), align);
4476 gtk_widget_show (align);
4477 gtk_widget_show (vbox);
4479 /* Priority toggles */
4480 priority_hbox = gtk_hbox_new (TRUE, 0);
4481 #ifdef MODEST_TOOLKIT_HILDON2
4482 high_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4484 high_toggle = gtk_toggle_button_new ();
4486 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
4487 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
4488 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
4489 #ifdef MODEST_TOOLKIT_HILDON2
4490 medium_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4492 medium_toggle = gtk_toggle_button_new ();
4494 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
4495 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
4496 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
4497 #ifdef MODEST_TOOLKIT_HILDON2
4498 low_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4500 low_toggle = gtk_toggle_button_new ();
4502 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
4503 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
4504 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
4505 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, TRUE, TRUE, 0);
4506 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, TRUE, TRUE, 0);
4507 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, TRUE, TRUE, 0);
4508 gtk_widget_show_all (priority_hbox);
4509 captioned = modest_toolkit_utils_create_captioned (title_sizegroup, value_sizegroup,
4510 _("mcen_me_editor_message_priority"), FALSE, priority_hbox);
4511 gtk_widget_show (captioned);
4512 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
4514 /* format toggles */
4515 format_hbox = gtk_hbox_new (TRUE, 0);
4516 #ifdef MODEST_TOOLKIT_HILDON2
4517 html_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4519 html_toggle = gtk_toggle_button_new ();
4521 gtk_button_set_label (GTK_BUTTON (html_toggle), _("mcen_me_editor_formatted_text"));
4522 helper.format_group = g_slist_prepend (helper.format_group, html_toggle);
4523 g_object_set_data (G_OBJECT (html_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_HTML));
4524 g_object_set_data (G_OBJECT (html_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_FORMATTED_TEXT));
4525 #ifdef MODEST_TOOLKIT_HILDON2
4526 text_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4528 text_toggle = gtk_toggle_button_new ();
4530 gtk_button_set_label (GTK_BUTTON (text_toggle), _("mcen_me_editor_plain_text"));
4531 helper.format_group = g_slist_prepend (helper.format_group, text_toggle);
4532 g_object_set_data (G_OBJECT (text_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_TEXT));
4533 g_object_set_data (G_OBJECT (text_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_PLAIN_TEXT));
4534 gtk_box_pack_start (GTK_BOX (format_hbox), html_toggle, TRUE, TRUE, 0);
4535 gtk_box_pack_start (GTK_BOX (format_hbox), text_toggle, TRUE, TRUE, 0);
4536 gtk_widget_show_all (format_hbox);
4537 gtk_widget_show (format_hbox);
4538 gtk_box_pack_start (GTK_BOX (vbox), format_hbox, FALSE, FALSE, 0);
4541 g_object_unref (title_sizegroup);
4542 g_object_unref (value_sizegroup);
4544 /* Set current values */
4545 switch (priv->priority_flags) {
4546 case TNY_HEADER_FLAG_HIGH_PRIORITY:
4547 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (high_toggle), TRUE);
4548 helper.current_priority = GTK_TOGGLE_BUTTON (high_toggle);
4550 case TNY_HEADER_FLAG_LOW_PRIORITY:
4551 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (low_toggle), TRUE);
4552 helper.current_priority = GTK_TOGGLE_BUTTON (low_toggle);
4555 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (medium_toggle), TRUE);
4556 helper.current_priority = GTK_TOGGLE_BUTTON (medium_toggle);
4560 switch (modest_msg_edit_window_get_format (window)) {
4561 case MODEST_MSG_EDIT_FORMAT_TEXT:
4562 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_toggle), TRUE);
4563 helper.current_format = GTK_TOGGLE_BUTTON (text_toggle);
4565 case MODEST_MSG_EDIT_FORMAT_HTML:
4567 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (html_toggle), TRUE);
4568 helper.current_format = GTK_TOGGLE_BUTTON (html_toggle);
4572 /* Signal connects */
4573 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4574 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4575 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4576 g_signal_connect (G_OBJECT (html_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4577 g_signal_connect (G_OBJECT (text_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4579 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
4580 GTK_WINDOW (dialog), GTK_WINDOW (window));
4582 /* Save settings if the user clicked on done */
4583 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
4584 TnyHeaderFlags flags;
4585 ModestMsgEditFormat old_format, new_format;
4587 /* Set priority flags */
4588 flags = (TnyHeaderFlags) g_object_get_data (G_OBJECT (helper.current_priority), "priority");
4589 if (priv->priority_flags != flags)
4590 modest_msg_edit_window_set_priority_flags (window, flags);
4592 /* Set edit format */
4593 old_format = modest_msg_edit_window_get_format (window);
4594 new_format = (ModestMsgEditFormat) g_object_get_data (G_OBJECT (helper.current_format), "format");
4595 if (old_format != new_format) {
4596 gint file_format = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (helper.current_format), "file-format"));
4597 modest_msg_edit_window_set_file_format (window, file_format);
4601 gtk_widget_destroy (dialog);
4602 g_slist_free (helper.priority_group);
4606 on_message_settings (GtkAction *action,
4607 ModestMsgEditWindow *window)
4609 modest_msg_edit_window_show_msg_settings_dialog (window);
4613 on_cc_button_toggled (GtkWidget *button,
4614 ModestMsgEditWindow *window)
4616 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4618 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
4619 modest_togglable_get_active (button));
4623 on_bcc_button_toggled (GtkWidget *button,
4624 ModestMsgEditWindow *window)
4626 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4628 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
4629 modest_togglable_get_active (button));
4633 setup_menu (ModestMsgEditWindow *self)
4635 ModestMsgEditWindowPrivate *priv = NULL;
4637 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
4639 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4641 /* Settings menu buttons */
4642 modest_window_add_to_menu (MODEST_WINDOW (self), _("mcen_me_editor_checknames"), NULL,
4643 MODEST_WINDOW_MENU_CALLBACK (modest_ui_actions_on_check_names),
4645 modest_window_add_to_menu (MODEST_WINDOW (self), _("mcen_me_viewer_addtocontacts"), NULL,
4646 MODEST_WINDOW_MENU_CALLBACK (modest_ui_actions_add_to_contacts),
4647 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_add_to_contacts));
4648 modest_window_add_to_menu (MODEST_WINDOW (self), _("mcen_me_inbox_undo"), "<Ctrl>z",
4649 MODEST_WINDOW_MENU_CALLBACK (modest_ui_actions_on_undo),
4650 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_undo));
4652 priv->cc_button = modest_toolkit_factory_create_check_menu (modest_runtime_get_toolkit_factory (),
4653 _("mcen_me_editor_showcc"));
4654 modest_togglable_set_active (priv->cc_button,
4656 modest_window_add_item_to_menu (MODEST_WINDOW (self), priv->cc_button, NULL);
4657 gtk_widget_show (priv->cc_button);
4658 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
4659 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
4661 priv->bcc_button = modest_toolkit_factory_create_check_menu (modest_runtime_get_toolkit_factory (),
4662 _("mcen_me_editor_showbcc"));
4663 gtk_widget_show (priv->bcc_button);
4664 modest_togglable_set_active (priv->bcc_button,
4666 modest_window_add_item_to_menu (MODEST_WINDOW (self), priv->bcc_button,
4668 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
4669 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
4671 modest_window_add_to_menu (MODEST_WINDOW (self), _("mcen_me_editor_attach_inlineimage"), NULL,
4672 MODEST_WINDOW_MENU_CALLBACK (modest_ui_actions_on_insert_image),
4673 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_set_style));
4674 modest_window_add_to_menu (MODEST_WINDOW (self), _("mcen_me_editor_add_attachment"), NULL,
4675 MODEST_WINDOW_MENU_CALLBACK (modest_msg_edit_window_add_attachment_clicked),
4677 modest_window_add_to_menu (MODEST_WINDOW (self), _("mcen_me_inbox_remove_attachments"), NULL,
4678 MODEST_WINDOW_MENU_CALLBACK (modest_ui_actions_on_remove_attachments),
4679 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
4680 modest_window_add_to_menu (MODEST_WINDOW (self), _("mcen_me_message_settings"), NULL,
4681 MODEST_WINDOW_MENU_CALLBACK (on_message_settings),
4683 modest_window_add_to_menu (MODEST_WINDOW (self), _("mcen_me_viewer_find"), "<Ctrl>f",
4684 MODEST_WINDOW_MENU_CALLBACK (modest_ui_actions_on_toggle_find_in_page),
4689 emit_open_addressbook (GtkButton *button,
4690 ModestRecptEditor *editor)
4692 g_signal_emit_by_name (G_OBJECT (editor), "open-addressbook");
4696 _create_addressbook_box (GtkSizeGroup *title_size_group, GtkSizeGroup *value_size_group,
4697 const gchar *label, GtkWidget *control)
4699 GtkWidget *abook_button;
4702 GtkWidget *label_widget;
4704 box = gtk_hbox_new (FALSE, 0);
4706 align = gtk_alignment_new (0.0, 0.0, 1.0, 0.0);
4707 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, 0, 0, MODEST_MARGIN_DEFAULT);
4709 #ifdef MODEST_TOOLKIT_HILDON2
4710 abook_button = hildon_gtk_button_new (HILDON_SIZE_FINGER_HEIGHT);
4712 abook_button = gtk_button_new ();
4714 label_widget = gtk_label_new (label);
4715 gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5);
4716 gtk_container_add (GTK_CONTAINER (abook_button), label_widget);
4718 gtk_container_add (GTK_CONTAINER (align), abook_button);
4719 gtk_widget_set_size_request (label_widget, 148 - MODEST_MARGIN_DOUBLE, -1);
4720 gtk_box_pack_start (GTK_BOX (box), align, FALSE, FALSE, 0);
4721 gtk_box_pack_start (GTK_BOX (box), control, TRUE, TRUE, 0);
4722 if (title_size_group)
4723 gtk_size_group_add_widget (title_size_group, label_widget);
4724 if (value_size_group)
4725 gtk_size_group_add_widget (value_size_group, control);
4727 g_signal_connect (G_OBJECT (abook_button), "clicked",
4728 G_CALLBACK (emit_open_addressbook), control);
4734 max_chars_banner_unref (ModestMsgEditWindow *self, GObject *old_ref)
4736 ModestMsgEditWindowPrivate *priv = NULL;
4738 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
4740 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4741 priv->max_chars_banner = NULL;
4745 has_pending_addresses (ModestRecptEditor *recpt_editor)
4747 const gchar *recipients = NULL;
4748 GSList *start_indexes = NULL, *end_indexes = NULL;
4749 GSList *current_start, *current_end;
4750 GtkTextBuffer *buffer;
4751 gint offset_delta = 0;
4753 gboolean has_recipients_to_add = FALSE;
4755 recipients = modest_recpt_editor_get_recipients (recpt_editor);
4756 last_length = g_utf8_strlen (recipients, -1);
4757 modest_text_utils_get_addresses_indexes (recipients, &start_indexes, &end_indexes);
4762 current_start = start_indexes;
4763 current_end = end_indexes;
4764 buffer = modest_recpt_editor_get_buffer (recpt_editor);
4766 while (current_start && !has_recipients_to_add) {
4768 gchar *start_ptr, *end_ptr;
4769 gint start_pos, end_pos;
4771 start_pos = (*((gint*) current_start->data)) + offset_delta;
4772 end_pos = (*((gint*) current_end->data)) + offset_delta;
4774 start_ptr = g_utf8_offset_to_pointer (recipients, start_pos);
4775 end_ptr = g_utf8_offset_to_pointer (recipients, end_pos);
4777 address = g_strstrip (g_strndup (start_ptr, end_ptr - start_ptr));
4779 if (modest_text_utils_validate_recipient (address, NULL)) {
4780 if (!modest_address_book_has_address (address)) {
4781 has_recipients_to_add = TRUE;
4784 current_start = g_slist_next (current_start);
4785 current_end = g_slist_next (current_end);
4787 return has_recipients_to_add;
4791 modest_msg_edit_window_has_pending_addresses (ModestMsgEditWindow *self)
4793 ModestMsgEditWindowPrivate *priv = NULL;
4795 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self), FALSE);
4797 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4799 if (!has_pending_addresses ((ModestRecptEditor *) priv->to_field) &&
4800 !has_pending_addresses ((ModestRecptEditor *) priv->cc_field) &&
4801 !has_pending_addresses ((ModestRecptEditor *) priv->bcc_field))