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;
1664 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1666 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1668 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1669 g_return_val_if_fail (account_name, NULL);
1672 /* don't free these (except from) */
1673 data = g_slice_new0 (MsgData);
1674 data->from = g_strdup ((gchar *) modest_selector_picker_get_active_display_name (MODEST_SELECTOR_PICKER (priv->from_field)));
1675 data->account_name = g_strdup (account_name);
1676 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1677 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1678 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1679 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1680 data->references = g_strdup (priv->references);
1681 data->in_reply_to = g_strdup (priv->in_reply_to);
1682 if (priv->draft_msg) {
1683 data->draft_msg = g_object_ref (priv->draft_msg);
1684 } else if (priv->outbox_msg) {
1685 data->draft_msg = g_object_ref (priv->outbox_msg);
1687 data->draft_msg = NULL;
1690 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1692 gtk_text_buffer_get_bounds (buf, &b, &e);
1693 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1695 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1696 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1698 data->html_body = NULL;
1700 /* deep-copy the data */
1701 att_iter = tny_list_create_iterator (priv->attachments);
1702 data->attachments = NULL;
1703 while (!tny_iterator_is_done (att_iter)) {
1704 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1705 if (!(TNY_IS_MIME_PART(part))) {
1706 g_warning ("strange data in attachment list");
1707 g_object_unref (part);
1708 tny_iterator_next (att_iter);
1711 data->attachments = g_list_append (data->attachments,
1713 tny_iterator_next (att_iter);
1715 g_object_unref (att_iter);
1717 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1718 att_iter = tny_list_create_iterator (priv->images);
1719 data->images = NULL;
1720 while (!tny_iterator_is_done (att_iter)) {
1721 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1723 if (!(TNY_IS_MIME_PART(part))) {
1724 g_warning ("strange data in attachment list");
1725 g_object_unref (part);
1726 tny_iterator_next (att_iter);
1729 cid = tny_mime_part_get_content_id (part);
1731 gchar *image_tag_id;
1732 GtkTextTag *image_tag;
1734 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1735 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1736 g_free (image_tag_id);
1738 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1740 ((gtk_text_iter_has_tag (&iter, image_tag))||
1741 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1742 data->images = g_list_append (data->images,
1743 g_object_ref (part));
1745 g_object_unref (part);
1746 tny_iterator_next (att_iter);
1748 g_object_unref (att_iter);
1750 data->priority_flags = priv->priority_flags;
1757 unref_gobject (GObject *obj, gpointer data)
1759 if (!G_IS_OBJECT(obj))
1761 g_object_unref (obj);
1765 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1768 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1776 g_free (data->from);
1777 g_free (data->subject);
1778 g_free (data->plain_body);
1779 g_free (data->html_body);
1780 g_free (data->account_name);
1781 g_free (data->references);
1782 g_free (data->in_reply_to);
1784 if (data->draft_msg != NULL) {
1785 g_object_unref (data->draft_msg);
1786 data->draft_msg = NULL;
1789 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1790 g_list_free (data->attachments);
1791 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1792 g_list_free (data->images);
1794 g_slice_free (MsgData, data);
1798 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1800 guint64 *parts_size)
1802 ModestMsgEditWindowPrivate *priv;
1804 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1806 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1808 /* TODO: add images */
1809 *parts_size += priv->images_size;
1810 *parts_count += priv->images_count;
1815 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1818 ModestMsgEditWindowPrivate *priv = NULL;
1819 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1821 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1823 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1825 return MODEST_MSG_EDIT_FORMAT_HTML;
1827 return MODEST_MSG_EDIT_FORMAT_TEXT;
1831 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1832 ModestMsgEditFormat format)
1834 ModestMsgEditWindowPrivate *priv;
1836 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1837 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1840 case MODEST_MSG_EDIT_FORMAT_HTML:
1841 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1843 case MODEST_MSG_EDIT_FORMAT_TEXT:
1844 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1847 g_return_if_reached ();
1851 ModestMsgEditFormatState *
1852 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1854 ModestMsgEditFormatState *format_state = NULL;
1855 ModestMsgEditWindowPrivate *priv;
1856 WPTextBufferFormat *buffer_format;
1858 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1860 buffer_format = g_new0 (WPTextBufferFormat, 1);
1861 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1863 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1865 format_state = g_new0 (ModestMsgEditFormatState, 1);
1866 format_state->bold = buffer_format->bold&0x1;
1867 format_state->italics = buffer_format->italic&0x1;
1868 format_state->bullet = buffer_format->bullet&0x1;
1869 format_state->color = buffer_format->color;
1870 format_state->font_size = buffer_format->font_size;
1871 format_state->font_family = wp_get_font_name (buffer_format->font);
1872 format_state->justification = buffer_format->justification;
1873 g_free (buffer_format);
1875 return format_state;
1880 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1881 const ModestMsgEditFormatState *format_state)
1883 ModestMsgEditWindowPrivate *priv;
1884 WPTextBufferFormat *buffer_format;
1885 WPTextBufferFormat *current_format;
1887 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1888 g_return_if_fail (format_state != NULL);
1890 buffer_format = g_new0 (WPTextBufferFormat, 1);
1891 current_format = g_new0 (WPTextBufferFormat, 1);
1893 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1894 gtk_widget_grab_focus (priv->msg_body);
1895 buffer_format->bold = (format_state->bold != FALSE);
1896 buffer_format->italic = (format_state->italics != FALSE);
1897 buffer_format->color = format_state->color;
1898 buffer_format->font_size = format_state->font_size;
1899 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1900 buffer_format->justification = format_state->justification;
1901 buffer_format->bullet = format_state->bullet;
1903 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1905 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1906 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1907 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1908 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1909 buffer_format->cs.font = (buffer_format->font != current_format->font);
1910 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1911 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1913 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1914 if (buffer_format->cs.bold) {
1915 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
1916 GINT_TO_POINTER (buffer_format->bold&0x1));
1918 if (buffer_format->cs.italic) {
1919 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
1920 GINT_TO_POINTER (buffer_format->italic&0x1));
1922 if (buffer_format->cs.color) {
1923 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1924 GINT_TO_POINTER (&(buffer_format->color)));
1926 if (buffer_format->cs.font_size) {
1927 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1928 GINT_TO_POINTER (buffer_format->font_size));
1930 if (buffer_format->cs.justification) {
1931 switch (buffer_format->justification) {
1932 case GTK_JUSTIFY_LEFT:
1933 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
1934 GINT_TO_POINTER(TRUE));
1936 case GTK_JUSTIFY_CENTER:
1937 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
1938 GINT_TO_POINTER(TRUE));
1940 case GTK_JUSTIFY_RIGHT:
1941 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
1942 GINT_TO_POINTER(TRUE));
1949 if (buffer_format->cs.font) {
1950 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1951 GINT_TO_POINTER (buffer_format->font));
1953 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1954 if (buffer_format->cs.bullet) {
1955 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
1956 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
1958 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1960 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
1962 g_free (buffer_format);
1963 g_free (current_format);
1965 /* Check dimming rules */
1966 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1967 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1971 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1973 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1975 ModestWindowPrivate *parent_priv;
1976 ModestMsgEditWindowPrivate *priv;
1978 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1979 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1981 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1982 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu");
1983 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1984 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1986 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatPlainTextMenu");
1987 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1988 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1991 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1993 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1994 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1996 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1997 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1999 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
2000 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
2003 switch (buffer_format->justification)
2005 case GTK_JUSTIFY_LEFT:
2006 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2008 case GTK_JUSTIFY_CENTER:
2009 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2011 case GTK_JUSTIFY_RIGHT:
2012 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2019 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
2021 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
2022 G_CALLBACK (modest_msg_edit_window_color_button_change),
2024 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
2025 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
2026 G_CALLBACK (modest_msg_edit_window_color_button_change),
2029 if (priv->current_size_index != buffer_format->font_size) {
2033 path = gtk_tree_path_new_from_indices (buffer_format->font_size, -1);
2034 if (gtk_tree_model_get_iter (priv->sizes_model, &iter, path)) {
2038 priv->current_size_index = buffer_format->font_size;
2040 gtk_tree_model_get (priv->sizes_model, &iter, 0, &size_text, -1);
2041 markup = g_strconcat ("<span font_family='Sans'>",
2042 size_text, "</span>", NULL);
2044 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2048 gtk_tree_path_free (path);
2051 if (priv->current_face_index != buffer_format->font) {
2055 path = gtk_tree_path_new_from_indices (buffer_format->font, -1);
2056 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2060 priv->current_face_index = buffer_format->font;
2061 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2062 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2063 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2070 g_free (buffer_format);
2074 #ifdef MODEST_HILDON_VERSION_0
2076 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2079 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2080 ModestMsgEditWindowPrivate *priv;
2081 GtkWidget *dialog = NULL;
2083 GdkColor *new_color = NULL;
2085 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2086 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2088 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2089 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
2090 g_free (buffer_format);
2092 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2093 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2094 if (new_color != NULL) {
2095 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2096 (gpointer) new_color);
2099 gtk_widget_destroy (dialog);
2104 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2107 ModestMsgEditWindowPrivate *priv;
2108 GtkWidget *dialog = NULL;
2110 GdkColor *old_color = NULL;
2111 const GdkColor *new_color = NULL;
2113 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2114 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2116 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2117 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2119 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2120 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2121 if (new_color != NULL)
2122 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2124 gtk_widget_destroy (dialog);
2130 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2133 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2134 ModestMsgEditWindowPrivate *priv;
2135 GtkWidget *dialog = NULL;
2137 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2138 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2140 dialog = hildon_color_chooser_new ();
2141 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2142 g_free (buffer_format);
2144 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2146 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2147 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2150 gtk_widget_destroy (dialog);
2155 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2158 ModestMsgEditWindowPrivate *priv;
2159 GtkWidget *dialog = NULL;
2160 GdkColor *old_color = NULL;
2162 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2163 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2165 dialog = hildon_color_chooser_new ();
2166 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2168 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2170 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2171 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2173 gtk_widget_destroy (dialog);
2176 #endif /*!MODEST_HILDON_VERSION_0*/
2181 create_stream_for_uri (const gchar* uri)
2186 TnyStream *result = NULL;
2188 GnomeVFSHandle *handle = NULL;
2189 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2190 if (test == GNOME_VFS_OK) {
2191 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2192 /* Streams over OBEX (Bluetooth) are not seekable but
2193 * we expect them to be (we might need to read them
2194 * several times). So if this is a Bluetooth URI just
2195 * read the whole file into memory (this is not a fast
2196 * protocol so we can assume that these files are not
2197 * going to be very big) */
2198 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2199 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2200 TnyStream *memstream = tny_camel_mem_stream_new ();
2201 tny_stream_write_to_stream (vfssstream, memstream);
2202 g_object_unref (vfssstream);
2205 result = vfssstream;
2213 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2216 ModestMsgEditWindowPrivate *priv;
2217 GtkWidget *dialog = NULL;
2219 GSList *uris = NULL;
2220 GSList *uri_node = NULL;
2222 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2224 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2225 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2226 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2228 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2230 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2231 GTK_WINDOW (dialog), GTK_WINDOW (window));
2233 response = gtk_dialog_run (GTK_DIALOG (dialog));
2235 case GTK_RESPONSE_OK:
2237 gchar *current_folder;
2238 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2239 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2240 if (current_folder && current_folder != '\0') {
2242 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_INSERT_IMAGE_PATH,
2243 current_folder, &err);
2245 g_debug ("Error storing latest used folder: %s", err->message);
2249 g_free (current_folder);
2255 gtk_widget_destroy (dialog);
2257 g_object_ref (window);
2258 /* The operation could take some time so allow the dialog to be closed */
2259 while (gtk_events_pending ())
2260 gtk_main_iteration ();
2262 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2264 GnomeVFSHandle *handle = NULL;
2265 GnomeVFSResult result;
2266 GtkTextIter position;
2267 GtkTextMark *insert_mark;
2269 uri = (const gchar *) uri_node->data;
2270 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2271 if (result == GNOME_VFS_OK) {
2273 GnomeVFSFileInfo *info;
2274 gchar *filename, *basename, *escaped_filename;
2275 TnyMimePart *mime_part;
2277 const gchar *mime_type = NULL;
2278 GnomeVFSURI *vfs_uri;
2279 guint64 stream_size;
2281 gnome_vfs_close (handle);
2282 vfs_uri = gnome_vfs_uri_new (uri);
2284 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2285 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2286 g_free (escaped_filename);
2287 gnome_vfs_uri_unref (vfs_uri);
2288 info = gnome_vfs_file_info_new ();
2290 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2291 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2293 mime_type = gnome_vfs_file_info_get_mime_type (info);
2295 mime_part = tny_platform_factory_new_mime_part
2296 (modest_runtime_get_platform_factory ());
2298 TnyStream *stream = create_stream_for_uri (uri);
2300 if (stream == NULL) {
2302 modest_platform_information_banner (NULL, NULL,
2303 _FM("sfil_ib_opening_not_allowed"));
2305 g_object_unref (mime_part);
2306 gnome_vfs_file_info_unref (info);
2310 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2312 content_id = g_strdup_printf ("%d", priv->next_cid);
2313 tny_mime_part_set_content_id (mime_part, content_id);
2314 g_free (content_id);
2317 basename = g_path_get_basename (filename);
2318 tny_mime_part_set_filename (mime_part, basename);
2321 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, window);
2323 if (pixbuf != NULL) {
2324 priv->images_size += stream_size;
2325 priv->images_count ++;
2326 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2327 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2328 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position,
2329 tny_mime_part_get_content_id (mime_part), pixbuf);
2330 g_object_unref (pixbuf);
2332 tny_list_prepend (priv->images, (GObject *) mime_part);
2333 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2335 modest_platform_information_banner (NULL, NULL,
2336 _("mail_ib_file_operation_failed"));
2340 g_object_unref (mime_part);
2341 gnome_vfs_file_info_unref (info);
2345 g_object_unref (window);
2349 on_attach_file_response (GtkDialog *dialog,
2353 GSList *uris = NULL;
2355 GnomeVFSFileSize total_size, allowed_size;
2356 ModestMsgEditWindow *window;
2357 ModestMsgEditWindowPrivate *priv;
2362 case GTK_RESPONSE_OK:
2364 gchar *current_folder;
2366 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2367 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2368 if (current_folder && current_folder != '\0') {
2370 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_ATTACH_FILE_PATH,
2371 current_folder, &err);
2373 g_debug ("Error storing latest used folder: %s", err->message);
2377 g_free (current_folder);
2384 window = MODEST_MSG_EDIT_WINDOW (user_data);
2385 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2387 /* allowed size is the maximum size - what's already there */
2388 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2389 &att_num, &att_size);
2390 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2393 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2395 const gchar *uri = (const gchar *) uri_node->data;
2398 modest_msg_edit_window_attach_file_one (window, uri, allowed_size);
2400 if (total_size > allowed_size) {
2401 g_warning ("%s: total size: %u",
2402 __FUNCTION__, (unsigned int)total_size);
2405 allowed_size -= total_size;
2407 g_slist_foreach (uris, (GFunc) g_free, NULL);
2408 g_slist_free (uris);
2410 gtk_widget_destroy (GTK_WIDGET (dialog));
2414 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2416 GtkWidget *dialog = NULL;
2417 ModestMsgEditWindowPrivate *priv;
2420 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2422 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2424 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2427 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window),
2428 GTK_FILE_CHOOSER_ACTION_OPEN);
2429 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2430 conf_folder = modest_conf_get_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_ATTACH_FILE_PATH, NULL);
2431 if (conf_folder && conf_folder[0] != '\0') {
2432 gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (dialog), conf_folder);
2435 /* Set the default folder to images folder */
2436 docs_folder = g_build_filename (g_getenv (MODEST_MAEMO_UTILS_MYDOCS_ENV),
2437 ".documents", NULL);
2438 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), docs_folder);
2439 g_free (docs_folder);
2441 g_free (conf_folder);
2442 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2443 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2444 GTK_WINDOW (dialog), GTK_WINDOW (window));
2446 /* Connect to response & show */
2447 g_signal_connect (dialog, "response",
2448 G_CALLBACK (on_attach_file_response), window);
2449 gtk_widget_show (dialog);
2454 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2456 GnomeVFSFileSize allowed_size)
2459 GnomeVFSHandle *handle = NULL;
2460 ModestMsgEditWindowPrivate *priv;
2461 GnomeVFSResult result;
2462 GnomeVFSFileSize size = 0;
2463 g_return_val_if_fail (window, 0);
2464 g_return_val_if_fail (uri, 0);
2466 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2468 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2469 if (result == GNOME_VFS_OK) {
2470 TnyMimePart *mime_part;
2472 const gchar *mime_type = NULL;
2474 gchar *escaped_filename;
2477 GnomeVFSFileInfo *info;
2478 GnomeVFSURI *vfs_uri;
2480 gnome_vfs_close (handle);
2481 vfs_uri = gnome_vfs_uri_new (uri);
2484 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2485 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2486 g_free (escaped_filename);
2487 gnome_vfs_uri_unref (vfs_uri);
2489 info = gnome_vfs_file_info_new ();
2491 if (gnome_vfs_get_file_info (uri,
2493 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2495 mime_type = gnome_vfs_file_info_get_mime_type (info);
2496 mime_part = tny_platform_factory_new_mime_part
2497 (modest_runtime_get_platform_factory ());
2499 /* try to get the attachment's size; this may fail for weird
2500 * file systems, like obex, upnp... */
2501 if (allowed_size != 0 &&
2502 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2504 if (size > allowed_size) {
2505 modest_platform_information_banner (NULL, NULL,
2506 _FM("sfil_ib_opening_not_allowed"));
2511 g_warning ("%s: could not get attachment size", __FUNCTION__);
2513 stream = create_stream_for_uri (uri);
2515 if (stream == NULL) {
2517 modest_platform_information_banner (NULL, NULL, _FM("sfil_ib_opening_not_allowed"));
2519 g_object_unref (mime_part);
2521 gnome_vfs_file_info_unref (info);
2525 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2526 g_object_unref (stream);
2528 content_id = g_strdup_printf ("%d", priv->next_cid);
2529 tny_mime_part_set_content_id (mime_part, content_id);
2530 g_free (content_id);
2533 basename = g_path_get_basename (filename);
2534 tny_mime_part_set_filename (mime_part, basename);
2537 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2538 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2540 info->size == 0, info->size);
2541 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2542 gtk_widget_show_all (priv->attachments_caption);
2543 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2545 g_object_unref (mime_part);
2546 gnome_vfs_file_info_unref (info);
2553 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2556 ModestMsgEditWindowPrivate *priv;
2559 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2560 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2562 if (att_list == NULL) {
2563 att_list = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2564 if (!modest_maemo_utils_select_attachments (GTK_WINDOW (window), att_list, TRUE)) {
2565 g_object_unref (att_list);
2570 g_object_ref (att_list);
2573 if (tny_list_get_length (att_list) == 0) {
2574 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2576 gboolean dialog_response;
2577 gchar *message = NULL;
2578 gchar *filename = NULL;
2580 if (tny_list_get_length (att_list) == 1) {
2582 iter = tny_list_create_iterator (att_list);
2583 part = (TnyMimePart *) tny_iterator_get_current (iter);
2584 g_object_unref (iter);
2585 if (TNY_IS_MSG (part)) {
2586 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2588 filename = tny_header_dup_subject (header);
2589 g_object_unref (header);
2591 if (filename == NULL) {
2592 filename = g_strdup (_("mail_va_no_subject"));
2595 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2597 g_object_unref (part);
2599 filename = g_strdup ("");
2601 message = g_strdup_printf (ngettext("emev_nc_delete_attachment",
2602 "emev_nc_delete_attachments",
2603 tny_list_get_length (att_list)), filename);
2606 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
2610 if (dialog_response != GTK_RESPONSE_OK) {
2611 g_object_unref (att_list);
2615 for (iter = tny_list_create_iterator (att_list);
2616 !tny_iterator_is_done (iter);
2617 tny_iterator_next (iter)) {
2618 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2619 const gchar *att_id;
2620 tny_list_remove (priv->attachments, (GObject *) mime_part);
2622 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2624 if (tny_list_get_length (priv->attachments) == 0)
2625 gtk_widget_hide (priv->attachments_caption);
2626 att_id = tny_mime_part_get_content_id (mime_part);
2628 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2630 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2631 g_object_unref (mime_part);
2633 g_object_unref (iter);
2636 g_object_unref (att_list);
2638 /* if the last attachment has been removed, focus the Subject: field */
2639 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2640 gtk_widget_grab_focus (priv->subject_field);
2644 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2647 ModestMsgEditWindowPrivate *priv;
2648 GdkColor *new_color;
2649 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2651 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2652 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2655 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2657 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2659 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2661 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2666 font_size_clicked (GtkToolButton *button,
2667 ModestMsgEditWindow *window)
2669 ModestMsgEditWindowPrivate *priv;
2670 GtkWidget *selector, *dialog;
2672 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2674 selector = hildon_touch_selector_new ();
2675 hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector), priv->sizes_model, TRUE);
2676 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_size_index);
2678 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2679 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2680 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_size"));
2682 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2686 WPTextBufferFormat format;
2688 new_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2690 memset (&format, 0, sizeof (format));
2691 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2693 format.cs.font_size = TRUE;
2694 format.cs.text_position = TRUE;
2695 format.cs.font = TRUE;
2696 format.font_size = new_index;
2697 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2699 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2700 GINT_TO_POINTER (new_index)))
2701 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2703 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2704 size_text = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (selector));
2705 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
2706 size_text, "</span>", NULL);
2708 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2712 gtk_widget_destroy (dialog);
2714 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2719 font_face_clicked (GtkToolButton *button,
2720 ModestMsgEditWindow *window)
2722 ModestMsgEditWindowPrivate *priv;
2723 GtkWidget *selector, *dialog;
2724 GtkCellRenderer *renderer;
2726 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2728 selector = hildon_touch_selector_new ();
2729 renderer = gtk_cell_renderer_text_new ();
2730 hildon_touch_selector_append_column (HILDON_TOUCH_SELECTOR (selector), priv->faces_model,
2731 renderer, "family", 0, "text", 0, NULL);
2732 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_face_index);
2734 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2735 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2736 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_face"));
2738 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2739 gint new_font_index;
2743 new_font_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2744 path = gtk_tree_path_new_from_indices (new_font_index, -1);
2745 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2749 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2751 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2752 GINT_TO_POINTER(new_font_index)))
2753 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2755 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2756 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2758 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2762 gtk_tree_path_free (path);
2765 gtk_widget_destroy (dialog);
2767 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2772 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2775 ModestMsgEditWindowPrivate *priv = NULL;
2776 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2778 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2779 if (!priv->update_caption_visibility)
2782 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2784 gtk_widget_show (priv->cc_caption);
2786 gtk_widget_hide (priv->cc_caption);
2788 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2792 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2795 ModestMsgEditWindowPrivate *priv = NULL;
2796 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2798 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2799 if (!priv->update_caption_visibility)
2802 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2804 gtk_widget_show (priv->bcc_caption);
2806 gtk_widget_hide (priv->bcc_caption);
2808 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2812 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2813 ModestRecptEditor *editor)
2815 ModestMsgEditWindowPrivate *priv;
2817 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2818 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2820 /* we check for low-mem; in that case, show a warning, and don't allow
2821 * for the addressbook
2823 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2826 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2828 if (editor == NULL) {
2829 GtkWidget *view_focus;
2830 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2832 /* This code should be kept in sync with ModestRecptEditor. The
2833 textview inside the recpt editor is the one that really gets the
2834 focus. As it's inside a scrolled window, and this one inside the
2835 hbox recpt editor inherits from, we'll need to go up in the
2836 hierarchy to know if the text view is part of the recpt editor
2837 or if it's a different text entry */
2839 if (gtk_widget_get_parent (view_focus)) {
2840 GtkWidget *first_parent;
2842 first_parent = gtk_widget_get_parent (view_focus);
2843 if (gtk_widget_get_parent (first_parent) &&
2844 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2845 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2850 editor = MODEST_RECPT_EDITOR (priv->to_field);
2854 modest_address_book_select_addresses (editor);
2859 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2861 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2863 modest_msg_edit_window_open_addressbook (window, NULL);
2867 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2868 gboolean show_toolbar)
2870 ModestWindowPrivate *parent_priv;
2872 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2873 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2875 /* We can not just use the code of
2876 modest_msg_edit_window_setup_toolbar because it has a
2877 mixture of both initialization and creation code. */
2879 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2881 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2885 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2886 TnyHeaderFlags priority_flags)
2888 ModestMsgEditWindowPrivate *priv;
2889 ModestWindowPrivate *parent_priv;
2891 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2893 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2894 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2896 if (priv->priority_flags != priority_flags) {
2897 GtkAction *priority_action = NULL;
2899 priv->priority_flags = priority_flags;
2901 switch (priority_flags) {
2902 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2903 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2904 MODEST_HEADER_ICON_HIGH,
2905 HILDON_ICON_SIZE_SMALL);
2906 gtk_widget_show (priv->priority_icon);
2907 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2908 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2910 case TNY_HEADER_FLAG_LOW_PRIORITY:
2911 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2912 MODEST_HEADER_ICON_LOW,
2913 HILDON_ICON_SIZE_SMALL);
2914 gtk_widget_show (priv->priority_icon);
2915 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2916 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2919 gtk_widget_hide (priv->priority_icon);
2920 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2921 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2924 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2925 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2927 gtk_widget_queue_resize (priv->subject_box);
2931 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2934 ModestMsgEditWindowPrivate *priv;
2935 ModestWindowPrivate *parent_priv;
2936 gint current_format;
2938 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2940 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2941 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2943 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2944 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2946 if (current_format != file_format) {
2947 switch (file_format) {
2948 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2949 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2950 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
2952 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2956 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2957 response = gtk_dialog_run (GTK_DIALOG (dialog));
2958 gtk_widget_destroy (dialog);
2959 if (response == GTK_RESPONSE_OK) {
2960 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2962 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
2963 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
2968 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2969 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2970 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2975 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2978 ModestMsgEditWindowPrivate *priv;
2979 WPTextBufferFormat oldfmt, fmt;
2980 gint old_position = 0;
2984 GdkColor *color = NULL;
2985 gboolean bold, bold_set, italic, italic_set;
2986 gboolean underline, underline_set;
2987 gboolean strikethrough, strikethrough_set;
2988 gboolean position_set;
2989 gboolean font_size_set, font_set, color_set;
2992 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2993 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2995 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2996 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
2997 GTK_WINDOW(dialog), GTK_WINDOW (window));
2999 /* First we get the currently selected font information */
3000 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
3002 switch (oldfmt.text_position) {
3003 case TEXT_POSITION_NORMAL:
3006 case TEXT_POSITION_SUPERSCRIPT:
3014 g_object_set (G_OBJECT (dialog),
3015 "bold", oldfmt.bold != FALSE,
3016 "bold-set", !oldfmt.cs.bold,
3017 "underline", oldfmt.underline != FALSE,
3018 "underline-set", !oldfmt.cs.underline,
3019 "italic", oldfmt.italic != FALSE,
3020 "italic-set", !oldfmt.cs.italic,
3021 "strikethrough", oldfmt.strikethrough != FALSE,
3022 "strikethrough-set", !oldfmt.cs.strikethrough,
3023 "color", &oldfmt.color,
3024 "color-set", !oldfmt.cs.color,
3025 "size", wp_font_size[oldfmt.font_size],
3026 "size-set", !oldfmt.cs.font_size,
3027 "position", old_position,
3028 "position-set", !oldfmt.cs.text_position,
3029 "family", wp_get_font_name (oldfmt.font),
3030 "family-set", !oldfmt.cs.font,
3033 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
3034 GTK_WINDOW (dialog), GTK_WINDOW (window));
3035 gtk_widget_show_all (dialog);
3036 priv->font_dialog = dialog;
3037 response = gtk_dialog_run (GTK_DIALOG (dialog));
3038 priv->font_dialog = NULL;
3039 if (response == GTK_RESPONSE_OK) {
3041 g_object_get( dialog,
3043 "bold-set", &bold_set,
3044 "underline", &underline,
3045 "underline-set", &underline_set,
3047 "italic-set", &italic_set,
3048 "strikethrough", &strikethrough,
3049 "strikethrough-set", &strikethrough_set,
3051 "color-set", &color_set,
3053 "size-set", &font_size_set,
3054 "family", &font_name,
3055 "family-set", &font_set,
3056 "position", &position,
3057 "position-set", &position_set,
3062 if (response == GTK_RESPONSE_OK) {
3063 memset(&fmt, 0, sizeof(fmt));
3069 fmt.italic = italic;
3070 fmt.cs.italic = TRUE;
3072 if (underline_set) {
3073 fmt.underline = underline;
3074 fmt.cs.underline = TRUE;
3076 if (strikethrough_set) {
3077 fmt.strikethrough = strikethrough;
3078 fmt.cs.strikethrough = TRUE;
3083 ? TEXT_POSITION_NORMAL
3084 : ( ( position == 1 )
3085 ? TEXT_POSITION_SUPERSCRIPT
3086 : TEXT_POSITION_SUBSCRIPT );
3087 fmt.cs.text_position = TRUE;
3088 fmt.font_size = oldfmt.font_size;
3092 fmt.cs.color = TRUE;
3095 fmt.font = wp_get_font_index(font_name,
3100 if (font_size_set) {
3101 fmt.cs.font_size = TRUE;
3102 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
3104 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
3105 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3107 gtk_widget_destroy (dialog);
3109 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
3113 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
3115 ModestMsgEditWindowPrivate *priv;
3117 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3118 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3120 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
3122 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3123 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3127 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
3129 ModestMsgEditWindowPrivate *priv;
3131 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3132 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3134 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
3136 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3137 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3142 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
3144 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3146 priv->can_undo = can_undo;
3150 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
3152 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3154 priv->can_redo = can_redo;
3158 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3160 ModestMsgEditWindowPrivate *priv;
3161 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3162 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3164 return priv->can_undo;
3168 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3170 ModestMsgEditWindowPrivate *priv;
3171 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3172 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3174 return priv->can_redo;
3179 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3182 GtkTextIter match_start, match_end;
3184 if (image_id == NULL)
3187 gtk_text_buffer_get_start_iter (buffer, &iter);
3189 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3190 GSList *tags = gtk_text_iter_get_tags (&match_start);
3192 for (node = tags; node != NULL; node = g_slist_next (node)) {
3193 GtkTextTag *tag = (GtkTextTag *) node->data;
3194 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3195 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3196 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3198 offset = gtk_text_iter_get_offset (&match_start);
3199 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3200 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3204 gtk_text_iter_forward_char (&iter);
3209 message_is_empty (ModestMsgEditWindow *window)
3211 ModestMsgEditWindowPrivate *priv = NULL;
3213 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3214 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3216 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3217 * so we can ignore markup.
3219 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3222 count = gtk_text_buffer_get_char_count (buf);
3228 msg_body_focus (GtkWidget *focus,
3229 GdkEventFocus *event,
3233 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3234 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3235 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3240 recpt_field_changed (GtkTextBuffer *buffer,
3241 ModestMsgEditWindow *editor)
3243 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3244 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3248 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3250 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3251 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3255 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3258 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3259 GtkTextBuffer *buffer;
3261 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3262 gtk_text_buffer_set_modified (buffer, modified);
3263 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3264 gtk_text_buffer_set_modified (buffer, modified);
3265 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3266 gtk_text_buffer_set_modified (buffer, modified);
3267 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3271 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3273 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3274 const char *account_name;
3275 GtkTextBuffer *buffer;
3277 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3278 if (gtk_text_buffer_get_modified (buffer))
3280 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3281 if (gtk_text_buffer_get_modified (buffer))
3283 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3284 if (gtk_text_buffer_get_modified (buffer))
3286 if (gtk_text_buffer_get_modified (priv->text_buffer))
3289 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3290 if ((priv->original_mailbox) &&
3291 (!account_name || strcmp (account_name, priv->original_mailbox)))
3293 if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3304 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3306 ModestMsgEditWindowPrivate *priv = NULL;
3308 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3309 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3311 /* check if there's no recipient added */
3312 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3313 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3314 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3315 /* no recipient contents, then select contacts */
3316 modest_msg_edit_window_open_addressbook (window, NULL);
3320 g_object_ref (window);
3321 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3322 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3323 g_object_unref (window);
3326 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3327 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3328 g_object_unref (window);
3331 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3332 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3333 g_object_unref (window);
3337 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3338 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3339 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3340 g_object_unref (window);
3347 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3348 ModestMsgEditWindow *window)
3350 modest_msg_edit_window_offer_attach_file (window);
3354 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3356 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3358 return priv->clipboard_text;
3362 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3364 ModestMsgEditWindow *window)
3366 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3367 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3370 /* It could happen that the window was already closed */
3371 if (!GTK_WIDGET_VISIBLE (window))
3374 g_object_ref (window);
3375 text = gtk_clipboard_wait_for_text (selection_clipboard);
3377 if (priv->clipboard_text != NULL) {
3378 g_free (priv->clipboard_text);
3380 priv->clipboard_text = text;
3382 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3384 g_object_unref (window);
3387 static gboolean clipboard_owner_change_idle (gpointer userdata)
3389 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3390 ModestMsgEditWindowPrivate *priv;
3392 gdk_threads_enter ();
3393 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3394 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3396 priv->clipboard_owner_idle = 0;
3397 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3398 gdk_threads_leave ();
3404 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3406 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3407 if (priv->clipboard_owner_idle == 0) {
3408 priv->clipboard_owner_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
3409 clipboard_owner_change_idle,
3410 g_object_ref (window),
3416 subject_field_move_cursor (GtkEntry *entry,
3417 GtkMovementStep step,
3422 /* It could happen that the window was already closed */
3423 if (!GTK_WIDGET_VISIBLE (window))
3426 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3430 update_window_title (ModestMsgEditWindow *window)
3432 ModestMsgEditWindowPrivate *priv = NULL;
3433 const gchar *subject;
3435 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3436 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3437 if (subject == NULL || subject[0] == '\0')
3438 subject = _("mail_va_new_email");
3440 gtk_window_set_title (GTK_WINDOW (window), subject);
3445 subject_field_changed (GtkEditable *editable,
3446 ModestMsgEditWindow *window)
3448 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3449 update_window_title (window);
3450 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3451 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3452 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3456 subject_field_insert_text (GtkEditable *editable,
3458 gint new_text_length,
3460 ModestMsgEditWindow *window)
3462 GString *result = g_string_new ("");
3464 gint result_len = 0;
3465 const gchar *entry_text = NULL;
3468 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3469 old_length = g_utf8_strlen (entry_text, -1);
3471 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3472 gunichar c = g_utf8_get_char_validated (current, 8);
3473 /* Invalid unichar, stop */
3479 result = g_string_append_unichar (result, c);
3483 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3484 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3487 /* Prevent endless recursion */
3488 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3489 g_signal_emit_by_name (editable, "insert-text",
3490 (gpointer) result->str, (gpointer) result->len,
3491 (gpointer) position, (gpointer) window);
3492 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3496 if (result_len + old_length > 1000) {
3497 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3498 _CS("ckdg_ib_maximum_characters_reached"));
3500 g_string_free (result, TRUE);
3504 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3507 ModestMsgEditWindowPrivate *priv = NULL;
3509 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3510 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3512 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3515 gtk_widget_show_all (priv->find_toolbar);
3516 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3518 gtk_widget_hide_all (priv->find_toolbar);
3519 gtk_widget_grab_focus (priv->msg_body);
3524 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3526 GtkTextIter *match_start,
3527 GtkTextIter *match_end)
3529 GtkTextIter end_iter;
3530 gchar *str_casefold;
3533 gchar *range_casefold;
3536 gboolean result = FALSE;
3543 gtk_text_iter_forward_to_end (&end_iter);
3545 str_casefold = g_utf8_casefold (str, -1);
3546 str_chars_n = strlen (str);
3548 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3549 range_casefold = g_utf8_casefold (range_text, -1);
3550 range_chars_n = strlen (range_casefold);
3552 if (range_chars_n < str_chars_n) {
3553 g_free (str_casefold);
3554 g_free (range_text);
3555 g_free (range_casefold);
3559 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3560 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3561 if (!g_utf8_collate (range_subtext, str_casefold)) {
3562 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3564 if (!gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3565 match_start, match_end, NULL)) {
3566 g_warning ("Matched string with collate, but not matched in model");
3568 g_free (found_text);
3570 g_free (range_subtext);
3574 g_free (str_casefold);
3575 g_free (range_text);
3576 g_free (range_casefold);
3583 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3584 ModestMsgEditWindow *window)
3586 gchar *current_search = NULL;
3587 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3589 GtkTextIter selection_start, selection_end;
3590 GtkTextIter match_start, match_end;
3591 gboolean continue_search = FALSE;
3593 if (message_is_empty (window)) {
3594 g_free (priv->last_search);
3595 priv->last_search = NULL;
3596 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3600 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3601 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3602 g_free (current_search);
3603 g_free (priv->last_search);
3604 priv->last_search = NULL;
3605 /* Information banner about empty search */
3606 hildon_banner_show_information (NULL, NULL, _CS("ecdg_ib_find_rep_enter_text"));
3610 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3611 continue_search = TRUE;
3613 g_free (priv->last_search);
3614 priv->last_search = g_strdup (current_search);
3617 if (continue_search) {
3618 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3619 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3620 &match_start, &match_end);
3622 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_search_complete"));
3624 GtkTextIter buffer_start;
3625 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3626 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3627 &match_start, &match_end);
3629 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_no_matches"));
3632 /* Mark as selected the string found in search */
3634 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3635 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3636 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3638 g_free (priv->last_search);
3639 priv->last_search = NULL;
3641 g_free (current_search);
3645 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3647 ModestMsgEditWindowPrivate *priv;
3649 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3654 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3657 ModestMsgEditWindowPrivate *priv;
3659 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3664 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3665 ModestMsgEditWindow *window)
3667 modest_msg_edit_window_toggle_find_toolbar (window, FALSE);
3671 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3674 ModestMsgEditWindowPrivate *priv;
3675 TnyHeader *header = NULL;
3677 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3678 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3680 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3682 if (priv->draft_msg != NULL) {
3683 g_object_unref (priv->draft_msg);
3686 if (draft != NULL) {
3687 g_object_ref (draft);
3688 header = tny_msg_get_header (draft);
3689 if (priv->msg_uid) {
3690 g_free (priv->msg_uid);
3691 priv->msg_uid = NULL;
3693 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3696 priv->draft_msg = draft;
3700 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3701 GtkTextIter *start, GtkTextIter *end,
3704 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3705 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3708 if (tag == NULL) return;
3709 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3710 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3711 replace_with_images (window, priv->images);
3716 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3719 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3721 g_return_if_fail (TNY_IS_MIME_PART (part));
3722 tny_list_prepend (priv->attachments, (GObject *) part);
3723 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3724 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3725 gtk_widget_show_all (priv->attachments_caption);
3726 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3730 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3732 ModestMsgEditWindowPrivate *priv;
3734 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3735 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3737 return priv->msg_uid;
3741 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3742 ModestMsgEditWindowWidgetType widget_type)
3744 ModestMsgEditWindowPrivate *priv;
3746 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3747 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3749 switch (widget_type) {
3750 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3751 return priv->msg_body;
3753 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3754 return priv->to_field;
3756 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3757 return priv->cc_field;
3759 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3760 return priv->bcc_field;
3762 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3763 return priv->subject_field;
3765 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3766 return priv->attachments_view;
3774 remove_tags (WPTextBuffer *buffer)
3776 GtkTextIter start, end;
3778 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3779 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3781 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3785 on_account_removed (TnyAccountStore *account_store,
3786 TnyAccount *account,
3789 /* Do nothing if it's a store account, because we use the
3790 transport to send the messages */
3791 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3792 const gchar *parent_acc = NULL;
3793 const gchar *our_acc = NULL;
3795 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3796 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3797 /* Close this window if I'm showing a message of the removed account */
3798 if (strcmp (parent_acc, our_acc) == 0)
3799 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3804 from_field_changed (HildonPickerButton *button,
3805 ModestMsgEditWindow *self)
3807 ModestMsgEditWindowPrivate *priv;
3808 gboolean has_old_signature, has_new_signature;
3810 GtkTextIter match_start, match_end;
3811 ModestAccountMgr *mgr;
3813 gchar *full_signature;
3815 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3817 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
3818 mgr = modest_runtime_get_account_mgr ();
3819 signature = modest_account_mgr_get_signature (mgr, priv->last_from_account, &has_old_signature);
3820 if (has_old_signature) {
3821 full_signature = g_strconcat ("\n--\n", signature, NULL);
3822 if (gtk_text_iter_forward_search (&iter, full_signature, 0, &match_start, &match_end, NULL)) {
3823 gtk_text_buffer_delete (priv->text_buffer, &match_start, &match_end);
3825 } else if (gtk_text_iter_forward_search (&iter, _("mcen_ia_editor_original_message"), 0,
3826 &match_start, &match_end, NULL)) {
3829 g_free (full_signature);
3833 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3834 signature = modest_account_mgr_get_signature (mgr, priv->last_from_account, &has_new_signature);
3835 if (has_new_signature) {
3836 full_signature = g_strconcat ("\n--\n", signature, NULL);
3837 gtk_text_buffer_insert (priv->text_buffer, &iter, full_signature, -1);
3838 g_free (full_signature);
3843 typedef struct _MessageSettingsHelper {
3844 ModestMsgEditWindow *window;
3845 GSList *priority_group;
3846 GSList *format_group;
3847 GtkToggleButton *current_priority;
3848 GtkToggleButton *current_format;
3849 } MessageSettingsHelper;
3852 on_priority_toggle (GtkToggleButton *button,
3853 MessageSettingsHelper *helper)
3856 ModestMsgEditWindowPrivate *priv;
3858 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3859 if (gtk_toggle_button_get_active (button)) {
3861 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3862 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3863 if ((node_button != button) &&
3864 gtk_toggle_button_get_active (node_button)) {
3865 gtk_toggle_button_set_active (node_button, FALSE);
3868 helper->current_priority = button;
3870 gboolean found = FALSE;
3871 /* If no one is active, activate it again */
3872 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3873 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3874 if (gtk_toggle_button_get_active (node_button)) {
3880 gtk_toggle_button_set_active (button, TRUE);
3886 on_format_toggle (GtkToggleButton *button,
3887 MessageSettingsHelper *helper)
3890 ModestMsgEditWindowPrivate *priv;
3892 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3893 if (gtk_toggle_button_get_active (button)) {
3895 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
3896 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3897 if ((node_button != button) &&
3898 gtk_toggle_button_get_active (node_button)) {
3899 gtk_toggle_button_set_active (node_button, FALSE);
3902 helper->current_format = button;
3904 gboolean found = FALSE;
3905 /* If no one is active, activate it again */
3906 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
3907 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3908 if (gtk_toggle_button_get_active (node_button)) {
3914 gtk_toggle_button_set_active (button, TRUE);
3921 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
3926 GtkWidget *priority_hbox;
3927 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
3928 GtkWidget *captioned;
3929 GtkSizeGroup *title_sizegroup, *value_sizegroup;
3930 GtkWidget *format_hbox;
3931 GtkWidget *html_toggle, *text_toggle;
3932 ModestMsgEditWindowPrivate *priv;
3933 MessageSettingsHelper helper = {0,};
3935 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3936 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3937 helper.window = window;
3938 helper.priority_group = NULL;
3939 helper.format_group = NULL;
3941 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3942 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3944 dialog = gtk_dialog_new_with_buttons (_("mcen_me_message_settings"), NULL,
3945 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
3946 _HL("wdgt_bd_done"), GTK_RESPONSE_ACCEPT, NULL);
3947 vbox = gtk_vbox_new (FALSE, 0);
3948 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
3949 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DOUBLE, 0);
3950 gtk_container_add (GTK_CONTAINER (align), vbox);
3951 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), align);
3952 gtk_widget_show (align);
3953 gtk_widget_show (vbox);
3955 /* Priority toggles */
3956 priority_hbox = gtk_hbox_new (TRUE, 0);
3957 high_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3958 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
3959 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
3960 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
3961 medium_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3962 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
3963 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
3964 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
3965 low_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3966 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
3967 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
3968 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
3969 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, TRUE, TRUE, 0);
3970 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, TRUE, TRUE, 0);
3971 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, TRUE, TRUE, 0);
3972 gtk_widget_show_all (priority_hbox);
3973 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
3974 _("mcen_me_editor_message_priority"), FALSE, priority_hbox);
3975 gtk_widget_show (captioned);
3976 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
3978 /* format toggles */
3979 format_hbox = gtk_hbox_new (TRUE, 0);
3980 html_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3981 gtk_button_set_label (GTK_BUTTON (html_toggle), _("mcen_me_editor_formatted_text"));
3982 helper.format_group = g_slist_prepend (helper.format_group, html_toggle);
3983 g_object_set_data (G_OBJECT (html_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_HTML));
3984 g_object_set_data (G_OBJECT (html_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_FORMATTED_TEXT));
3985 text_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3986 gtk_button_set_label (GTK_BUTTON (text_toggle), _("mcen_me_editor_plain_text"));
3987 helper.format_group = g_slist_prepend (helper.format_group, text_toggle);
3988 g_object_set_data (G_OBJECT (text_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_TEXT));
3989 g_object_set_data (G_OBJECT (text_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_PLAIN_TEXT));
3990 gtk_box_pack_start (GTK_BOX (format_hbox), html_toggle, TRUE, TRUE, 0);
3991 gtk_box_pack_start (GTK_BOX (format_hbox), text_toggle, TRUE, TRUE, 0);
3992 gtk_widget_show_all (format_hbox);
3993 gtk_widget_show (format_hbox);
3994 gtk_box_pack_start (GTK_BOX (vbox), format_hbox, FALSE, FALSE, 0);
3997 g_object_unref (title_sizegroup);
3998 g_object_unref (value_sizegroup);
4000 /* Set current values */
4001 switch (priv->priority_flags) {
4002 case TNY_HEADER_FLAG_HIGH_PRIORITY:
4003 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (high_toggle), TRUE);
4004 helper.current_priority = GTK_TOGGLE_BUTTON (high_toggle);
4006 case TNY_HEADER_FLAG_LOW_PRIORITY:
4007 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (low_toggle), TRUE);
4008 helper.current_priority = GTK_TOGGLE_BUTTON (low_toggle);
4011 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (medium_toggle), TRUE);
4012 helper.current_priority = GTK_TOGGLE_BUTTON (medium_toggle);
4016 switch (modest_msg_edit_window_get_format (window)) {
4017 case MODEST_MSG_EDIT_FORMAT_TEXT:
4018 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_toggle), TRUE);
4019 helper.current_format = GTK_TOGGLE_BUTTON (text_toggle);
4021 case MODEST_MSG_EDIT_FORMAT_HTML:
4023 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (html_toggle), TRUE);
4024 helper.current_format = GTK_TOGGLE_BUTTON (html_toggle);
4028 /* Signal connects */
4029 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4030 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4031 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4032 g_signal_connect (G_OBJECT (html_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4033 g_signal_connect (G_OBJECT (text_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4035 /* Save settings if the user clicked on done */
4036 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
4037 TnyHeaderFlags flags;
4038 ModestMsgEditFormat old_format, new_format;
4040 /* Set priority flags */
4041 flags = (TnyHeaderFlags) g_object_get_data (G_OBJECT (helper.current_priority), "priority");
4042 if (priv->priority_flags != flags)
4043 modest_msg_edit_window_set_priority_flags (window, flags);
4045 /* Set edit format */
4046 old_format = modest_msg_edit_window_get_format (window);
4047 new_format = (ModestMsgEditFormat) g_object_get_data (G_OBJECT (helper.current_format), "format");
4048 if (old_format != new_format) {
4049 gint file_format = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (helper.current_format), "file-format"));
4050 modest_msg_edit_window_set_file_format (window, file_format);
4054 gtk_widget_destroy (dialog);
4055 g_slist_free (helper.priority_group);
4059 on_message_settings (GtkAction *action,
4060 ModestMsgEditWindow *window)
4062 modest_msg_edit_window_show_msg_settings_dialog (window);
4066 on_cc_button_toggled (HildonCheckButton *button,
4067 ModestMsgEditWindow *window)
4069 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4071 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
4072 hildon_check_button_get_active (button));
4076 on_bcc_button_toggled (HildonCheckButton *button,
4077 ModestMsgEditWindow *window)
4079 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4081 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
4082 hildon_check_button_get_active (button));
4086 setup_menu (ModestMsgEditWindow *self)
4088 ModestMsgEditWindowPrivate *priv = NULL;
4090 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
4092 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4094 /* Settings menu buttons */
4095 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_checknames"), NULL,
4096 APP_MENU_CALLBACK (modest_ui_actions_on_check_names),
4098 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_undo"), "<Ctrl>z",
4099 APP_MENU_CALLBACK (modest_ui_actions_on_undo),
4100 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_undo));
4102 priv->cc_button = hildon_check_button_new (0);
4103 gtk_button_set_label (GTK_BUTTON (priv->cc_button), _("mcen_me_editor_showcc"));
4104 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button),
4106 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->cc_button),
4108 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
4109 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
4110 priv->bcc_button = hildon_check_button_new (0);
4111 gtk_button_set_label (GTK_BUTTON (priv->bcc_button), _("mcen_me_editor_showbcc"));
4112 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button),
4114 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->bcc_button),
4116 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
4117 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
4119 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_attach_inlineimage"), NULL,
4120 APP_MENU_CALLBACK (modest_ui_actions_on_insert_image),
4121 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_set_style));
4122 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_remove_attachments"), NULL,
4123 APP_MENU_CALLBACK (modest_ui_actions_on_remove_attachments),
4124 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
4125 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_message_settings"), NULL,
4126 APP_MENU_CALLBACK (on_message_settings),
4128 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_viewer_find"), "<Ctrl>f",
4129 APP_MENU_CALLBACK (modest_ui_actions_on_toggle_find_in_page),