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 <modest-selector-picker.h>
48 #include <widgets/modest-recpt-editor.h>
49 #include <widgets/modest-attachments-view.h>
51 #include <modest-runtime.h>
53 #include "modest-platform.h"
54 #include "modest-icon-names.h"
55 #include "modest-widget-memory.h"
56 #include "modest-window-priv.h"
57 #include "modest-mail-operation.h"
58 #include "modest-tny-platform-factory.h"
59 #include "modest-tny-msg.h"
60 #include "modest-tny-folder.h"
61 #include "modest-tny-account.h"
62 #include "modest-address-book.h"
63 #include "modest-text-utils.h"
64 #include <tny-simple-list.h>
65 #include <modest-wp-text-view.h>
66 #include <wptextbuffer.h>
67 #include <hildon/hildon-pannable-area.h>
68 #include <hildon/hildon-touch-selector.h>
69 #include <hildon/hildon-picker-dialog.h>
70 #include "modest-msg-edit-window-ui-dimming.h"
72 #include "modest-hildon-includes.h"
73 #ifdef MODEST_HAVE_HILDON0_WIDGETS
74 #include <hildon-widgets/hildon-color-chooser.h>
76 #include "widgets/modest-msg-edit-window-ui.h"
77 #ifdef MODEST_HAVE_HILDON0_WIDGETS
78 #include <libgnomevfs/gnome-vfs-mime-utils.h>
80 #include <libgnomevfs/gnome-vfs-mime.h>
82 #include <modest-utils.h>
83 #include "modest-maemo-utils.h"
84 #include <modest-ui-constants.h>
87 #define DEFAULT_FONT_SIZE 3
88 #define DEFAULT_FONT 2
89 #define DEFAULT_SIZE_BUTTON_FONT_FAMILY "Sans"
90 #define DEFAULT_MAIN_VBOX_SPACING 6
91 #define SUBJECT_MAX_LENGTH 1000
92 #define IMAGE_MAX_WIDTH 560
93 #define DEFAULT_FONT_SCALE 1.5
94 #define ATTACHMENT_BUTTON_WIDTH 118
96 static gboolean is_wp_text_buffer_started = FALSE;
98 static void modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass);
99 static void modest_msg_edit_window_init (ModestMsgEditWindow *obj);
100 static void modest_msg_edit_window_finalize (GObject *obj);
102 static gboolean msg_body_focus (GtkWidget *focus, GdkEventFocus *event, gpointer userdata);
103 static void body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
104 static void recpt_field_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
106 static void text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window);
107 static void text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window);
108 static void text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window);
109 static void text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
110 GtkTextIter *start, GtkTextIter *end,
112 static void text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id);
113 static void subject_field_changed (GtkEditable *editable, ModestMsgEditWindow *window);
114 static void subject_field_insert_text (GtkEditable *editable,
116 gint new_text_length,
118 ModestMsgEditWindow *window);
119 static void modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
121 static void modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
123 static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
124 ModestRecptEditor *editor);
125 static void modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
126 ModestMsgEditWindow *window);
128 /* ModestWindow methods implementation */
129 static void modest_msg_edit_window_disconnect_signals (ModestWindow *window);
130 static void modest_msg_edit_window_show_toolbar (ModestWindow *window,
131 gboolean show_toolbar);
132 static void modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
134 ModestMsgEditWindow *window);
135 static void modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window);
136 static void subject_field_move_cursor (GtkEntry *entry,
137 GtkMovementStep step,
141 static void update_window_title (ModestMsgEditWindow *window);
144 static void modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
145 ModestMsgEditWindow *window);
146 static void modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
147 ModestMsgEditWindow *window);
148 static gboolean gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
150 GtkTextIter *match_start,
151 GtkTextIter *match_end);
153 static void remove_tags (WPTextBuffer *buffer);
155 static void on_account_removed (TnyAccountStore *account_store,
159 static void init_window (ModestMsgEditWindow *obj);
161 gboolean scroll_drag_timeout (gpointer userdata);
162 static void correct_scroll (ModestMsgEditWindow *w);
163 static void correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused);
164 static void text_buffer_end_user_action (GtkTextBuffer *buffer,
165 ModestMsgEditWindow *userdata);
166 static void text_buffer_mark_set (GtkTextBuffer *buffer,
169 ModestMsgEditWindow *userdata);
170 static void on_message_settings (GtkAction *action,
171 ModestMsgEditWindow *window);
172 static void setup_menu (ModestMsgEditWindow *self);
174 static void from_field_changed (HildonPickerButton *button,
175 ModestMsgEditWindow *self);
176 static void font_size_clicked (GtkToolButton *button,
177 ModestMsgEditWindow *window);
178 static void font_face_clicked (GtkToolButton *button,
179 ModestMsgEditWindow *window);
180 static void DEBUG_BUFFER (WPTextBuffer *buffer)
184 g_message ("BEGIN BUFFER OF SIZE %d", gtk_text_buffer_get_char_count (GTK_TEXT_BUFFER (buffer)));
186 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &iter);
187 while (!gtk_text_iter_is_end (&iter)) {
188 GString *output = g_string_new ("");
189 GSList *toggled_tags;
192 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
193 g_string_append_printf (output, "%d: CLOSED [ ", gtk_text_iter_get_offset (&iter));
194 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
195 GtkTextTag *tag = (GtkTextTag *) node->data;
197 g_object_get (G_OBJECT (tag), "name", &name, NULL);
198 output = g_string_append (output, name);
199 g_string_append (output, " ");
201 output = g_string_append (output, "] OPENED [ ");
202 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
203 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
204 GtkTextTag *tag = (GtkTextTag *) node->data;
206 g_object_get (G_OBJECT (tag), "name", &name, NULL);
207 output = g_string_append (output, name);
208 g_string_append (output, " ");
210 output = g_string_append (output, "]\n");
211 g_message ("%s", output->str);
212 g_string_free (output, TRUE);
213 gtk_text_iter_forward_to_tag_toggle (&iter, NULL);
215 g_message ("END BUFFER");
219 static const GtkActionEntry hildon2_msg_edit_action_entries [] = {
220 { "MessageSettings", NULL, N_("mcen_me_message_settings"), NULL, NULL, G_CALLBACK (on_message_settings)},
224 /* static gboolean */
225 /* on_key_pressed (GtkWidget *self, */
226 /* GdkEventKey *event, */
227 /* gpointer user_data); */
229 /* list my signals */
236 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
237 struct _ModestMsgEditWindowPrivate {
239 GtkWidget *header_box;
241 ModestPairList *from_field_protos;
242 GtkWidget *from_field;
243 gchar *last_from_account;
244 gchar *original_account_name;
249 gchar *original_mailbox;
253 GtkWidget *bcc_field;
254 GtkWidget *subject_field;
255 GtkWidget *attachments_view;
256 GtkWidget *priority_icon;
257 GtkWidget *subject_box;
258 GtkWidget *add_attachment_button;
260 GtkWidget *cc_caption;
261 GtkWidget *bcc_caption;
262 gboolean update_caption_visibility;
263 GtkWidget *attachments_caption;
265 GtkTextBuffer *text_buffer;
267 GtkWidget *font_size_toolitem;
268 GtkWidget *font_face_toolitem;
269 GtkWidget *font_color_button;
270 GtkWidget *font_color_toolitem;
271 GSList *font_items_group;
272 GtkTreeModel *faces_model;
273 gint current_face_index;
274 GtkWidget *font_tool_button_label;
275 GtkTreeModel *sizes_model;
276 gint current_size_index;
277 GtkWidget *size_tool_button_label;
279 GtkWidget *find_toolbar;
282 GtkWidget *font_dialog;
285 guint correct_scroll_idle;
286 guint scroll_drag_timeout_id;
290 TnyList *attachments;
295 TnyHeaderFlags priority_flags;
297 gboolean can_undo, can_redo;
298 gulong clipboard_change_handler_id;
299 gulong default_clipboard_change_handler_id;
300 gulong account_removed_handler_id;
301 guint clipboard_owner_idle;
302 gchar *clipboard_text;
311 GtkWidget *cc_button;
312 GtkWidget *bcc_button;
315 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
316 MODEST_TYPE_MSG_EDIT_WINDOW, \
317 ModestMsgEditWindowPrivate))
319 static GtkWindowClass *parent_class = NULL;
321 /* uncomment the following if you have defined any signals */
322 /* static guint signals[LAST_SIGNAL] = {0}; */
325 modest_msg_edit_window_get_type (void)
327 static GType my_type = 0;
329 static const GTypeInfo my_info = {
330 sizeof(ModestMsgEditWindowClass),
331 NULL, /* base init */
332 NULL, /* base finalize */
333 (GClassInitFunc) modest_msg_edit_window_class_init,
334 NULL, /* class finalize */
335 NULL, /* class data */
336 sizeof(ModestMsgEditWindow),
338 (GInstanceInitFunc) modest_msg_edit_window_init,
341 my_type = g_type_register_static (MODEST_TYPE_HILDON2_WINDOW,
342 "ModestMsgEditWindow",
350 save_state (ModestWindow *self)
352 modest_widget_memory_save (modest_runtime_get_conf(),
353 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
358 restore_settings (ModestMsgEditWindow *self)
360 ModestConf *conf = NULL;
362 conf = modest_runtime_get_conf ();
364 /* Dim at start clipboard actions */
365 modest_widget_memory_restore (conf, G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
370 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
372 GObjectClass *gobject_class;
373 ModestWindowClass *modest_window_class;
374 gobject_class = (GObjectClass*) klass;
375 modest_window_class = (ModestWindowClass*) klass;
377 parent_class = g_type_class_peek_parent (klass);
378 gobject_class->finalize = modest_msg_edit_window_finalize;
380 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
381 modest_window_class->save_state_func = save_state;
382 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
384 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
388 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
390 ModestMsgEditWindowPrivate *priv;
391 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
393 priv->msg_body = NULL;
394 priv->from_field = NULL;
395 priv->to_field = NULL;
396 priv->cc_field = NULL;
397 priv->bcc_field = NULL;
398 priv->subject_field = NULL;
399 priv->attachments = TNY_LIST (tny_simple_list_new ());
400 priv->images = TNY_LIST (tny_simple_list_new ());
401 priv->images_size = 0;
402 priv->images_count = 0;
405 priv->cc_caption = NULL;
406 priv->bcc_caption = NULL;
407 priv->update_caption_visibility = FALSE;
409 priv->priority_flags = 0;
411 priv->find_toolbar = NULL;
412 priv->last_search = NULL;
414 priv->draft_msg = NULL;
415 priv->outbox_msg = NULL;
416 priv->msg_uid = NULL;
418 priv->can_undo = FALSE;
419 priv->can_redo = FALSE;
420 priv->clipboard_change_handler_id = 0;
421 priv->default_clipboard_change_handler_id = 0;
422 priv->account_removed_handler_id = 0;
423 priv->clipboard_owner_idle = 0;
424 priv->clipboard_text = NULL;
427 priv->scroll_drag_timeout_id = 0;
428 priv->correct_scroll_idle = 0;
429 priv->last_upper = 0.0;
431 priv->font_dialog = NULL;
432 priv->app_menu = NULL;
434 priv->references = NULL;
435 priv->in_reply_to = NULL;
437 if (!is_wp_text_buffer_started) {
438 is_wp_text_buffer_started = TRUE;
439 wp_text_buffer_library_init ();
444 hildon_program_add_window (hildon_program_get_instance(),
450 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
452 static ModestPairList*
453 get_transports (void)
455 GSList *transports = NULL;
457 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
458 GSList *accounts = modest_account_mgr_account_names (account_mgr,
459 TRUE /* only enabled accounts. */);
461 GSList *cursor = accounts;
463 gchar *account_name = cursor->data;
466 gchar *transport_account;
467 gboolean multi_mailbox = FALSE;
470 transport_account = modest_account_mgr_get_server_account_name (modest_runtime_get_account_mgr (),
472 TNY_ACCOUNT_TYPE_TRANSPORT);
473 if (transport_account) {
474 proto = modest_account_mgr_get_string (modest_runtime_get_account_mgr (), transport_account,
475 MODEST_ACCOUNT_PROTO, TRUE);
477 ModestProtocol *protocol =
478 modest_protocol_registry_get_protocol_by_name (modest_runtime_get_protocol_registry (),
479 MODEST_PROTOCOL_REGISTRY_TRANSPORT_PROTOCOLS,
481 if (MODEST_IS_ACCOUNT_PROTOCOL (protocol)) {
482 ModestPairList *pair_list;
483 pair_list = modest_account_protocol_get_from_list (MODEST_ACCOUNT_PROTOCOL (protocol),
486 transports = g_slist_concat (transports, pair_list);
487 multi_mailbox = TRUE;
494 if (!multi_mailbox) {
495 gchar *from_string = NULL;
497 from_string = modest_account_mgr_get_from_string (account_mgr,
499 if (from_string && account_name) {
500 gchar *name = account_name;
501 ModestPair *pair = modest_pair_new ((gpointer) name,
502 (gpointer) from_string , TRUE);
503 transports = g_slist_prepend (transports, pair);
508 cursor = cursor->next;
510 g_slist_free (accounts); /* only free the accounts, not the elements,
511 * because they are used in the pairlist */
515 static void window_focus (GtkWindow *window,
519 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
523 scroll_drag_timeout (gpointer userdata)
525 ModestMsgEditWindow *win = (ModestMsgEditWindow *) userdata;
526 ModestMsgEditWindowPrivate *priv;
528 /* It could happen that the window was already closed */
529 if (!GTK_WIDGET_VISIBLE (win))
532 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(win);
534 correct_scroll_without_drag_check (win, TRUE);
536 priv->scroll_drag_timeout_id = 0;
542 correct_scroll_without_drag_check_idle (gpointer userdata)
544 ModestMsgEditWindow *w = (ModestMsgEditWindow *) userdata;
545 ModestMsgEditWindowPrivate *priv;
547 GdkRectangle rectangle;
548 gint offset_min, offset_max;
552 /* It could happen that the window was already closed */
553 if (!GTK_WIDGET_VISIBLE (w))
556 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
558 insert = gtk_text_buffer_get_insert (priv->text_buffer);
559 gtk_text_buffer_get_iter_at_mark (priv->text_buffer, &iter, insert);
561 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &iter, &rectangle);
562 offset_min = priv->msg_body->allocation.y + rectangle.y;
563 offset_max = offset_min + rectangle.height;
565 vadj = hildon_pannable_area_get_vadjustment (HILDON_PANNABLE_AREA (priv->pannable));
566 offset_min = MAX (offset_min - 48, 0);
567 offset_max = MIN (offset_max + 48, vadj->upper);
569 gtk_adjustment_clamp_page (vadj, (gdouble) offset_min, (gdouble) offset_max);
571 priv->correct_scroll_idle = 0;
576 correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused)
578 ModestMsgEditWindowPrivate *priv;
580 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
582 if (only_if_focused && !gtk_widget_is_focus (priv->msg_body))
585 if (priv->correct_scroll_idle > 0) {
589 priv->correct_scroll_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
590 (GSourceFunc) correct_scroll_without_drag_check_idle,
596 correct_scroll (ModestMsgEditWindow *w)
598 ModestMsgEditWindowPrivate *priv;
600 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
601 if (gtk_grab_get_current () == priv->msg_body) {
602 if (priv->scroll_drag_timeout_id == 0) {
603 priv->scroll_drag_timeout_id = g_timeout_add_full (G_PRIORITY_DEFAULT,
605 (GSourceFunc) scroll_drag_timeout,
612 correct_scroll_without_drag_check (w, TRUE);
616 text_buffer_end_user_action (GtkTextBuffer *buffer,
617 ModestMsgEditWindow *userdata)
620 correct_scroll (userdata);
624 text_buffer_mark_set (GtkTextBuffer *buffer,
627 ModestMsgEditWindow *userdata)
629 gtk_text_buffer_begin_user_action (buffer);
630 gtk_text_buffer_end_user_action (buffer);
634 cut_clipboard_check (GtkTextView *text_view,
637 GtkTextBuffer *buffer;
639 buffer = gtk_text_view_get_buffer (text_view);
640 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
641 g_signal_stop_emission_by_name ((gpointer )text_view, "cut-clipboard");
646 copy_clipboard_check (GtkTextView *text_view,
649 GtkTextBuffer *buffer;
651 buffer = gtk_text_view_get_buffer (text_view);
652 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
653 g_signal_stop_emission_by_name ((gpointer )text_view, "copy-clipboard");
658 attachment_deleted (ModestAttachmentsView *attachments_view,
661 modest_msg_edit_window_remove_attachments (MODEST_MSG_EDIT_WINDOW (user_data),
666 connect_signals (ModestMsgEditWindow *obj)
668 ModestMsgEditWindowPrivate *priv;
670 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
672 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
673 G_CALLBACK (text_buffer_refresh_attributes), obj);
674 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
675 G_CALLBACK (text_buffer_can_undo), obj);
676 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
677 G_CALLBACK (text_buffer_can_redo), obj);
678 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
679 G_CALLBACK (body_changed), obj);
680 g_signal_connect (G_OBJECT (priv->text_buffer), "modified-changed",
681 G_CALLBACK (body_changed), obj);
682 g_signal_connect (G_OBJECT (priv->text_buffer), "end-user-action",
683 G_CALLBACK (text_buffer_end_user_action), obj);
684 g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
685 G_CALLBACK (text_buffer_mark_set), obj);
686 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
687 G_CALLBACK (text_buffer_apply_tag), obj);
688 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
689 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
690 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
691 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
692 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
693 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
695 g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
696 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
697 g_signal_connect (G_OBJECT (priv->from_field), "value-changed",
698 G_CALLBACK (from_field_changed), obj);
700 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
701 G_CALLBACK (msg_body_focus), obj);
702 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
703 G_CALLBACK (msg_body_focus), obj);
704 g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
705 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
706 "changed", G_CALLBACK (recpt_field_changed), obj);
707 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
708 "changed", G_CALLBACK (recpt_field_changed), obj);
709 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
710 "changed", G_CALLBACK (recpt_field_changed), obj);
711 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
712 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
713 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
715 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
716 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
718 priv->clipboard_change_handler_id =
719 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
720 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
721 priv->default_clipboard_change_handler_id =
722 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
723 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
725 g_signal_connect (G_OBJECT (priv->msg_body), "cut-clipboard", G_CALLBACK (cut_clipboard_check), NULL);
726 g_signal_connect (G_OBJECT (priv->msg_body), "copy-clipboard", G_CALLBACK (copy_clipboard_check), NULL);
727 g_signal_connect (G_OBJECT (priv->attachments_view), "delete", G_CALLBACK (attachment_deleted), obj);
731 init_wp_text_view_style ()
733 static gboolean initialized = FALSE;
736 gtk_rc_parse_string ("class \"WPTextView\" style \"fremantle-textview\"");
742 init_window (ModestMsgEditWindow *obj)
744 GtkWidget *to_caption, *subject_caption;
745 GtkWidget *main_vbox;
746 GtkWidget *add_attachment_align;
747 ModestMsgEditWindowPrivate *priv;
748 GtkActionGroup *action_group;
749 ModestWindowPrivate *parent_priv;
750 GdkPixbuf *window_icon = NULL;
751 GError *error = NULL;
753 GtkSizeGroup *title_size_group;
754 GtkSizeGroup *value_size_group;
755 GtkWidget *attachment_icon;
756 GtkWidget *window_box;
757 GtkWidget *window_align;
758 #if (GTK_MINOR_VERSION >= 10)
759 GdkAtom deserialize_type;
762 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
763 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
765 parent_priv->ui_manager = gtk_ui_manager_new();
766 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
767 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
769 /* Add common actions */
770 gtk_action_group_add_actions (action_group,
771 modest_msg_edit_action_entries,
772 G_N_ELEMENTS (modest_msg_edit_action_entries),
774 gtk_action_group_add_actions (action_group,
775 hildon2_msg_edit_action_entries,
776 G_N_ELEMENTS (hildon2_msg_edit_action_entries),
778 gtk_action_group_add_toggle_actions (action_group,
779 modest_msg_edit_toggle_action_entries,
780 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
782 gtk_action_group_add_radio_actions (action_group,
783 modest_msg_edit_alignment_radio_action_entries,
784 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
786 G_CALLBACK (modest_ui_actions_on_change_justify),
788 gtk_action_group_add_radio_actions (action_group,
789 modest_msg_edit_priority_action_entries,
790 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
792 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
794 gtk_action_group_add_radio_actions (action_group,
795 modest_msg_edit_file_format_action_entries,
796 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
797 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
798 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
800 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
801 g_object_unref (action_group);
803 /* Load the UI definition */
804 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
807 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
808 g_clear_error (&error);
811 /* Add accelerators */
812 gtk_window_add_accel_group (GTK_WINDOW (obj),
813 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
815 parent_priv->menubar = NULL;
817 title_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
818 value_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
820 /* Note: This ModestPairList* must exist for as long as the picker
821 * that uses it, because the ModestSelectorPicker uses the ID opaquely,
822 * so it can't know how to manage its memory. */
823 priv->from_field = modest_selector_picker_new (MODEST_EDITABLE_SIZE,
824 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL,
826 modest_maemo_utils_set_hbutton_layout (title_size_group, value_size_group,
827 _("mail_va_from"), priv->from_field);
829 priv->to_field = modest_recpt_editor_new ();
830 priv->cc_field = modest_recpt_editor_new ();
831 priv->bcc_field = modest_recpt_editor_new ();
832 priv->subject_box = gtk_hbox_new (FALSE, MODEST_MARGIN_NONE);
833 priv->priority_icon = gtk_image_new ();
834 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->priority_icon, FALSE, FALSE, 0);
835 priv->subject_field = hildon_entry_new (MODEST_EDITABLE_SIZE);
836 gtk_entry_set_max_length (GTK_ENTRY (priv->subject_field) ,SUBJECT_MAX_LENGTH);
837 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
838 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
839 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
840 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->subject_field, TRUE, TRUE, 0);
841 priv->add_attachment_button = hildon_button_new (MODEST_EDITABLE_SIZE, HILDON_BUTTON_ARRANGEMENT_VERTICAL);
842 gtk_widget_set_size_request (priv->add_attachment_button, ATTACHMENT_BUTTON_WIDTH, -1);
843 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
844 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
845 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, HILDON_ICON_SIZE_FINGER);
846 hildon_button_set_image (HILDON_BUTTON (priv->add_attachment_button), attachment_icon);
847 add_attachment_align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
848 gtk_alignment_set_padding (GTK_ALIGNMENT (add_attachment_align), 0, 0, MODEST_MARGIN_DEFAULT, 0);
849 gtk_container_add (GTK_CONTAINER (add_attachment_align), priv->add_attachment_button);
850 gtk_box_pack_start (GTK_BOX (priv->subject_box), add_attachment_align, FALSE, FALSE, 0);
851 priv->attachments_view = modest_attachments_view_new (NULL);
852 modest_attachments_view_set_style (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
853 MODEST_ATTACHMENTS_VIEW_STYLE_NO_FOCUS);
855 priv->header_box = gtk_vbox_new (FALSE, 0);
857 to_caption = modest_maemo_utils_create_captioned_with_size_type
858 (title_size_group, value_size_group,
859 _("mail_va_to"), FALSE, priv->to_field,
860 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
861 priv->cc_caption = modest_maemo_utils_create_captioned_with_size_type
862 (title_size_group, value_size_group,
863 _("mail_va_cc"), FALSE, priv->cc_field,
864 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
865 priv->bcc_caption = modest_maemo_utils_create_captioned_with_size_type
866 (title_size_group, value_size_group,
867 _("mail_va_hotfix1"), FALSE, priv->bcc_field,
868 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
869 subject_caption = modest_maemo_utils_create_captioned (title_size_group, value_size_group,
870 _("mail_va_subject"), FALSE, priv->subject_box);
871 priv->attachments_caption = modest_maemo_utils_create_captioned_with_size_type (title_size_group, value_size_group,
872 _("mail_va_attachment"),
874 priv->attachments_view,
875 HILDON_SIZE_AUTO_WIDTH |
876 HILDON_SIZE_AUTO_HEIGHT);
877 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), value_size_group); */
878 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), value_size_group); */
879 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), value_size_group); */
880 g_object_unref (title_size_group);
881 g_object_unref (value_size_group);
883 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->from_field, FALSE, FALSE, 0);
884 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
885 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
886 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
887 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
888 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
889 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
891 init_wp_text_view_style ();
893 priv->msg_body = modest_wp_text_view_new ();
896 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
897 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
898 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
899 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
900 #if (GTK_MINOR_VERSION >= 10)
901 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
902 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
904 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
905 deserialize_type, TRUE);
907 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
909 priv->find_toolbar = hildon_find_toolbar_new (NULL);
910 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
912 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
914 priv->pannable = hildon_pannable_area_new ();
916 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
917 window_align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
918 gtk_alignment_set_padding (GTK_ALIGNMENT (window_align), 0, 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DEFAULT);
920 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
921 gtk_box_pack_start (GTK_BOX(main_vbox), priv->msg_body, TRUE, TRUE, 0);
922 gtk_container_add (GTK_CONTAINER (window_align), main_vbox);
924 hildon_pannable_area_add_with_viewport (HILDON_PANNABLE_AREA (priv->pannable), window_align);
925 gtk_widget_show_all (GTK_WIDGET(priv->pannable));
927 window_box = gtk_vbox_new (FALSE, 0);
928 gtk_container_add (GTK_CONTAINER(obj), window_box);
930 gtk_box_pack_start (GTK_BOX (window_box), priv->pannable, TRUE, TRUE, 0);
932 /* Set window icon */
933 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
935 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
936 g_object_unref (window_icon);
941 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
943 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
945 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
946 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
947 priv->clipboard_change_handler_id))
948 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
949 priv->clipboard_change_handler_id);
950 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
951 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
952 priv->default_clipboard_change_handler_id))
953 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
954 priv->default_clipboard_change_handler_id);
956 if (priv->account_removed_handler_id &&
957 g_signal_handler_is_connected (modest_runtime_get_account_store (),
958 priv->account_removed_handler_id))
959 g_signal_handler_disconnect(modest_runtime_get_account_store (),
960 priv->account_removed_handler_id);
964 modest_msg_edit_window_finalize (GObject *obj)
966 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
968 /* Sanity check: shouldn't be needed, the window mgr should
969 call this function before */
970 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
972 if (priv->font_dialog != NULL) {
973 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
976 if (priv->clipboard_text != NULL) {
977 g_free (priv->clipboard_text);
978 priv->clipboard_text = NULL;
981 if (priv->draft_msg != NULL) {
982 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
983 if (TNY_IS_HEADER (header)) {
984 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
985 modest_window_mgr_unregister_header (mgr, header);
987 g_object_unref (priv->draft_msg);
988 priv->draft_msg = NULL;
990 if (priv->outbox_msg != NULL) {
991 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
992 if (TNY_IS_HEADER (header)) {
993 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
994 modest_window_mgr_unregister_header (mgr, header);
996 g_object_unref (priv->outbox_msg);
997 priv->outbox_msg = NULL;
999 if (priv->correct_scroll_idle > 0) {
1000 g_source_remove (priv->correct_scroll_idle);
1001 priv->correct_scroll_idle = 0;
1003 if (priv->scroll_drag_timeout_id > 0) {
1004 g_source_remove (priv->scroll_drag_timeout_id);
1005 priv->scroll_drag_timeout_id = 0;
1007 if (priv->clipboard_owner_idle > 0) {
1008 g_source_remove (priv->clipboard_owner_idle);
1009 priv->clipboard_owner_idle = 0;
1011 if (priv->original_account_name)
1012 g_free (priv->original_account_name);
1013 if (priv->original_mailbox)
1014 g_free (priv->original_mailbox);
1015 g_free (priv->msg_uid);
1016 g_free (priv->last_search);
1017 g_free (priv->references);
1018 g_free (priv->in_reply_to);
1019 g_object_unref (priv->faces_model);
1020 g_object_unref (priv->sizes_model);
1021 g_object_unref (priv->attachments);
1022 g_object_unref (priv->images);
1024 /* This had to stay alive for as long as the picker that used it: */
1025 modest_pair_list_free (priv->from_field_protos);
1027 G_OBJECT_CLASS(parent_class)->finalize (obj);
1031 pixbuf_size_prepared (GdkPixbufLoader *loader,
1034 ModestMsgEditWindow *self)
1036 gint new_height, new_width;
1039 new_height = height;
1043 if (width > IMAGE_MAX_WIDTH) {
1044 new_height = height * IMAGE_MAX_WIDTH / width;
1045 new_width = IMAGE_MAX_WIDTH;
1048 gdk_pixbuf_loader_set_size (loader, new_width, new_height);
1052 pixbuf_from_stream (TnyStream *stream,
1053 const gchar *mime_type,
1054 guint64 *stream_size,
1055 ModestMsgEditWindow *self)
1057 GdkPixbufLoader *loader;
1060 GError *error = NULL;
1064 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
1066 if (loader == NULL) {
1071 g_signal_connect (G_OBJECT (loader), "size-prepared", G_CALLBACK (pixbuf_size_prepared), self);
1073 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (self), TRUE);
1075 tny_stream_reset (TNY_STREAM (stream));
1076 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
1077 unsigned char read_buffer[128];
1079 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
1081 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
1084 /* Allow some UI responsiveness */
1085 while (gtk_events_pending ())
1086 gtk_main_iteration ();
1088 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (self), FALSE);
1090 gdk_pixbuf_loader_close (loader, &error);
1093 g_error_free (error);
1094 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1096 g_object_ref (pixbuf);
1097 g_object_unref (loader);
1102 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1103 GdkPixbuf *new_pixbuf;
1105 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1106 gdk_pixbuf_get_width (pixbuf);
1107 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1108 g_object_unref (pixbuf);
1109 pixbuf = new_pixbuf;
1113 *stream_size = size;
1119 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1121 ModestMsgEditWindowPrivate *priv;
1124 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1126 g_object_ref (self);
1127 for (iter = tny_list_create_iterator (attachments);
1128 !tny_iterator_is_done (iter);
1129 tny_iterator_next (iter)) {
1130 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1131 const gchar *cid = tny_mime_part_get_content_id (part);
1132 const gchar *mime_type = tny_mime_part_get_content_type (part);
1133 if ((cid != NULL)&&(mime_type != NULL)) {
1134 guint64 stream_size;
1135 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1136 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, self);
1139 g_object_unref (stream);
1141 if (pixbuf != NULL) {
1142 priv->images_count ++;
1143 priv->images_size += stream_size;
1144 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1145 g_object_unref (pixbuf);
1148 g_object_unref (part);
1150 g_object_unref (iter);
1151 g_object_unref (self);
1155 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1157 TnyMimePart *parent = NULL;
1158 const gchar *content_type = NULL;
1159 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1161 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1163 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1164 parent = g_object_ref (msg);
1165 } else if (content_type && !g_strcasecmp (content_type, "multipart/mixed")) {
1166 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1169 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1170 iter = tny_list_create_iterator (parts);
1171 while (!tny_iterator_is_done (iter)) {
1173 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1174 content_type = tny_mime_part_get_content_type (part);
1175 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1179 g_object_unref (part);
1181 tny_iterator_next (iter);
1183 g_object_unref (iter);
1184 g_object_unref (parts);
1187 if (parent != NULL) {
1188 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1191 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1192 iter = tny_list_create_iterator (parts);
1193 while (!tny_iterator_is_done (iter)) {
1195 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1196 content_type = tny_mime_part_get_content_type (part);
1197 if (content_type && g_str_has_prefix (content_type, "image/")) {
1198 tny_list_prepend (priv->images, (GObject *) part);
1200 g_object_unref (part);
1201 tny_iterator_next (iter);
1203 g_object_unref (iter);
1204 g_object_unref (parts);
1205 g_object_unref (parent);
1210 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1213 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1215 for (iter = tny_list_create_iterator (attachments) ;
1216 !tny_iterator_is_done (iter);
1217 tny_iterator_next (iter)) {
1218 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1219 const gchar *cid = tny_mime_part_get_content_id (part);
1221 char *invalid = NULL;
1222 gint int_cid = strtol (cid, &invalid, 10);
1223 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1224 priv->next_cid = int_cid + 1;
1227 g_object_unref (part);
1229 g_object_unref (iter);
1233 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1236 gchar *to, *cc, *bcc, *subject;
1238 ModestMsgEditWindowPrivate *priv;
1239 ModestWindowPrivate *parent_priv;
1241 TnyHeaderFlags priority_flags;
1242 TnyFolder *msg_folder;
1243 gboolean is_html = FALSE;
1244 gboolean field_view_set;
1246 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1247 g_return_if_fail (TNY_IS_MSG (msg));
1249 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1250 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1252 header = tny_msg_get_header (msg);
1253 to = tny_header_dup_to (header);
1254 cc = tny_header_dup_cc (header);
1255 bcc = tny_header_dup_bcc (header);
1256 subject = tny_header_dup_subject (header);
1258 modest_tny_msg_get_references (TNY_MSG (msg), NULL, &(priv->references), &(priv->in_reply_to));
1259 priority_flags = tny_header_get_priority (header);
1262 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
1264 field_view_set = TRUE;
1266 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
1267 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1268 gtk_widget_show (priv->cc_caption);
1269 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1270 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1271 gtk_widget_hide (priv->cc_caption);
1272 field_view_set = FALSE;
1274 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button), field_view_set);
1276 field_view_set = TRUE;
1278 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
1279 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1280 gtk_widget_show (priv->bcc_caption);
1281 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1282 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1283 gtk_widget_hide (priv->bcc_caption);
1284 field_view_set = FALSE;
1286 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button), field_view_set);
1290 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1291 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1294 update_window_title (self);
1296 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1297 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1299 if ((body == NULL)||(body[0] == '\0')) {
1301 body = modest_text_utils_convert_to_html ("");
1304 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1305 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1308 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1311 /* Add attachments to the view */
1312 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1313 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1314 if (tny_list_get_length (priv->attachments) == 0) {
1315 gtk_widget_hide (priv->attachments_caption);
1317 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1318 gtk_widget_show_all (priv->attachments_caption);
1320 get_related_images (self, msg);
1321 update_next_cid (self, priv->attachments);
1322 update_next_cid (self, priv->images);
1323 replace_with_images (self, priv->images);
1325 if (preserve_is_rich && !is_html) {
1326 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1327 /* Get the default format required from configuration */
1328 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1329 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1332 /* Set the default focus depending on having already a To: field or not */
1333 if ((!to)||(*to == '\0')) {
1334 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1336 gtk_widget_grab_focus (priv->msg_body);
1339 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1341 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1342 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1344 modest_msg_edit_window_set_modified (self, FALSE);
1346 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1347 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1348 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1349 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1351 if (priv->msg_uid) {
1352 g_free (priv->msg_uid);
1353 priv->msg_uid = NULL;
1356 /* we should set a reference to the incoming message if it is a draft */
1357 msg_folder = tny_msg_get_folder (msg);
1359 if (modest_tny_folder_is_local_folder (msg_folder)) {
1360 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1361 if (type == TNY_FOLDER_TYPE_INVALID)
1362 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1364 if (type == TNY_FOLDER_TYPE_DRAFTS)
1365 priv->draft_msg = g_object_ref(msg);
1366 if (type == TNY_FOLDER_TYPE_OUTBOX)
1367 priv->outbox_msg = g_object_ref(msg);
1368 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1370 g_object_unref (msg_folder);
1381 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1383 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1384 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1385 GtkWidget *placeholder;
1386 GtkWidget *tool_item;
1391 GtkWidget *sizes_menu;
1392 GtkWidget *fonts_menu;
1398 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1399 gtk_toolbar_set_show_arrow (GTK_TOOLBAR (parent_priv->toolbar), FALSE);
1400 gtk_toolbar_set_icon_size (GTK_TOOLBAR (parent_priv->toolbar), HILDON_ICON_SIZE_FINGER);
1401 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1403 /* Font color placeholder */
1404 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1405 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1408 priv->font_color_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1409 priv->font_color_button = hildon_color_button_new ();
1410 gtk_widget_set_size_request (priv->font_color_button, -1, 48);
1411 GTK_WIDGET_UNSET_FLAGS (priv->font_color_toolitem, GTK_CAN_FOCUS);
1412 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1413 gtk_container_add (GTK_CONTAINER (priv->font_color_toolitem), priv->font_color_button);
1414 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1415 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1416 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->font_color_toolitem), insert_index);
1417 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1419 G_CALLBACK (modest_msg_edit_window_color_button_change),
1422 /* Font size and face placeholder */
1423 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1424 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1426 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1427 priv->size_tool_button_label = gtk_label_new (NULL);
1428 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1429 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1430 size_text, "</span>", NULL);
1431 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1432 gtk_misc_set_alignment (GTK_MISC (priv->size_tool_button_label), 1.0, 0.5);
1434 hildon_helper_set_logical_font (priv->size_tool_button_label, "LargeSystemFont");
1435 hbox = gtk_hbox_new (MODEST_MARGIN_DEFAULT, FALSE);
1436 gtk_box_pack_start (GTK_BOX (hbox), priv->size_tool_button_label, TRUE, TRUE, 0);
1437 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1438 gtk_misc_set_alignment (GTK_MISC (arrow), 0.0, 0.5);
1439 gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
1440 gtk_widget_set_sensitive (arrow, FALSE);
1441 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), hbox);
1442 sizes_menu = gtk_menu_new ();
1443 priv->sizes_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1444 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1447 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1448 gtk_list_store_append (GTK_LIST_STORE (priv->sizes_model), &iter);
1450 gtk_list_store_set (GTK_LIST_STORE (priv->sizes_model), &iter,
1454 if (wp_font_size[size_index] == 12)
1455 priv->current_size_index = size_index;
1459 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_size_clicked), window);
1460 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1461 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1462 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1463 priv->font_size_toolitem = tool_item;
1466 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1467 priv->font_tool_button_label = gtk_label_new (NULL);
1468 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1469 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1470 gtk_misc_set_alignment (GTK_MISC (priv->font_tool_button_label), 1.0, 0.5);
1472 hildon_helper_set_logical_font (priv->font_tool_button_label, "LargeSystemFont");
1473 hbox = gtk_hbox_new (MODEST_MARGIN_DEFAULT, FALSE);
1474 gtk_box_pack_start (GTK_BOX (hbox), priv->font_tool_button_label, TRUE, TRUE, 0);
1475 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1476 gtk_misc_set_alignment (GTK_MISC (arrow), 0.0, 0.5);
1477 gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
1478 gtk_widget_set_sensitive (arrow, FALSE);
1479 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), hbox);
1480 fonts_menu = gtk_menu_new ();
1481 priv->faces_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1482 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1485 gtk_list_store_append (GTK_LIST_STORE (priv->faces_model), &iter);
1487 gtk_list_store_set (GTK_LIST_STORE (priv->faces_model), &iter,
1488 0, wp_get_font_name (font_index),
1491 if (font_index == DEFAULT_FONT)
1492 priv->current_face_index = font_index;
1494 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_face_clicked), window);
1495 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1496 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1497 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1498 priv->font_face_toolitem = tool_item;
1500 /* Set expand and homogeneous for remaining items */
1501 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
1502 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1503 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1504 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1505 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1506 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1507 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1508 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1509 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1511 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1512 will not show the tool items added to the placeholders) */
1513 gtk_widget_show_all (parent_priv->toolbar);
1515 /* Set the no show all *after* showing all items. We do not
1516 want the toolbar to be shown with a show all because it
1517 could go agains the gconf setting regarding showing or not
1518 the toolbar of the editor window */
1519 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1525 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, const gchar *mailbox, gboolean preserve_is_rich)
1528 ModestWindowPrivate *parent_priv;
1529 ModestMsgEditWindowPrivate *priv;
1530 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1531 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1532 ModestWindowMgr *mgr = NULL;
1534 g_return_val_if_fail (msg, NULL);
1535 g_return_val_if_fail (account_name, NULL);
1537 mgr = modest_runtime_get_window_mgr ();
1539 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1541 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1542 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1544 /* Menubar. Update the state of some toggles */
1545 priv->from_field_protos = get_transports ();
1546 modest_selector_picker_set_pair_list (MODEST_SELECTOR_PICKER (priv->from_field), priv->from_field_protos);
1547 if (mailbox && modest_pair_list_find_by_first_as_string (priv->from_field_protos, mailbox)) {
1548 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) mailbox);
1550 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1552 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1553 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1555 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1556 hildon_touch_selector_get_current_text
1557 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1558 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1559 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1562 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1564 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1566 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1567 modest_window_set_active_mailbox (MODEST_WINDOW(obj), mailbox);
1569 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1570 priv->original_mailbox = (mailbox) ? g_strdup (mailbox) : NULL;
1572 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1573 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1574 /* Add common dimming rules */
1575 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1576 modest_msg_edit_window_toolbar_dimming_entries,
1577 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1578 MODEST_WINDOW (obj));
1579 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_toolitem,
1580 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1581 MODEST_WINDOW (obj));
1582 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1583 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1584 MODEST_WINDOW (obj));
1585 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1586 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1587 MODEST_WINDOW (obj));
1588 /* Insert dimming rules group for this window */
1589 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1590 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1592 /* Setup app menu */
1593 setup_menu (MODEST_MSG_EDIT_WINDOW (obj));
1595 /* Checks the dimming rules */
1596 g_object_unref (toolbar_rules_group);
1597 g_object_unref (clipboard_rules_group);
1598 gtk_widget_hide (priv->priority_icon);
1599 gtk_widget_queue_resize (priv->subject_box);
1600 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1602 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1604 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1605 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1606 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1607 priv->update_caption_visibility = TRUE;
1609 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1611 /* Track account-removed signal, this window should be closed
1612 in the case we're creating a mail associated to the account
1614 priv->account_removed_handler_id =
1615 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1617 G_CALLBACK(on_account_removed),
1620 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1622 return (ModestWindow*) obj;
1626 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1628 GString **string_buffer = (GString **) user_data;
1630 *string_buffer = g_string_append (*string_buffer, buffer);
1636 * @result: A new string which should be freed with g_free().
1639 get_formatted_data (ModestMsgEditWindow *edit_window)
1641 ModestMsgEditWindowPrivate *priv;
1642 GString *string_buffer = g_string_new ("");
1644 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1646 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1648 modest_text_utils_hyperlinkify (string_buffer);
1650 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1652 return g_string_free (string_buffer, FALSE);
1657 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1660 const gchar *account_name;
1661 ModestMsgEditWindowPrivate *priv;
1662 TnyIterator *att_iter;
1663 const gchar *picker_active_id;
1665 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1667 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1669 picker_active_id = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1670 g_return_val_if_fail (picker_active_id, NULL);
1671 account_name = modest_utils_get_account_name_from_recipient (picker_active_id, NULL);
1673 /* don't free these (except from) */
1674 data = g_slice_new0 (MsgData);
1675 data->from = g_strdup ((gchar *) modest_selector_picker_get_active_display_name (MODEST_SELECTOR_PICKER (priv->from_field)));
1676 data->account_name = g_strdup (account_name);
1677 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1678 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1679 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1680 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1681 data->references = g_strdup (priv->references);
1682 data->in_reply_to = g_strdup (priv->in_reply_to);
1683 if (priv->draft_msg) {
1684 data->draft_msg = g_object_ref (priv->draft_msg);
1685 } else if (priv->outbox_msg) {
1686 data->draft_msg = g_object_ref (priv->outbox_msg);
1688 data->draft_msg = NULL;
1691 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1693 gtk_text_buffer_get_bounds (buf, &b, &e);
1694 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1696 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1697 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1699 data->html_body = NULL;
1701 /* deep-copy the data */
1702 att_iter = tny_list_create_iterator (priv->attachments);
1703 data->attachments = NULL;
1704 while (!tny_iterator_is_done (att_iter)) {
1705 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1706 if (!(TNY_IS_MIME_PART(part))) {
1707 g_warning ("strange data in attachment list");
1708 g_object_unref (part);
1709 tny_iterator_next (att_iter);
1712 data->attachments = g_list_append (data->attachments,
1714 tny_iterator_next (att_iter);
1716 g_object_unref (att_iter);
1718 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1719 att_iter = tny_list_create_iterator (priv->images);
1720 data->images = NULL;
1721 while (!tny_iterator_is_done (att_iter)) {
1722 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1724 if (!(TNY_IS_MIME_PART(part))) {
1725 g_warning ("strange data in attachment list");
1726 g_object_unref (part);
1727 tny_iterator_next (att_iter);
1730 cid = tny_mime_part_get_content_id (part);
1732 gchar *image_tag_id;
1733 GtkTextTag *image_tag;
1735 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1736 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1737 g_free (image_tag_id);
1739 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1741 ((gtk_text_iter_has_tag (&iter, image_tag))||
1742 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1743 data->images = g_list_append (data->images,
1744 g_object_ref (part));
1746 g_object_unref (part);
1747 tny_iterator_next (att_iter);
1749 g_object_unref (att_iter);
1751 data->priority_flags = priv->priority_flags;
1758 unref_gobject (GObject *obj, gpointer data)
1760 if (!G_IS_OBJECT(obj))
1762 g_object_unref (obj);
1766 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1769 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1777 g_free (data->from);
1778 g_free (data->subject);
1779 g_free (data->plain_body);
1780 g_free (data->html_body);
1781 g_free (data->account_name);
1782 g_free (data->references);
1783 g_free (data->in_reply_to);
1785 if (data->draft_msg != NULL) {
1786 g_object_unref (data->draft_msg);
1787 data->draft_msg = NULL;
1790 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1791 g_list_free (data->attachments);
1792 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1793 g_list_free (data->images);
1795 g_slice_free (MsgData, data);
1799 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1801 guint64 *parts_size)
1803 ModestMsgEditWindowPrivate *priv;
1805 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1807 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1809 /* TODO: add images */
1810 *parts_size += priv->images_size;
1811 *parts_count += priv->images_count;
1816 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1819 ModestMsgEditWindowPrivate *priv = NULL;
1820 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1822 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1824 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1826 return MODEST_MSG_EDIT_FORMAT_HTML;
1828 return MODEST_MSG_EDIT_FORMAT_TEXT;
1832 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1833 ModestMsgEditFormat format)
1835 ModestMsgEditWindowPrivate *priv;
1837 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1838 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1841 case MODEST_MSG_EDIT_FORMAT_HTML:
1842 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1844 case MODEST_MSG_EDIT_FORMAT_TEXT:
1845 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1848 g_return_if_reached ();
1852 ModestMsgEditFormatState *
1853 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1855 ModestMsgEditFormatState *format_state = NULL;
1856 ModestMsgEditWindowPrivate *priv;
1857 WPTextBufferFormat *buffer_format;
1859 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1861 buffer_format = g_new0 (WPTextBufferFormat, 1);
1862 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1864 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1866 format_state = g_new0 (ModestMsgEditFormatState, 1);
1867 format_state->bold = buffer_format->bold&0x1;
1868 format_state->italics = buffer_format->italic&0x1;
1869 format_state->bullet = buffer_format->bullet&0x1;
1870 format_state->color = buffer_format->color;
1871 format_state->font_size = buffer_format->font_size;
1872 format_state->font_family = wp_get_font_name (buffer_format->font);
1873 format_state->justification = buffer_format->justification;
1874 g_free (buffer_format);
1876 return format_state;
1881 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1882 const ModestMsgEditFormatState *format_state)
1884 ModestMsgEditWindowPrivate *priv;
1885 WPTextBufferFormat *buffer_format;
1886 WPTextBufferFormat *current_format;
1888 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1889 g_return_if_fail (format_state != NULL);
1891 buffer_format = g_new0 (WPTextBufferFormat, 1);
1892 current_format = g_new0 (WPTextBufferFormat, 1);
1894 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1895 gtk_widget_grab_focus (priv->msg_body);
1896 buffer_format->bold = (format_state->bold != FALSE);
1897 buffer_format->italic = (format_state->italics != FALSE);
1898 buffer_format->color = format_state->color;
1899 buffer_format->font_size = format_state->font_size;
1900 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1901 buffer_format->justification = format_state->justification;
1902 buffer_format->bullet = format_state->bullet;
1904 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1906 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1907 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1908 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1909 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1910 buffer_format->cs.font = (buffer_format->font != current_format->font);
1911 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1912 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1914 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1915 if (buffer_format->cs.bold) {
1916 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
1917 GINT_TO_POINTER (buffer_format->bold&0x1));
1919 if (buffer_format->cs.italic) {
1920 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
1921 GINT_TO_POINTER (buffer_format->italic&0x1));
1923 if (buffer_format->cs.color) {
1924 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1925 GINT_TO_POINTER (&(buffer_format->color)));
1927 if (buffer_format->cs.font_size) {
1928 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1929 GINT_TO_POINTER (buffer_format->font_size));
1931 if (buffer_format->cs.justification) {
1932 switch (buffer_format->justification) {
1933 case GTK_JUSTIFY_LEFT:
1934 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
1935 GINT_TO_POINTER(TRUE));
1937 case GTK_JUSTIFY_CENTER:
1938 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
1939 GINT_TO_POINTER(TRUE));
1941 case GTK_JUSTIFY_RIGHT:
1942 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
1943 GINT_TO_POINTER(TRUE));
1950 if (buffer_format->cs.font) {
1951 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1952 GINT_TO_POINTER (buffer_format->font));
1954 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1955 if (buffer_format->cs.bullet) {
1956 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
1957 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
1959 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1961 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
1963 g_free (buffer_format);
1964 g_free (current_format);
1966 /* Check dimming rules */
1967 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1968 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1972 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1974 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1976 ModestWindowPrivate *parent_priv;
1977 ModestMsgEditWindowPrivate *priv;
1979 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1980 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1982 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1983 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu");
1984 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1985 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1987 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatPlainTextMenu");
1988 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1989 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1992 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1994 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1995 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1997 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1998 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
2000 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
2001 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
2004 switch (buffer_format->justification)
2006 case GTK_JUSTIFY_LEFT:
2007 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2009 case GTK_JUSTIFY_CENTER:
2010 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2012 case GTK_JUSTIFY_RIGHT:
2013 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2020 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
2022 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
2023 G_CALLBACK (modest_msg_edit_window_color_button_change),
2025 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
2026 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
2027 G_CALLBACK (modest_msg_edit_window_color_button_change),
2030 if (priv->current_size_index != buffer_format->font_size) {
2034 path = gtk_tree_path_new_from_indices (buffer_format->font_size, -1);
2035 if (gtk_tree_model_get_iter (priv->sizes_model, &iter, path)) {
2039 priv->current_size_index = buffer_format->font_size;
2041 gtk_tree_model_get (priv->sizes_model, &iter, 0, &size_text, -1);
2042 markup = g_strconcat ("<span font_family='Sans'>",
2043 size_text, "</span>", NULL);
2045 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2049 gtk_tree_path_free (path);
2052 if (priv->current_face_index != buffer_format->font) {
2056 path = gtk_tree_path_new_from_indices (buffer_format->font, -1);
2057 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2061 priv->current_face_index = buffer_format->font;
2062 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2063 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2064 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2071 g_free (buffer_format);
2075 #ifdef MODEST_HILDON_VERSION_0
2077 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2080 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2081 ModestMsgEditWindowPrivate *priv;
2082 GtkWidget *dialog = NULL;
2084 GdkColor *new_color = NULL;
2086 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2087 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2089 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2090 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
2091 g_free (buffer_format);
2093 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2094 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2095 if (new_color != NULL) {
2096 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2097 (gpointer) new_color);
2100 gtk_widget_destroy (dialog);
2105 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2108 ModestMsgEditWindowPrivate *priv;
2109 GtkWidget *dialog = NULL;
2111 GdkColor *old_color = NULL;
2112 const GdkColor *new_color = NULL;
2114 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2115 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2117 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2118 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2120 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2121 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2122 if (new_color != NULL)
2123 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2125 gtk_widget_destroy (dialog);
2131 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2134 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2135 ModestMsgEditWindowPrivate *priv;
2136 GtkWidget *dialog = NULL;
2138 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2139 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2141 dialog = hildon_color_chooser_new ();
2142 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2143 g_free (buffer_format);
2145 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2147 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2148 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2151 gtk_widget_destroy (dialog);
2156 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2159 ModestMsgEditWindowPrivate *priv;
2160 GtkWidget *dialog = NULL;
2161 GdkColor *old_color = NULL;
2163 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2164 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2166 dialog = hildon_color_chooser_new ();
2167 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2169 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2171 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2172 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2174 gtk_widget_destroy (dialog);
2177 #endif /*!MODEST_HILDON_VERSION_0*/
2182 create_stream_for_uri (const gchar* uri)
2187 TnyStream *result = NULL;
2189 GnomeVFSHandle *handle = NULL;
2190 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2191 if (test == GNOME_VFS_OK) {
2192 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2193 /* Streams over OBEX (Bluetooth) are not seekable but
2194 * we expect them to be (we might need to read them
2195 * several times). So if this is a Bluetooth URI just
2196 * read the whole file into memory (this is not a fast
2197 * protocol so we can assume that these files are not
2198 * going to be very big) */
2199 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2200 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2201 TnyStream *memstream = tny_camel_mem_stream_new ();
2202 tny_stream_write_to_stream (vfssstream, memstream);
2203 g_object_unref (vfssstream);
2206 result = vfssstream;
2214 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2217 ModestMsgEditWindowPrivate *priv;
2218 GtkWidget *dialog = NULL;
2220 GSList *uris = NULL;
2221 GSList *uri_node = NULL;
2223 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2225 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2226 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2227 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2229 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2231 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2232 GTK_WINDOW (dialog), GTK_WINDOW (window));
2234 response = gtk_dialog_run (GTK_DIALOG (dialog));
2236 case GTK_RESPONSE_OK:
2238 gchar *current_folder;
2239 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2240 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2241 if (current_folder && current_folder != '\0') {
2243 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_INSERT_IMAGE_PATH,
2244 current_folder, &err);
2246 g_debug ("Error storing latest used folder: %s", err->message);
2250 g_free (current_folder);
2256 gtk_widget_destroy (dialog);
2258 g_object_ref (window);
2259 /* The operation could take some time so allow the dialog to be closed */
2260 while (gtk_events_pending ())
2261 gtk_main_iteration ();
2263 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2265 GnomeVFSHandle *handle = NULL;
2266 GnomeVFSResult result;
2267 GtkTextIter position;
2268 GtkTextMark *insert_mark;
2270 uri = (const gchar *) uri_node->data;
2271 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2272 if (result == GNOME_VFS_OK) {
2274 GnomeVFSFileInfo *info;
2275 gchar *filename, *basename, *escaped_filename;
2276 TnyMimePart *mime_part;
2278 const gchar *mime_type = NULL;
2279 GnomeVFSURI *vfs_uri;
2280 guint64 stream_size;
2282 gnome_vfs_close (handle);
2283 vfs_uri = gnome_vfs_uri_new (uri);
2285 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2286 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2287 g_free (escaped_filename);
2288 gnome_vfs_uri_unref (vfs_uri);
2289 info = gnome_vfs_file_info_new ();
2291 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2292 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2294 mime_type = gnome_vfs_file_info_get_mime_type (info);
2296 mime_part = tny_platform_factory_new_mime_part
2297 (modest_runtime_get_platform_factory ());
2299 TnyStream *stream = create_stream_for_uri (uri);
2301 if (stream == NULL) {
2303 modest_platform_information_banner (NULL, NULL,
2304 _FM("sfil_ib_opening_not_allowed"));
2306 g_object_unref (mime_part);
2307 gnome_vfs_file_info_unref (info);
2311 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2313 content_id = g_strdup_printf ("%d", priv->next_cid);
2314 tny_mime_part_set_content_id (mime_part, content_id);
2315 g_free (content_id);
2318 basename = g_path_get_basename (filename);
2319 tny_mime_part_set_filename (mime_part, basename);
2322 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, window);
2324 if (pixbuf != NULL) {
2325 priv->images_size += stream_size;
2326 priv->images_count ++;
2327 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2328 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2329 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position,
2330 tny_mime_part_get_content_id (mime_part), pixbuf);
2331 g_object_unref (pixbuf);
2333 tny_list_prepend (priv->images, (GObject *) mime_part);
2334 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2336 modest_platform_information_banner (NULL, NULL,
2337 _("mail_ib_file_operation_failed"));
2341 g_object_unref (mime_part);
2342 gnome_vfs_file_info_unref (info);
2346 g_object_unref (window);
2350 on_attach_file_response (GtkDialog *dialog,
2354 GSList *uris = NULL;
2356 GnomeVFSFileSize total_size, allowed_size;
2357 ModestMsgEditWindow *window;
2358 ModestMsgEditWindowPrivate *priv;
2363 case GTK_RESPONSE_OK:
2365 gchar *current_folder;
2367 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2368 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2369 if (current_folder && current_folder != '\0') {
2371 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_ATTACH_FILE_PATH,
2372 current_folder, &err);
2374 g_debug ("Error storing latest used folder: %s", err->message);
2378 g_free (current_folder);
2385 window = MODEST_MSG_EDIT_WINDOW (user_data);
2386 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2388 /* allowed size is the maximum size - what's already there */
2389 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2390 &att_num, &att_size);
2391 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2394 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2396 const gchar *uri = (const gchar *) uri_node->data;
2399 modest_msg_edit_window_attach_file_one (window, uri, allowed_size);
2401 if (total_size > allowed_size) {
2402 g_warning ("%s: total size: %u",
2403 __FUNCTION__, (unsigned int)total_size);
2406 allowed_size -= total_size;
2408 g_slist_foreach (uris, (GFunc) g_free, NULL);
2409 g_slist_free (uris);
2411 gtk_widget_destroy (GTK_WIDGET (dialog));
2415 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2417 GtkWidget *dialog = NULL;
2418 ModestMsgEditWindowPrivate *priv;
2421 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2423 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2425 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2428 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window),
2429 GTK_FILE_CHOOSER_ACTION_OPEN);
2430 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2431 conf_folder = modest_conf_get_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_ATTACH_FILE_PATH, NULL);
2432 if (conf_folder && conf_folder[0] != '\0') {
2433 gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (dialog), conf_folder);
2436 /* Set the default folder to images folder */
2437 docs_folder = g_build_filename (g_getenv (MODEST_MAEMO_UTILS_MYDOCS_ENV),
2438 ".documents", NULL);
2439 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), docs_folder);
2440 g_free (docs_folder);
2442 g_free (conf_folder);
2443 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2444 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2445 GTK_WINDOW (dialog), GTK_WINDOW (window));
2447 /* Connect to response & show */
2448 g_signal_connect (dialog, "response",
2449 G_CALLBACK (on_attach_file_response), window);
2450 gtk_widget_show (dialog);
2455 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2457 GnomeVFSFileSize allowed_size)
2460 GnomeVFSHandle *handle = NULL;
2461 ModestMsgEditWindowPrivate *priv;
2462 GnomeVFSResult result;
2463 GnomeVFSFileSize size = 0;
2464 g_return_val_if_fail (window, 0);
2465 g_return_val_if_fail (uri, 0);
2467 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2469 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2470 if (result == GNOME_VFS_OK) {
2471 TnyMimePart *mime_part;
2473 const gchar *mime_type = NULL;
2475 gchar *escaped_filename;
2478 GnomeVFSFileInfo *info;
2479 GnomeVFSURI *vfs_uri;
2481 gnome_vfs_close (handle);
2482 vfs_uri = gnome_vfs_uri_new (uri);
2485 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2486 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2487 g_free (escaped_filename);
2488 gnome_vfs_uri_unref (vfs_uri);
2490 info = gnome_vfs_file_info_new ();
2492 if (gnome_vfs_get_file_info (uri,
2494 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2496 mime_type = gnome_vfs_file_info_get_mime_type (info);
2497 mime_part = tny_platform_factory_new_mime_part
2498 (modest_runtime_get_platform_factory ());
2500 /* try to get the attachment's size; this may fail for weird
2501 * file systems, like obex, upnp... */
2502 if (allowed_size != 0 &&
2503 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2505 if (size > allowed_size) {
2506 modest_platform_information_banner (NULL, NULL,
2507 _FM("sfil_ib_opening_not_allowed"));
2512 g_warning ("%s: could not get attachment size", __FUNCTION__);
2514 stream = create_stream_for_uri (uri);
2516 if (stream == NULL) {
2518 modest_platform_information_banner (NULL, NULL, _FM("sfil_ib_opening_not_allowed"));
2520 g_object_unref (mime_part);
2522 gnome_vfs_file_info_unref (info);
2526 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2527 g_object_unref (stream);
2529 content_id = g_strdup_printf ("%d", priv->next_cid);
2530 tny_mime_part_set_content_id (mime_part, content_id);
2531 g_free (content_id);
2534 basename = g_path_get_basename (filename);
2535 tny_mime_part_set_filename (mime_part, basename);
2538 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2539 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2541 info->size == 0, info->size);
2542 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2543 gtk_widget_show_all (priv->attachments_caption);
2544 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2546 g_object_unref (mime_part);
2547 gnome_vfs_file_info_unref (info);
2554 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2557 ModestMsgEditWindowPrivate *priv;
2560 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2561 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2563 if (att_list == NULL) {
2564 att_list = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2565 if (!modest_maemo_utils_select_attachments (GTK_WINDOW (window), att_list, TRUE)) {
2566 g_object_unref (att_list);
2571 g_object_ref (att_list);
2574 if (tny_list_get_length (att_list) == 0) {
2575 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2577 gboolean dialog_response;
2578 gchar *message = NULL;
2579 gchar *filename = NULL;
2581 if (tny_list_get_length (att_list) == 1) {
2583 iter = tny_list_create_iterator (att_list);
2584 part = (TnyMimePart *) tny_iterator_get_current (iter);
2585 g_object_unref (iter);
2586 if (TNY_IS_MSG (part)) {
2587 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2589 filename = tny_header_dup_subject (header);
2590 g_object_unref (header);
2592 if (filename == NULL) {
2593 filename = g_strdup (_("mail_va_no_subject"));
2596 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2598 g_object_unref (part);
2600 filename = g_strdup ("");
2602 message = g_strdup_printf (ngettext("emev_nc_delete_attachment",
2603 "emev_nc_delete_attachments",
2604 tny_list_get_length (att_list)), filename);
2607 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
2611 if (dialog_response != GTK_RESPONSE_OK) {
2612 g_object_unref (att_list);
2616 for (iter = tny_list_create_iterator (att_list);
2617 !tny_iterator_is_done (iter);
2618 tny_iterator_next (iter)) {
2619 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2620 const gchar *att_id;
2621 tny_list_remove (priv->attachments, (GObject *) mime_part);
2623 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2625 if (tny_list_get_length (priv->attachments) == 0)
2626 gtk_widget_hide (priv->attachments_caption);
2627 att_id = tny_mime_part_get_content_id (mime_part);
2629 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2631 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2632 g_object_unref (mime_part);
2634 g_object_unref (iter);
2637 g_object_unref (att_list);
2639 /* if the last attachment has been removed, focus the Subject: field */
2640 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2641 gtk_widget_grab_focus (priv->subject_field);
2645 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2648 ModestMsgEditWindowPrivate *priv;
2649 GdkColor *new_color;
2650 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2652 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2653 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2656 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2658 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2660 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2662 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2667 font_size_clicked (GtkToolButton *button,
2668 ModestMsgEditWindow *window)
2670 ModestMsgEditWindowPrivate *priv;
2671 GtkWidget *selector, *dialog;
2673 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2675 selector = hildon_touch_selector_new ();
2676 hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector), priv->sizes_model, TRUE);
2677 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_size_index);
2679 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2680 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2681 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_size"));
2683 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2687 WPTextBufferFormat format;
2689 new_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2691 memset (&format, 0, sizeof (format));
2692 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2694 format.cs.font_size = TRUE;
2695 format.cs.text_position = TRUE;
2696 format.cs.font = TRUE;
2697 format.font_size = new_index;
2698 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2700 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2701 GINT_TO_POINTER (new_index)))
2702 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2704 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2705 size_text = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (selector));
2706 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
2707 size_text, "</span>", NULL);
2709 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2713 gtk_widget_destroy (dialog);
2715 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2720 font_face_clicked (GtkToolButton *button,
2721 ModestMsgEditWindow *window)
2723 ModestMsgEditWindowPrivate *priv;
2724 GtkWidget *selector, *dialog;
2725 GtkCellRenderer *renderer;
2727 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2729 selector = hildon_touch_selector_new ();
2730 renderer = gtk_cell_renderer_text_new ();
2731 hildon_touch_selector_append_column (HILDON_TOUCH_SELECTOR (selector), priv->faces_model,
2732 renderer, "family", 0, "text", 0, NULL);
2733 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_face_index);
2735 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2736 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2737 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_face"));
2739 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2740 gint new_font_index;
2744 new_font_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2745 path = gtk_tree_path_new_from_indices (new_font_index, -1);
2746 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2750 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2752 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2753 GINT_TO_POINTER(new_font_index)))
2754 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2756 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2757 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2759 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2763 gtk_tree_path_free (path);
2766 gtk_widget_destroy (dialog);
2768 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2773 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2776 ModestMsgEditWindowPrivate *priv = NULL;
2777 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2779 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2780 if (!priv->update_caption_visibility)
2783 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2785 gtk_widget_show (priv->cc_caption);
2787 gtk_widget_hide (priv->cc_caption);
2789 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2793 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2796 ModestMsgEditWindowPrivate *priv = NULL;
2797 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2799 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2800 if (!priv->update_caption_visibility)
2803 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2805 gtk_widget_show (priv->bcc_caption);
2807 gtk_widget_hide (priv->bcc_caption);
2809 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2813 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2814 ModestRecptEditor *editor)
2816 ModestMsgEditWindowPrivate *priv;
2818 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2819 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2821 /* we check for low-mem; in that case, show a warning, and don't allow
2822 * for the addressbook
2824 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2827 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2829 if (editor == NULL) {
2830 GtkWidget *view_focus;
2831 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2833 /* This code should be kept in sync with ModestRecptEditor. The
2834 textview inside the recpt editor is the one that really gets the
2835 focus. As it's inside a scrolled window, and this one inside the
2836 hbox recpt editor inherits from, we'll need to go up in the
2837 hierarchy to know if the text view is part of the recpt editor
2838 or if it's a different text entry */
2840 if (gtk_widget_get_parent (view_focus)) {
2841 GtkWidget *first_parent;
2843 first_parent = gtk_widget_get_parent (view_focus);
2844 if (gtk_widget_get_parent (first_parent) &&
2845 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2846 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2851 editor = MODEST_RECPT_EDITOR (priv->to_field);
2855 modest_address_book_select_addresses (editor);
2860 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2862 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2864 modest_msg_edit_window_open_addressbook (window, NULL);
2868 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2869 gboolean show_toolbar)
2871 ModestWindowPrivate *parent_priv;
2873 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2874 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2876 /* We can not just use the code of
2877 modest_msg_edit_window_setup_toolbar because it has a
2878 mixture of both initialization and creation code. */
2880 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2882 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2886 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2887 TnyHeaderFlags priority_flags)
2889 ModestMsgEditWindowPrivate *priv;
2890 ModestWindowPrivate *parent_priv;
2892 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2894 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2895 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2897 if (priv->priority_flags != priority_flags) {
2898 GtkAction *priority_action = NULL;
2900 priv->priority_flags = priority_flags;
2902 switch (priority_flags) {
2903 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2904 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2905 MODEST_HEADER_ICON_HIGH,
2906 HILDON_ICON_SIZE_SMALL);
2907 gtk_widget_show (priv->priority_icon);
2908 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2909 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2911 case TNY_HEADER_FLAG_LOW_PRIORITY:
2912 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2913 MODEST_HEADER_ICON_LOW,
2914 HILDON_ICON_SIZE_SMALL);
2915 gtk_widget_show (priv->priority_icon);
2916 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2917 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2920 gtk_widget_hide (priv->priority_icon);
2921 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2922 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2925 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2926 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2928 gtk_widget_queue_resize (priv->subject_box);
2932 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2935 ModestMsgEditWindowPrivate *priv;
2936 ModestWindowPrivate *parent_priv;
2937 gint current_format;
2939 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2941 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2942 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2944 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2945 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2947 if (current_format != file_format) {
2948 switch (file_format) {
2949 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2950 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2951 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
2953 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2957 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2958 response = gtk_dialog_run (GTK_DIALOG (dialog));
2959 gtk_widget_destroy (dialog);
2960 if (response == GTK_RESPONSE_OK) {
2961 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2963 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
2964 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
2969 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2970 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2971 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2976 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2979 ModestMsgEditWindowPrivate *priv;
2980 WPTextBufferFormat oldfmt, fmt;
2981 gint old_position = 0;
2985 GdkColor *color = NULL;
2986 gboolean bold, bold_set, italic, italic_set;
2987 gboolean underline, underline_set;
2988 gboolean strikethrough, strikethrough_set;
2989 gboolean position_set;
2990 gboolean font_size_set, font_set, color_set;
2993 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2994 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2996 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2997 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
2998 GTK_WINDOW(dialog), GTK_WINDOW (window));
3000 /* First we get the currently selected font information */
3001 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
3003 switch (oldfmt.text_position) {
3004 case TEXT_POSITION_NORMAL:
3007 case TEXT_POSITION_SUPERSCRIPT:
3015 g_object_set (G_OBJECT (dialog),
3016 "bold", oldfmt.bold != FALSE,
3017 "bold-set", !oldfmt.cs.bold,
3018 "underline", oldfmt.underline != FALSE,
3019 "underline-set", !oldfmt.cs.underline,
3020 "italic", oldfmt.italic != FALSE,
3021 "italic-set", !oldfmt.cs.italic,
3022 "strikethrough", oldfmt.strikethrough != FALSE,
3023 "strikethrough-set", !oldfmt.cs.strikethrough,
3024 "color", &oldfmt.color,
3025 "color-set", !oldfmt.cs.color,
3026 "size", wp_font_size[oldfmt.font_size],
3027 "size-set", !oldfmt.cs.font_size,
3028 "position", old_position,
3029 "position-set", !oldfmt.cs.text_position,
3030 "family", wp_get_font_name (oldfmt.font),
3031 "family-set", !oldfmt.cs.font,
3034 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
3035 GTK_WINDOW (dialog), GTK_WINDOW (window));
3036 gtk_widget_show_all (dialog);
3037 priv->font_dialog = dialog;
3038 response = gtk_dialog_run (GTK_DIALOG (dialog));
3039 priv->font_dialog = NULL;
3040 if (response == GTK_RESPONSE_OK) {
3042 g_object_get( dialog,
3044 "bold-set", &bold_set,
3045 "underline", &underline,
3046 "underline-set", &underline_set,
3048 "italic-set", &italic_set,
3049 "strikethrough", &strikethrough,
3050 "strikethrough-set", &strikethrough_set,
3052 "color-set", &color_set,
3054 "size-set", &font_size_set,
3055 "family", &font_name,
3056 "family-set", &font_set,
3057 "position", &position,
3058 "position-set", &position_set,
3063 if (response == GTK_RESPONSE_OK) {
3064 memset(&fmt, 0, sizeof(fmt));
3070 fmt.italic = italic;
3071 fmt.cs.italic = TRUE;
3073 if (underline_set) {
3074 fmt.underline = underline;
3075 fmt.cs.underline = TRUE;
3077 if (strikethrough_set) {
3078 fmt.strikethrough = strikethrough;
3079 fmt.cs.strikethrough = TRUE;
3084 ? TEXT_POSITION_NORMAL
3085 : ( ( position == 1 )
3086 ? TEXT_POSITION_SUPERSCRIPT
3087 : TEXT_POSITION_SUBSCRIPT );
3088 fmt.cs.text_position = TRUE;
3089 fmt.font_size = oldfmt.font_size;
3093 fmt.cs.color = TRUE;
3096 fmt.font = wp_get_font_index(font_name,
3101 if (font_size_set) {
3102 fmt.cs.font_size = TRUE;
3103 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
3105 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
3106 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3108 gtk_widget_destroy (dialog);
3110 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
3114 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
3116 ModestMsgEditWindowPrivate *priv;
3118 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3119 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3121 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
3123 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3124 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3128 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
3130 ModestMsgEditWindowPrivate *priv;
3132 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3133 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3135 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
3137 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3138 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3143 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
3145 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3147 priv->can_undo = can_undo;
3151 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
3153 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3155 priv->can_redo = can_redo;
3159 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3161 ModestMsgEditWindowPrivate *priv;
3162 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3163 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3165 return priv->can_undo;
3169 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3171 ModestMsgEditWindowPrivate *priv;
3172 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3173 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3175 return priv->can_redo;
3180 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3183 GtkTextIter match_start, match_end;
3185 if (image_id == NULL)
3188 gtk_text_buffer_get_start_iter (buffer, &iter);
3190 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3191 GSList *tags = gtk_text_iter_get_tags (&match_start);
3193 for (node = tags; node != NULL; node = g_slist_next (node)) {
3194 GtkTextTag *tag = (GtkTextTag *) node->data;
3195 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3196 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3197 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3199 offset = gtk_text_iter_get_offset (&match_start);
3200 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3201 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3205 gtk_text_iter_forward_char (&iter);
3210 message_is_empty (ModestMsgEditWindow *window)
3212 ModestMsgEditWindowPrivate *priv = NULL;
3214 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3215 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3217 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3218 * so we can ignore markup.
3220 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3223 count = gtk_text_buffer_get_char_count (buf);
3229 msg_body_focus (GtkWidget *focus,
3230 GdkEventFocus *event,
3234 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3235 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3236 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3241 recpt_field_changed (GtkTextBuffer *buffer,
3242 ModestMsgEditWindow *editor)
3244 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3245 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3249 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3251 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3252 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3256 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3259 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3260 GtkTextBuffer *buffer;
3262 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3263 gtk_text_buffer_set_modified (buffer, modified);
3264 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3265 gtk_text_buffer_set_modified (buffer, modified);
3266 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3267 gtk_text_buffer_set_modified (buffer, modified);
3268 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3272 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3274 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3275 const char *account_name;
3276 GtkTextBuffer *buffer;
3278 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3279 if (gtk_text_buffer_get_modified (buffer))
3281 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3282 if (gtk_text_buffer_get_modified (buffer))
3284 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3285 if (gtk_text_buffer_get_modified (buffer))
3287 if (gtk_text_buffer_get_modified (priv->text_buffer))
3290 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3291 if (priv->original_mailbox) {
3292 if (!account_name || strcmp (account_name, priv->original_mailbox))
3294 } else if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3305 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3307 ModestMsgEditWindowPrivate *priv = NULL;
3309 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3310 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3312 /* check if there's no recipient added */
3313 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3314 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3315 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3316 /* no recipient contents, then select contacts */
3317 modest_msg_edit_window_open_addressbook (window, NULL);
3321 g_object_ref (window);
3322 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3323 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3324 g_object_unref (window);
3327 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3328 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3329 g_object_unref (window);
3332 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3333 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3334 g_object_unref (window);
3338 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3339 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3340 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3341 g_object_unref (window);
3348 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3349 ModestMsgEditWindow *window)
3351 modest_msg_edit_window_offer_attach_file (window);
3355 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3357 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3359 return priv->clipboard_text;
3363 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3365 ModestMsgEditWindow *window)
3367 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3368 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3371 /* It could happen that the window was already closed */
3372 if (!GTK_WIDGET_VISIBLE (window))
3375 g_object_ref (window);
3376 text = gtk_clipboard_wait_for_text (selection_clipboard);
3378 if (priv->clipboard_text != NULL) {
3379 g_free (priv->clipboard_text);
3381 priv->clipboard_text = text;
3383 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3385 g_object_unref (window);
3388 static gboolean clipboard_owner_change_idle (gpointer userdata)
3390 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3391 ModestMsgEditWindowPrivate *priv;
3393 gdk_threads_enter ();
3394 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3395 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3397 priv->clipboard_owner_idle = 0;
3398 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3399 gdk_threads_leave ();
3405 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3407 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3408 if (priv->clipboard_owner_idle == 0) {
3409 priv->clipboard_owner_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
3410 clipboard_owner_change_idle,
3411 g_object_ref (window),
3417 subject_field_move_cursor (GtkEntry *entry,
3418 GtkMovementStep step,
3423 /* It could happen that the window was already closed */
3424 if (!GTK_WIDGET_VISIBLE (window))
3427 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3431 update_window_title (ModestMsgEditWindow *window)
3433 ModestMsgEditWindowPrivate *priv = NULL;
3434 const gchar *subject;
3436 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3437 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3438 if (subject == NULL || subject[0] == '\0')
3439 subject = _("mail_va_new_email");
3441 gtk_window_set_title (GTK_WINDOW (window), subject);
3446 subject_field_changed (GtkEditable *editable,
3447 ModestMsgEditWindow *window)
3449 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3450 update_window_title (window);
3451 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3452 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3453 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3457 subject_field_insert_text (GtkEditable *editable,
3459 gint new_text_length,
3461 ModestMsgEditWindow *window)
3463 GString *result = g_string_new ("");
3465 gint result_len = 0;
3466 const gchar *entry_text = NULL;
3469 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3470 old_length = g_utf8_strlen (entry_text, -1);
3472 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3473 gunichar c = g_utf8_get_char_validated (current, 8);
3474 /* Invalid unichar, stop */
3480 result = g_string_append_unichar (result, c);
3484 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3485 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3488 /* Prevent endless recursion */
3489 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3490 g_signal_emit_by_name (editable, "insert-text",
3491 (gpointer) result->str, (gpointer) result->len,
3492 (gpointer) position, (gpointer) window);
3493 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3497 if (result_len + old_length > 1000) {
3498 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3499 _CS("ckdg_ib_maximum_characters_reached"));
3501 g_string_free (result, TRUE);
3505 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3508 ModestMsgEditWindowPrivate *priv = NULL;
3510 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3511 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3513 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3516 gtk_widget_show_all (priv->find_toolbar);
3517 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3519 gtk_widget_hide_all (priv->find_toolbar);
3520 gtk_widget_grab_focus (priv->msg_body);
3525 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3527 GtkTextIter *match_start,
3528 GtkTextIter *match_end)
3530 GtkTextIter end_iter;
3531 gchar *str_casefold;
3534 gchar *range_casefold;
3537 gboolean result = FALSE;
3544 gtk_text_iter_forward_to_end (&end_iter);
3546 str_casefold = g_utf8_casefold (str, -1);
3547 str_chars_n = strlen (str);
3549 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3550 range_casefold = g_utf8_casefold (range_text, -1);
3551 range_chars_n = strlen (range_casefold);
3553 if (range_chars_n < str_chars_n) {
3554 g_free (str_casefold);
3555 g_free (range_text);
3556 g_free (range_casefold);
3560 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3561 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3562 if (!g_utf8_collate (range_subtext, str_casefold)) {
3563 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3565 if (!gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3566 match_start, match_end, NULL)) {
3567 g_warning ("Matched string with collate, but not matched in model");
3569 g_free (found_text);
3571 g_free (range_subtext);
3575 g_free (str_casefold);
3576 g_free (range_text);
3577 g_free (range_casefold);
3584 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3585 ModestMsgEditWindow *window)
3587 gchar *current_search = NULL;
3588 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3590 GtkTextIter selection_start, selection_end;
3591 GtkTextIter match_start, match_end;
3592 gboolean continue_search = FALSE;
3594 if (message_is_empty (window)) {
3595 g_free (priv->last_search);
3596 priv->last_search = NULL;
3597 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3601 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3602 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3603 g_free (current_search);
3604 g_free (priv->last_search);
3605 priv->last_search = NULL;
3606 /* Information banner about empty search */
3607 hildon_banner_show_information (NULL, NULL, _CS("ecdg_ib_find_rep_enter_text"));
3611 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3612 continue_search = TRUE;
3614 g_free (priv->last_search);
3615 priv->last_search = g_strdup (current_search);
3618 if (continue_search) {
3619 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3620 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3621 &match_start, &match_end);
3623 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_search_complete"));
3625 GtkTextIter buffer_start;
3626 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3627 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3628 &match_start, &match_end);
3630 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_no_matches"));
3633 /* Mark as selected the string found in search */
3635 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3636 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3637 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3639 g_free (priv->last_search);
3640 priv->last_search = NULL;
3642 g_free (current_search);
3646 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3648 ModestMsgEditWindowPrivate *priv;
3650 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3655 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3658 ModestMsgEditWindowPrivate *priv;
3660 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3665 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3666 ModestMsgEditWindow *window)
3668 modest_msg_edit_window_toggle_find_toolbar (window, FALSE);
3672 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3675 ModestMsgEditWindowPrivate *priv;
3676 TnyHeader *header = NULL;
3678 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3679 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3681 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3683 if (priv->draft_msg != NULL) {
3684 g_object_unref (priv->draft_msg);
3687 if (draft != NULL) {
3688 g_object_ref (draft);
3689 header = tny_msg_get_header (draft);
3690 if (priv->msg_uid) {
3691 g_free (priv->msg_uid);
3692 priv->msg_uid = NULL;
3694 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3697 priv->draft_msg = draft;
3701 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3702 GtkTextIter *start, GtkTextIter *end,
3705 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3706 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3709 if (tag == NULL) return;
3710 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3711 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3712 replace_with_images (window, priv->images);
3717 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3720 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3722 g_return_if_fail (TNY_IS_MIME_PART (part));
3723 tny_list_prepend (priv->attachments, (GObject *) part);
3724 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3725 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3726 gtk_widget_show_all (priv->attachments_caption);
3727 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3731 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3733 ModestMsgEditWindowPrivate *priv;
3735 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3736 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3738 return priv->msg_uid;
3742 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3743 ModestMsgEditWindowWidgetType widget_type)
3745 ModestMsgEditWindowPrivate *priv;
3747 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3748 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3750 switch (widget_type) {
3751 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3752 return priv->msg_body;
3754 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3755 return priv->to_field;
3757 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3758 return priv->cc_field;
3760 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3761 return priv->bcc_field;
3763 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3764 return priv->subject_field;
3766 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3767 return priv->attachments_view;
3775 remove_tags (WPTextBuffer *buffer)
3777 GtkTextIter start, end;
3779 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3780 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3782 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3786 on_account_removed (TnyAccountStore *account_store,
3787 TnyAccount *account,
3790 /* Do nothing if it's a store account, because we use the
3791 transport to send the messages */
3792 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3793 const gchar *parent_acc = NULL;
3794 const gchar *our_acc = NULL;
3796 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3797 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3798 /* Close this window if I'm showing a message of the removed account */
3799 if (strcmp (parent_acc, our_acc) == 0)
3800 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3805 from_field_changed (HildonPickerButton *button,
3806 ModestMsgEditWindow *self)
3808 ModestMsgEditWindowPrivate *priv;
3809 gboolean has_old_signature, has_new_signature;
3811 GtkTextIter match_start, match_end;
3812 ModestAccountMgr *mgr;
3814 gchar *full_signature;
3816 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3818 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
3819 mgr = modest_runtime_get_account_mgr ();
3820 signature = modest_account_mgr_get_signature (mgr, priv->last_from_account, &has_old_signature);
3821 if (has_old_signature) {
3822 full_signature = g_strconcat ("\n--\n", signature, NULL);
3823 if (gtk_text_iter_forward_search (&iter, full_signature, 0, &match_start, &match_end, NULL)) {
3824 gtk_text_buffer_delete (priv->text_buffer, &match_start, &match_end);
3826 } else if (gtk_text_iter_forward_search (&iter, _("mcen_ia_editor_original_message"), 0,
3827 &match_start, &match_end, NULL)) {
3830 g_free (full_signature);
3834 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3835 signature = modest_account_mgr_get_signature (mgr, priv->last_from_account, &has_new_signature);
3836 if (has_new_signature) {
3837 full_signature = g_strconcat ("\n--\n", signature, NULL);
3838 gtk_text_buffer_insert (priv->text_buffer, &iter, full_signature, -1);
3839 g_free (full_signature);
3844 typedef struct _MessageSettingsHelper {
3845 ModestMsgEditWindow *window;
3846 GSList *priority_group;
3847 GSList *format_group;
3848 GtkToggleButton *current_priority;
3849 GtkToggleButton *current_format;
3850 } MessageSettingsHelper;
3853 on_priority_toggle (GtkToggleButton *button,
3854 MessageSettingsHelper *helper)
3857 ModestMsgEditWindowPrivate *priv;
3859 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3860 if (gtk_toggle_button_get_active (button)) {
3862 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3863 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3864 if ((node_button != button) &&
3865 gtk_toggle_button_get_active (node_button)) {
3866 gtk_toggle_button_set_active (node_button, FALSE);
3869 helper->current_priority = button;
3871 gboolean found = FALSE;
3872 /* If no one is active, activate it again */
3873 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3874 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3875 if (gtk_toggle_button_get_active (node_button)) {
3881 gtk_toggle_button_set_active (button, TRUE);
3887 on_format_toggle (GtkToggleButton *button,
3888 MessageSettingsHelper *helper)
3891 ModestMsgEditWindowPrivate *priv;
3893 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3894 if (gtk_toggle_button_get_active (button)) {
3896 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
3897 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3898 if ((node_button != button) &&
3899 gtk_toggle_button_get_active (node_button)) {
3900 gtk_toggle_button_set_active (node_button, FALSE);
3903 helper->current_format = button;
3905 gboolean found = FALSE;
3906 /* If no one is active, activate it again */
3907 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
3908 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3909 if (gtk_toggle_button_get_active (node_button)) {
3915 gtk_toggle_button_set_active (button, TRUE);
3922 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
3927 GtkWidget *priority_hbox;
3928 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
3929 GtkWidget *captioned;
3930 GtkSizeGroup *title_sizegroup, *value_sizegroup;
3931 GtkWidget *format_hbox;
3932 GtkWidget *html_toggle, *text_toggle;
3933 ModestMsgEditWindowPrivate *priv;
3934 MessageSettingsHelper helper = {0,};
3936 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3937 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3938 helper.window = window;
3939 helper.priority_group = NULL;
3940 helper.format_group = NULL;
3942 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3943 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3945 dialog = gtk_dialog_new_with_buttons (_("mcen_me_message_settings"), NULL,
3946 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
3947 _HL("wdgt_bd_done"), GTK_RESPONSE_ACCEPT, NULL);
3948 vbox = gtk_vbox_new (FALSE, 0);
3949 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
3950 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DOUBLE, 0);
3951 gtk_container_add (GTK_CONTAINER (align), vbox);
3952 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), align);
3953 gtk_widget_show (align);
3954 gtk_widget_show (vbox);
3956 /* Priority toggles */
3957 priority_hbox = gtk_hbox_new (TRUE, 0);
3958 high_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3959 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
3960 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
3961 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
3962 medium_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3963 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
3964 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
3965 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
3966 low_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3967 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
3968 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
3969 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
3970 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, TRUE, TRUE, 0);
3971 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, TRUE, TRUE, 0);
3972 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, TRUE, TRUE, 0);
3973 gtk_widget_show_all (priority_hbox);
3974 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
3975 _("mcen_me_editor_message_priority"), FALSE, priority_hbox);
3976 gtk_widget_show (captioned);
3977 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
3979 /* format toggles */
3980 format_hbox = gtk_hbox_new (TRUE, 0);
3981 html_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3982 gtk_button_set_label (GTK_BUTTON (html_toggle), _("mcen_me_editor_formatted_text"));
3983 helper.format_group = g_slist_prepend (helper.format_group, html_toggle);
3984 g_object_set_data (G_OBJECT (html_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_HTML));
3985 g_object_set_data (G_OBJECT (html_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_FORMATTED_TEXT));
3986 text_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3987 gtk_button_set_label (GTK_BUTTON (text_toggle), _("mcen_me_editor_plain_text"));
3988 helper.format_group = g_slist_prepend (helper.format_group, text_toggle);
3989 g_object_set_data (G_OBJECT (text_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_TEXT));
3990 g_object_set_data (G_OBJECT (text_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_PLAIN_TEXT));
3991 gtk_box_pack_start (GTK_BOX (format_hbox), html_toggle, TRUE, TRUE, 0);
3992 gtk_box_pack_start (GTK_BOX (format_hbox), text_toggle, TRUE, TRUE, 0);
3993 gtk_widget_show_all (format_hbox);
3994 gtk_widget_show (format_hbox);
3995 gtk_box_pack_start (GTK_BOX (vbox), format_hbox, FALSE, FALSE, 0);
3998 g_object_unref (title_sizegroup);
3999 g_object_unref (value_sizegroup);
4001 /* Set current values */
4002 switch (priv->priority_flags) {
4003 case TNY_HEADER_FLAG_HIGH_PRIORITY:
4004 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (high_toggle), TRUE);
4005 helper.current_priority = GTK_TOGGLE_BUTTON (high_toggle);
4007 case TNY_HEADER_FLAG_LOW_PRIORITY:
4008 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (low_toggle), TRUE);
4009 helper.current_priority = GTK_TOGGLE_BUTTON (low_toggle);
4012 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (medium_toggle), TRUE);
4013 helper.current_priority = GTK_TOGGLE_BUTTON (medium_toggle);
4017 switch (modest_msg_edit_window_get_format (window)) {
4018 case MODEST_MSG_EDIT_FORMAT_TEXT:
4019 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_toggle), TRUE);
4020 helper.current_format = GTK_TOGGLE_BUTTON (text_toggle);
4022 case MODEST_MSG_EDIT_FORMAT_HTML:
4024 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (html_toggle), TRUE);
4025 helper.current_format = GTK_TOGGLE_BUTTON (html_toggle);
4029 /* Signal connects */
4030 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4031 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4032 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4033 g_signal_connect (G_OBJECT (html_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4034 g_signal_connect (G_OBJECT (text_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4036 /* Save settings if the user clicked on done */
4037 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
4038 TnyHeaderFlags flags;
4039 ModestMsgEditFormat old_format, new_format;
4041 /* Set priority flags */
4042 flags = (TnyHeaderFlags) g_object_get_data (G_OBJECT (helper.current_priority), "priority");
4043 if (priv->priority_flags != flags)
4044 modest_msg_edit_window_set_priority_flags (window, flags);
4046 /* Set edit format */
4047 old_format = modest_msg_edit_window_get_format (window);
4048 new_format = (ModestMsgEditFormat) g_object_get_data (G_OBJECT (helper.current_format), "format");
4049 if (old_format != new_format) {
4050 gint file_format = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (helper.current_format), "file-format"));
4051 modest_msg_edit_window_set_file_format (window, file_format);
4055 gtk_widget_destroy (dialog);
4056 g_slist_free (helper.priority_group);
4060 on_message_settings (GtkAction *action,
4061 ModestMsgEditWindow *window)
4063 modest_msg_edit_window_show_msg_settings_dialog (window);
4067 on_cc_button_toggled (HildonCheckButton *button,
4068 ModestMsgEditWindow *window)
4070 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4072 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
4073 hildon_check_button_get_active (button));
4077 on_bcc_button_toggled (HildonCheckButton *button,
4078 ModestMsgEditWindow *window)
4080 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4082 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
4083 hildon_check_button_get_active (button));
4087 setup_menu (ModestMsgEditWindow *self)
4089 ModestMsgEditWindowPrivate *priv = NULL;
4091 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
4093 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4095 /* Settings menu buttons */
4096 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_checknames"), NULL,
4097 APP_MENU_CALLBACK (modest_ui_actions_on_check_names),
4099 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_undo"), "<Ctrl>z",
4100 APP_MENU_CALLBACK (modest_ui_actions_on_undo),
4101 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_undo));
4103 priv->cc_button = hildon_check_button_new (0);
4104 gtk_button_set_label (GTK_BUTTON (priv->cc_button), _("mcen_me_editor_showcc"));
4105 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button),
4107 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->cc_button),
4109 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
4110 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
4111 priv->bcc_button = hildon_check_button_new (0);
4112 gtk_button_set_label (GTK_BUTTON (priv->bcc_button), _("mcen_me_editor_showbcc"));
4113 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button),
4115 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->bcc_button),
4117 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
4118 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
4120 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_attach_inlineimage"), NULL,
4121 APP_MENU_CALLBACK (modest_ui_actions_on_insert_image),
4122 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_set_style));
4123 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_remove_attachments"), NULL,
4124 APP_MENU_CALLBACK (modest_ui_actions_on_remove_attachments),
4125 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
4126 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_message_settings"), NULL,
4127 APP_MENU_CALLBACK (on_message_settings),
4129 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_viewer_find"), "<Ctrl>f",
4130 APP_MENU_CALLBACK (modest_ui_actions_on_toggle_find_in_page),