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 update_signature (ModestMsgEditWindow *self,
181 const gchar *old_account,
182 const gchar *new_account);
183 static void DEBUG_BUFFER (WPTextBuffer *buffer)
187 g_message ("BEGIN BUFFER OF SIZE %d", gtk_text_buffer_get_char_count (GTK_TEXT_BUFFER (buffer)));
189 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &iter);
190 while (!gtk_text_iter_is_end (&iter)) {
191 GString *output = g_string_new ("");
192 GSList *toggled_tags;
195 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
196 g_string_append_printf (output, "%d: CLOSED [ ", gtk_text_iter_get_offset (&iter));
197 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
198 GtkTextTag *tag = (GtkTextTag *) node->data;
200 g_object_get (G_OBJECT (tag), "name", &name, NULL);
201 output = g_string_append (output, name);
202 g_string_append (output, " ");
204 output = g_string_append (output, "] OPENED [ ");
205 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
206 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
207 GtkTextTag *tag = (GtkTextTag *) node->data;
209 g_object_get (G_OBJECT (tag), "name", &name, NULL);
210 output = g_string_append (output, name);
211 g_string_append (output, " ");
213 output = g_string_append (output, "]\n");
214 g_message ("%s", output->str);
215 g_string_free (output, TRUE);
216 gtk_text_iter_forward_to_tag_toggle (&iter, NULL);
218 g_message ("END BUFFER");
222 static const GtkActionEntry hildon2_msg_edit_action_entries [] = {
223 { "MessageSettings", NULL, N_("mcen_me_message_settings"), NULL, NULL, G_CALLBACK (on_message_settings)},
227 /* static gboolean */
228 /* on_key_pressed (GtkWidget *self, */
229 /* GdkEventKey *event, */
230 /* gpointer user_data); */
232 /* list my signals */
239 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
240 struct _ModestMsgEditWindowPrivate {
242 GtkWidget *header_box;
244 ModestPairList *from_field_protos;
245 GtkWidget *from_field;
246 gchar *last_from_account;
247 gchar *original_account_name;
252 gchar *original_mailbox;
256 GtkWidget *bcc_field;
257 GtkWidget *subject_field;
258 GtkWidget *attachments_view;
259 GtkWidget *priority_icon;
260 GtkWidget *subject_box;
261 GtkWidget *add_attachment_button;
263 GtkWidget *cc_caption;
264 GtkWidget *bcc_caption;
265 gboolean update_caption_visibility;
266 GtkWidget *attachments_caption;
268 GtkTextBuffer *text_buffer;
270 GtkWidget *font_size_toolitem;
271 GtkWidget *font_face_toolitem;
272 GtkWidget *font_color_button;
273 GtkWidget *font_color_toolitem;
274 GSList *font_items_group;
275 GtkTreeModel *faces_model;
276 gint current_face_index;
277 GtkWidget *font_tool_button_label;
278 GtkTreeModel *sizes_model;
279 gint current_size_index;
280 GtkWidget *size_tool_button_label;
282 GtkWidget *find_toolbar;
285 GtkWidget *font_dialog;
288 guint correct_scroll_idle;
289 guint scroll_drag_timeout_id;
293 TnyList *attachments;
298 TnyHeaderFlags priority_flags;
300 gboolean can_undo, can_redo;
301 gulong clipboard_change_handler_id;
302 gulong default_clipboard_change_handler_id;
303 gulong account_removed_handler_id;
304 guint clipboard_owner_idle;
305 gchar *clipboard_text;
314 GtkWidget *cc_button;
315 GtkWidget *bcc_button;
318 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
319 MODEST_TYPE_MSG_EDIT_WINDOW, \
320 ModestMsgEditWindowPrivate))
322 static GtkWindowClass *parent_class = NULL;
324 /* uncomment the following if you have defined any signals */
325 /* static guint signals[LAST_SIGNAL] = {0}; */
328 modest_msg_edit_window_get_type (void)
330 static GType my_type = 0;
332 static const GTypeInfo my_info = {
333 sizeof(ModestMsgEditWindowClass),
334 NULL, /* base init */
335 NULL, /* base finalize */
336 (GClassInitFunc) modest_msg_edit_window_class_init,
337 NULL, /* class finalize */
338 NULL, /* class data */
339 sizeof(ModestMsgEditWindow),
341 (GInstanceInitFunc) modest_msg_edit_window_init,
344 my_type = g_type_register_static (MODEST_TYPE_HILDON2_WINDOW,
345 "ModestMsgEditWindow",
353 save_state (ModestWindow *self)
355 modest_widget_memory_save (modest_runtime_get_conf(),
356 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
361 restore_settings (ModestMsgEditWindow *self)
363 ModestConf *conf = NULL;
365 conf = modest_runtime_get_conf ();
367 /* Dim at start clipboard actions */
368 modest_widget_memory_restore (conf, G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
373 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
375 GObjectClass *gobject_class;
376 ModestWindowClass *modest_window_class;
377 gobject_class = (GObjectClass*) klass;
378 modest_window_class = (ModestWindowClass*) klass;
380 parent_class = g_type_class_peek_parent (klass);
381 gobject_class->finalize = modest_msg_edit_window_finalize;
383 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
384 modest_window_class->save_state_func = save_state;
385 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
387 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
391 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
393 ModestMsgEditWindowPrivate *priv;
394 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
396 priv->msg_body = NULL;
397 priv->from_field = NULL;
398 priv->to_field = NULL;
399 priv->cc_field = NULL;
400 priv->bcc_field = NULL;
401 priv->subject_field = NULL;
402 priv->attachments = TNY_LIST (tny_simple_list_new ());
403 priv->images = TNY_LIST (tny_simple_list_new ());
404 priv->images_size = 0;
405 priv->images_count = 0;
408 priv->cc_caption = NULL;
409 priv->bcc_caption = NULL;
410 priv->update_caption_visibility = FALSE;
412 priv->priority_flags = 0;
414 priv->find_toolbar = NULL;
415 priv->last_search = NULL;
417 priv->draft_msg = NULL;
418 priv->outbox_msg = NULL;
419 priv->msg_uid = NULL;
421 priv->can_undo = FALSE;
422 priv->can_redo = FALSE;
423 priv->clipboard_change_handler_id = 0;
424 priv->default_clipboard_change_handler_id = 0;
425 priv->account_removed_handler_id = 0;
426 priv->clipboard_owner_idle = 0;
427 priv->clipboard_text = NULL;
430 priv->scroll_drag_timeout_id = 0;
431 priv->correct_scroll_idle = 0;
432 priv->last_upper = 0.0;
434 priv->font_dialog = NULL;
435 priv->app_menu = NULL;
437 priv->references = NULL;
438 priv->in_reply_to = NULL;
440 if (!is_wp_text_buffer_started) {
441 is_wp_text_buffer_started = TRUE;
442 wp_text_buffer_library_init ();
447 hildon_program_add_window (hildon_program_get_instance(),
452 multimailbox_get_default_mailbox (const gchar *account_name)
454 gchar *transport_account;
455 gchar *result = NULL;
457 transport_account = modest_account_mgr_get_server_account_name (modest_runtime_get_account_mgr (),
459 TNY_ACCOUNT_TYPE_TRANSPORT);
460 if (transport_account) {
462 ModestProtocolRegistry *registry;
464 registry = modest_runtime_get_protocol_registry ();
466 proto = modest_account_mgr_get_string (modest_runtime_get_account_mgr (), transport_account,
467 MODEST_ACCOUNT_PROTO, TRUE);
469 ModestProtocol *protocol =
470 modest_protocol_registry_get_protocol_by_name (registry,
471 MODEST_PROTOCOL_REGISTRY_TRANSPORT_PROTOCOLS,
473 if (MODEST_ACCOUNT_PROTOCOL (protocol)) {
474 ModestPairList *pair_list;
476 pair_list = modest_account_protocol_get_from_list (MODEST_ACCOUNT_PROTOCOL (protocol),
479 ModestPair *pair = (ModestPair *) pair_list->data;
480 result = g_strdup ((const gchar *) pair->first);
481 modest_pair_list_free (pair_list);
492 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
494 static ModestPairList*
495 get_transports (void)
497 GSList *transports = NULL;
499 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
500 GSList *accounts = modest_account_mgr_account_names (account_mgr,
501 TRUE /* only enabled accounts. */);
503 GSList *cursor = accounts;
505 gchar *account_name = cursor->data;
508 gchar *transport_account;
509 gboolean multi_mailbox = FALSE;
510 ModestProtocol *protocol = NULL;
512 if (modest_account_mgr_account_is_multimailbox (account_mgr, account_name, &protocol)) {
514 transport_account = modest_account_mgr_get_server_account_name
515 (modest_runtime_get_account_mgr (),
517 TNY_ACCOUNT_TYPE_TRANSPORT);
518 if (protocol && MODEST_IS_ACCOUNT_PROTOCOL (protocol)) {
519 ModestPairList *pair_list;
520 pair_list = modest_account_protocol_get_from_list (MODEST_ACCOUNT_PROTOCOL (protocol),
523 transports = g_slist_concat (transports, pair_list);
524 multi_mailbox = TRUE;
529 if (!multi_mailbox) {
530 gchar *from_string = NULL;
532 from_string = modest_account_mgr_get_from_string (account_mgr,
534 if (from_string && account_name) {
535 gchar *name = account_name;
536 ModestPair *pair = modest_pair_new ((gpointer) name,
537 (gpointer) from_string , TRUE);
538 transports = g_slist_prepend (transports, pair);
543 cursor = cursor->next;
545 g_slist_free (accounts); /* only free the accounts, not the elements,
546 * because they are used in the pairlist */
550 static void window_focus (GtkWindow *window,
554 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
558 scroll_drag_timeout (gpointer userdata)
560 ModestMsgEditWindow *win = (ModestMsgEditWindow *) userdata;
561 ModestMsgEditWindowPrivate *priv;
563 /* It could happen that the window was already closed */
564 if (!GTK_WIDGET_VISIBLE (win))
567 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(win);
569 correct_scroll_without_drag_check (win, TRUE);
571 priv->scroll_drag_timeout_id = 0;
577 correct_scroll_without_drag_check_idle (gpointer userdata)
579 ModestMsgEditWindow *w = (ModestMsgEditWindow *) userdata;
580 ModestMsgEditWindowPrivate *priv;
582 GdkRectangle rectangle;
583 gint offset_min, offset_max;
587 /* It could happen that the window was already closed */
588 if (!GTK_WIDGET_VISIBLE (w))
591 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
593 insert = gtk_text_buffer_get_insert (priv->text_buffer);
594 gtk_text_buffer_get_iter_at_mark (priv->text_buffer, &iter, insert);
596 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &iter, &rectangle);
597 offset_min = priv->msg_body->allocation.y + rectangle.y;
598 offset_max = offset_min + rectangle.height;
600 vadj = hildon_pannable_area_get_vadjustment (HILDON_PANNABLE_AREA (priv->pannable));
601 offset_min = MAX (offset_min - 48, 0);
602 offset_max = MIN (offset_max + 48, vadj->upper);
604 gtk_adjustment_clamp_page (vadj, (gdouble) offset_min, (gdouble) offset_max);
606 priv->correct_scroll_idle = 0;
611 correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused)
613 ModestMsgEditWindowPrivate *priv;
615 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
617 if (only_if_focused && !gtk_widget_is_focus (priv->msg_body))
620 if (priv->correct_scroll_idle > 0) {
624 priv->correct_scroll_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
625 (GSourceFunc) correct_scroll_without_drag_check_idle,
631 correct_scroll (ModestMsgEditWindow *w)
633 ModestMsgEditWindowPrivate *priv;
635 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
636 if (gtk_grab_get_current () == priv->msg_body) {
637 if (priv->scroll_drag_timeout_id == 0) {
638 priv->scroll_drag_timeout_id = g_timeout_add_full (G_PRIORITY_DEFAULT,
640 (GSourceFunc) scroll_drag_timeout,
647 correct_scroll_without_drag_check (w, TRUE);
651 text_buffer_end_user_action (GtkTextBuffer *buffer,
652 ModestMsgEditWindow *userdata)
655 correct_scroll (userdata);
659 text_buffer_mark_set (GtkTextBuffer *buffer,
662 ModestMsgEditWindow *userdata)
664 gtk_text_buffer_begin_user_action (buffer);
665 gtk_text_buffer_end_user_action (buffer);
669 cut_clipboard_check (GtkTextView *text_view,
672 GtkTextBuffer *buffer;
674 buffer = gtk_text_view_get_buffer (text_view);
675 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
676 g_signal_stop_emission_by_name ((gpointer )text_view, "cut-clipboard");
681 copy_clipboard_check (GtkTextView *text_view,
684 GtkTextBuffer *buffer;
686 buffer = gtk_text_view_get_buffer (text_view);
687 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
688 g_signal_stop_emission_by_name ((gpointer )text_view, "copy-clipboard");
693 attachment_deleted (ModestAttachmentsView *attachments_view,
696 modest_msg_edit_window_remove_attachments (MODEST_MSG_EDIT_WINDOW (user_data),
701 connect_signals (ModestMsgEditWindow *obj)
703 ModestMsgEditWindowPrivate *priv;
705 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
707 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
708 G_CALLBACK (text_buffer_refresh_attributes), obj);
709 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
710 G_CALLBACK (text_buffer_can_undo), obj);
711 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
712 G_CALLBACK (text_buffer_can_redo), obj);
713 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
714 G_CALLBACK (body_changed), obj);
715 g_signal_connect (G_OBJECT (priv->text_buffer), "modified-changed",
716 G_CALLBACK (body_changed), obj);
717 g_signal_connect (G_OBJECT (priv->text_buffer), "end-user-action",
718 G_CALLBACK (text_buffer_end_user_action), obj);
719 g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
720 G_CALLBACK (text_buffer_mark_set), obj);
721 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
722 G_CALLBACK (text_buffer_apply_tag), obj);
723 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
724 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
725 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
726 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
727 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
728 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
730 g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
731 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
732 g_signal_connect (G_OBJECT (priv->from_field), "value-changed",
733 G_CALLBACK (from_field_changed), obj);
735 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
736 G_CALLBACK (msg_body_focus), obj);
737 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
738 G_CALLBACK (msg_body_focus), obj);
739 g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
740 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
741 "changed", G_CALLBACK (recpt_field_changed), obj);
742 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
743 "changed", G_CALLBACK (recpt_field_changed), obj);
744 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
745 "changed", G_CALLBACK (recpt_field_changed), obj);
746 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
747 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
748 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
750 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
751 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
753 priv->clipboard_change_handler_id =
754 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
755 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
756 priv->default_clipboard_change_handler_id =
757 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
758 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
760 g_signal_connect (G_OBJECT (priv->msg_body), "cut-clipboard", G_CALLBACK (cut_clipboard_check), NULL);
761 g_signal_connect (G_OBJECT (priv->msg_body), "copy-clipboard", G_CALLBACK (copy_clipboard_check), NULL);
762 g_signal_connect (G_OBJECT (priv->attachments_view), "delete", G_CALLBACK (attachment_deleted), obj);
766 init_wp_text_view_style ()
768 static gboolean initialized = FALSE;
771 gtk_rc_parse_string ("class \"WPTextView\" style \"fremantle-textview\"");
777 init_window (ModestMsgEditWindow *obj)
779 GtkWidget *to_caption, *subject_caption;
780 GtkWidget *main_vbox;
781 GtkWidget *add_attachment_align;
782 ModestMsgEditWindowPrivate *priv;
783 GtkActionGroup *action_group;
784 ModestWindowPrivate *parent_priv;
785 GdkPixbuf *window_icon = NULL;
786 GError *error = NULL;
788 GtkSizeGroup *title_size_group;
789 GtkSizeGroup *value_size_group;
790 GtkWidget *attachment_icon;
791 GtkWidget *window_box;
792 GtkWidget *window_align;
793 #if (GTK_MINOR_VERSION >= 10)
794 GdkAtom deserialize_type;
797 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
798 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
800 parent_priv->ui_manager = gtk_ui_manager_new();
801 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
802 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
804 /* Add common actions */
805 gtk_action_group_add_actions (action_group,
806 modest_msg_edit_action_entries,
807 G_N_ELEMENTS (modest_msg_edit_action_entries),
809 gtk_action_group_add_actions (action_group,
810 hildon2_msg_edit_action_entries,
811 G_N_ELEMENTS (hildon2_msg_edit_action_entries),
813 gtk_action_group_add_toggle_actions (action_group,
814 modest_msg_edit_toggle_action_entries,
815 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
817 gtk_action_group_add_radio_actions (action_group,
818 modest_msg_edit_alignment_radio_action_entries,
819 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
821 G_CALLBACK (modest_ui_actions_on_change_justify),
823 gtk_action_group_add_radio_actions (action_group,
824 modest_msg_edit_priority_action_entries,
825 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
827 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
829 gtk_action_group_add_radio_actions (action_group,
830 modest_msg_edit_file_format_action_entries,
831 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
832 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
833 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
835 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
836 g_object_unref (action_group);
838 /* Load the UI definition */
839 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
842 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
843 g_clear_error (&error);
846 /* Add accelerators */
847 gtk_window_add_accel_group (GTK_WINDOW (obj),
848 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
850 parent_priv->menubar = NULL;
852 title_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
853 value_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
855 /* Note: This ModestPairList* must exist for as long as the picker
856 * that uses it, because the ModestSelectorPicker uses the ID opaquely,
857 * so it can't know how to manage its memory. */
858 priv->from_field = modest_selector_picker_new (MODEST_EDITABLE_SIZE,
859 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL,
861 modest_maemo_utils_set_hbutton_layout (title_size_group, value_size_group,
862 _("mail_va_from"), priv->from_field);
864 priv->to_field = modest_recpt_editor_new ();
865 priv->cc_field = modest_recpt_editor_new ();
866 priv->bcc_field = modest_recpt_editor_new ();
867 priv->subject_box = gtk_hbox_new (FALSE, MODEST_MARGIN_NONE);
868 priv->priority_icon = gtk_image_new ();
869 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->priority_icon, FALSE, FALSE, 0);
870 priv->subject_field = hildon_entry_new (MODEST_EDITABLE_SIZE);
871 gtk_entry_set_max_length (GTK_ENTRY (priv->subject_field) ,SUBJECT_MAX_LENGTH);
872 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
873 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
874 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
875 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->subject_field, TRUE, TRUE, 0);
876 priv->add_attachment_button = hildon_button_new (MODEST_EDITABLE_SIZE, HILDON_BUTTON_ARRANGEMENT_VERTICAL);
877 gtk_widget_set_size_request (priv->add_attachment_button, ATTACHMENT_BUTTON_WIDTH, -1);
878 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
879 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
880 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, HILDON_ICON_SIZE_FINGER);
881 hildon_button_set_image (HILDON_BUTTON (priv->add_attachment_button), attachment_icon);
882 add_attachment_align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
883 gtk_alignment_set_padding (GTK_ALIGNMENT (add_attachment_align), 0, 0, MODEST_MARGIN_DEFAULT, 0);
884 gtk_container_add (GTK_CONTAINER (add_attachment_align), priv->add_attachment_button);
885 gtk_box_pack_start (GTK_BOX (priv->subject_box), add_attachment_align, FALSE, FALSE, 0);
886 priv->attachments_view = modest_attachments_view_new (NULL);
887 modest_attachments_view_set_style (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
888 MODEST_ATTACHMENTS_VIEW_STYLE_NO_FOCUS);
890 priv->header_box = gtk_vbox_new (FALSE, 0);
892 to_caption = modest_maemo_utils_create_captioned_with_size_type
893 (title_size_group, value_size_group,
894 _("mail_va_to"), FALSE, priv->to_field,
895 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
896 priv->cc_caption = modest_maemo_utils_create_captioned_with_size_type
897 (title_size_group, value_size_group,
898 _("mail_va_cc"), FALSE, priv->cc_field,
899 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
900 priv->bcc_caption = modest_maemo_utils_create_captioned_with_size_type
901 (title_size_group, value_size_group,
902 _("mail_va_hotfix1"), FALSE, priv->bcc_field,
903 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
904 subject_caption = modest_maemo_utils_create_captioned (title_size_group, value_size_group,
905 _("mail_va_subject"), FALSE, priv->subject_box);
906 priv->attachments_caption = modest_maemo_utils_create_captioned_with_size_type (title_size_group, value_size_group,
907 _("mail_va_attachment"),
909 priv->attachments_view,
910 HILDON_SIZE_AUTO_WIDTH |
911 HILDON_SIZE_AUTO_HEIGHT);
912 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), value_size_group); */
913 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), value_size_group); */
914 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), value_size_group); */
915 g_object_unref (title_size_group);
916 g_object_unref (value_size_group);
918 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->from_field, FALSE, FALSE, 0);
919 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
920 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
921 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
922 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
923 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
924 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
926 init_wp_text_view_style ();
928 priv->msg_body = modest_wp_text_view_new ();
931 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
932 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
933 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
934 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
935 #if (GTK_MINOR_VERSION >= 10)
936 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
937 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
939 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
940 deserialize_type, TRUE);
942 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
944 priv->find_toolbar = hildon_find_toolbar_new (NULL);
945 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
947 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
949 priv->pannable = hildon_pannable_area_new ();
951 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
952 window_align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
953 gtk_alignment_set_padding (GTK_ALIGNMENT (window_align), 0, 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DEFAULT);
955 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
956 gtk_box_pack_start (GTK_BOX(main_vbox), priv->msg_body, TRUE, TRUE, 0);
957 gtk_container_add (GTK_CONTAINER (window_align), main_vbox);
959 hildon_pannable_area_add_with_viewport (HILDON_PANNABLE_AREA (priv->pannable), window_align);
960 gtk_widget_show_all (GTK_WIDGET(priv->pannable));
962 window_box = gtk_vbox_new (FALSE, 0);
963 gtk_container_add (GTK_CONTAINER(obj), window_box);
965 gtk_box_pack_start (GTK_BOX (window_box), priv->pannable, TRUE, TRUE, 0);
967 /* Set window icon */
968 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
970 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
971 g_object_unref (window_icon);
976 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
978 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
980 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
981 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
982 priv->clipboard_change_handler_id))
983 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
984 priv->clipboard_change_handler_id);
985 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
986 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
987 priv->default_clipboard_change_handler_id))
988 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
989 priv->default_clipboard_change_handler_id);
991 if (priv->account_removed_handler_id &&
992 g_signal_handler_is_connected (modest_runtime_get_account_store (),
993 priv->account_removed_handler_id))
994 g_signal_handler_disconnect(modest_runtime_get_account_store (),
995 priv->account_removed_handler_id);
999 modest_msg_edit_window_finalize (GObject *obj)
1001 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1003 /* Sanity check: shouldn't be needed, the window mgr should
1004 call this function before */
1005 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
1007 if (priv->font_dialog != NULL) {
1008 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
1011 if (priv->clipboard_text != NULL) {
1012 g_free (priv->clipboard_text);
1013 priv->clipboard_text = NULL;
1016 if (priv->draft_msg != NULL) {
1017 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
1018 if (TNY_IS_HEADER (header)) {
1019 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1020 modest_window_mgr_unregister_header (mgr, header);
1022 g_object_unref (priv->draft_msg);
1023 priv->draft_msg = NULL;
1025 if (priv->outbox_msg != NULL) {
1026 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
1027 if (TNY_IS_HEADER (header)) {
1028 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1029 modest_window_mgr_unregister_header (mgr, header);
1031 g_object_unref (priv->outbox_msg);
1032 priv->outbox_msg = NULL;
1034 if (priv->correct_scroll_idle > 0) {
1035 g_source_remove (priv->correct_scroll_idle);
1036 priv->correct_scroll_idle = 0;
1038 if (priv->scroll_drag_timeout_id > 0) {
1039 g_source_remove (priv->scroll_drag_timeout_id);
1040 priv->scroll_drag_timeout_id = 0;
1042 if (priv->clipboard_owner_idle > 0) {
1043 g_source_remove (priv->clipboard_owner_idle);
1044 priv->clipboard_owner_idle = 0;
1046 if (priv->original_account_name)
1047 g_free (priv->original_account_name);
1048 if (priv->original_mailbox)
1049 g_free (priv->original_mailbox);
1050 g_free (priv->msg_uid);
1051 g_free (priv->last_search);
1052 g_free (priv->references);
1053 g_free (priv->in_reply_to);
1054 g_object_unref (priv->faces_model);
1055 g_object_unref (priv->sizes_model);
1056 g_object_unref (priv->attachments);
1057 g_object_unref (priv->images);
1059 /* This had to stay alive for as long as the picker that used it: */
1060 modest_pair_list_free (priv->from_field_protos);
1062 G_OBJECT_CLASS(parent_class)->finalize (obj);
1066 pixbuf_size_prepared (GdkPixbufLoader *loader,
1069 ModestMsgEditWindow *self)
1071 gint new_height, new_width;
1074 new_height = height;
1078 if (width > IMAGE_MAX_WIDTH) {
1079 new_height = height * IMAGE_MAX_WIDTH / width;
1080 new_width = IMAGE_MAX_WIDTH;
1083 gdk_pixbuf_loader_set_size (loader, new_width, new_height);
1087 pixbuf_from_stream (TnyStream *stream,
1088 const gchar *mime_type,
1089 guint64 *stream_size,
1090 ModestMsgEditWindow *self)
1092 GdkPixbufLoader *loader;
1095 GError *error = NULL;
1099 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
1101 if (loader == NULL) {
1106 g_signal_connect (G_OBJECT (loader), "size-prepared", G_CALLBACK (pixbuf_size_prepared), self);
1108 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (self), TRUE);
1110 tny_stream_reset (TNY_STREAM (stream));
1111 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
1112 unsigned char read_buffer[128];
1114 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
1116 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
1119 /* Allow some UI responsiveness */
1120 while (gtk_events_pending ())
1121 gtk_main_iteration ();
1123 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (self), FALSE);
1125 gdk_pixbuf_loader_close (loader, &error);
1128 g_error_free (error);
1129 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1131 g_object_ref (pixbuf);
1132 g_object_unref (loader);
1137 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1138 GdkPixbuf *new_pixbuf;
1140 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1141 gdk_pixbuf_get_width (pixbuf);
1142 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1143 g_object_unref (pixbuf);
1144 pixbuf = new_pixbuf;
1148 *stream_size = size;
1154 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1156 ModestMsgEditWindowPrivate *priv;
1159 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1161 g_object_ref (self);
1162 for (iter = tny_list_create_iterator (attachments);
1163 !tny_iterator_is_done (iter);
1164 tny_iterator_next (iter)) {
1165 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1166 const gchar *cid = tny_mime_part_get_content_id (part);
1167 const gchar *mime_type = tny_mime_part_get_content_type (part);
1168 if ((cid != NULL)&&(mime_type != NULL)) {
1169 guint64 stream_size;
1170 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1171 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, self);
1174 g_object_unref (stream);
1176 if (pixbuf != NULL) {
1177 priv->images_count ++;
1178 priv->images_size += stream_size;
1179 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1180 g_object_unref (pixbuf);
1183 g_object_unref (part);
1185 g_object_unref (iter);
1186 g_object_unref (self);
1190 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1192 TnyMimePart *parent = NULL;
1193 const gchar *content_type = NULL;
1194 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1196 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1198 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1199 parent = g_object_ref (msg);
1200 } else if (content_type && !g_strcasecmp (content_type, "multipart/mixed")) {
1201 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1204 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1205 iter = tny_list_create_iterator (parts);
1206 while (!tny_iterator_is_done (iter)) {
1208 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1209 content_type = tny_mime_part_get_content_type (part);
1210 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1214 g_object_unref (part);
1216 tny_iterator_next (iter);
1218 g_object_unref (iter);
1219 g_object_unref (parts);
1222 if (parent != NULL) {
1223 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1226 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1227 iter = tny_list_create_iterator (parts);
1228 while (!tny_iterator_is_done (iter)) {
1230 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1231 content_type = tny_mime_part_get_content_type (part);
1232 if (content_type && g_str_has_prefix (content_type, "image/")) {
1233 tny_list_prepend (priv->images, (GObject *) part);
1235 g_object_unref (part);
1236 tny_iterator_next (iter);
1238 g_object_unref (iter);
1239 g_object_unref (parts);
1240 g_object_unref (parent);
1245 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1248 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1250 for (iter = tny_list_create_iterator (attachments) ;
1251 !tny_iterator_is_done (iter);
1252 tny_iterator_next (iter)) {
1253 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1254 const gchar *cid = tny_mime_part_get_content_id (part);
1256 char *invalid = NULL;
1257 gint int_cid = strtol (cid, &invalid, 10);
1258 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1259 priv->next_cid = int_cid + 1;
1262 g_object_unref (part);
1264 g_object_unref (iter);
1268 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1271 gchar *to, *cc, *bcc, *subject;
1273 ModestMsgEditWindowPrivate *priv;
1274 ModestWindowPrivate *parent_priv;
1276 TnyHeaderFlags priority_flags;
1277 TnyFolder *msg_folder;
1278 gboolean is_html = FALSE;
1279 gboolean field_view_set;
1281 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1282 g_return_if_fail (TNY_IS_MSG (msg));
1284 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1285 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1287 header = tny_msg_get_header (msg);
1288 to = tny_header_dup_to (header);
1289 cc = tny_header_dup_cc (header);
1290 bcc = tny_header_dup_bcc (header);
1291 subject = tny_header_dup_subject (header);
1293 modest_tny_msg_get_references (TNY_MSG (msg), NULL, &(priv->references), &(priv->in_reply_to));
1294 priority_flags = tny_header_get_priority (header);
1297 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
1299 field_view_set = TRUE;
1301 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
1302 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1303 gtk_widget_show (priv->cc_caption);
1304 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1305 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1306 gtk_widget_hide (priv->cc_caption);
1307 field_view_set = FALSE;
1309 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button), field_view_set);
1311 field_view_set = TRUE;
1313 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
1314 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1315 gtk_widget_show (priv->bcc_caption);
1316 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1317 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1318 gtk_widget_hide (priv->bcc_caption);
1319 field_view_set = FALSE;
1321 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button), field_view_set);
1325 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1326 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1329 update_window_title (self);
1331 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1332 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1334 if ((body == NULL)||(body[0] == '\0')) {
1336 body = modest_text_utils_convert_to_html ("");
1339 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1340 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1343 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1346 /* Add attachments to the view */
1347 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1348 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1349 if (tny_list_get_length (priv->attachments) == 0) {
1350 gtk_widget_hide (priv->attachments_caption);
1352 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1353 gtk_widget_show_all (priv->attachments_caption);
1355 get_related_images (self, msg);
1356 update_next_cid (self, priv->attachments);
1357 update_next_cid (self, priv->images);
1358 replace_with_images (self, priv->images);
1360 if (preserve_is_rich && !is_html) {
1361 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1362 /* Get the default format required from configuration */
1363 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1364 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1367 /* Set the default focus depending on having already a To: field or not */
1368 if ((!to)||(*to == '\0')) {
1369 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1371 gtk_widget_grab_focus (priv->msg_body);
1374 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1376 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1377 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1379 modest_msg_edit_window_set_modified (self, FALSE);
1381 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1382 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1383 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1384 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1386 if (priv->msg_uid) {
1387 g_free (priv->msg_uid);
1388 priv->msg_uid = NULL;
1391 /* we should set a reference to the incoming message if it is a draft */
1392 msg_folder = tny_msg_get_folder (msg);
1394 if (modest_tny_folder_is_local_folder (msg_folder)) {
1395 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1396 if (type == TNY_FOLDER_TYPE_INVALID)
1397 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1399 if (type == TNY_FOLDER_TYPE_DRAFTS)
1400 priv->draft_msg = g_object_ref(msg);
1401 if (type == TNY_FOLDER_TYPE_OUTBOX)
1402 priv->outbox_msg = g_object_ref(msg);
1403 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1405 g_object_unref (msg_folder);
1416 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1418 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1419 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1420 GtkWidget *placeholder;
1421 GtkWidget *tool_item;
1426 GtkWidget *sizes_menu;
1427 GtkWidget *fonts_menu;
1433 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1434 gtk_toolbar_set_show_arrow (GTK_TOOLBAR (parent_priv->toolbar), FALSE);
1435 gtk_toolbar_set_icon_size (GTK_TOOLBAR (parent_priv->toolbar), HILDON_ICON_SIZE_FINGER);
1436 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1438 /* Font color placeholder */
1439 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1440 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1443 priv->font_color_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1444 priv->font_color_button = hildon_color_button_new ();
1445 gtk_widget_set_size_request (priv->font_color_button, -1, 48);
1446 GTK_WIDGET_UNSET_FLAGS (priv->font_color_toolitem, GTK_CAN_FOCUS);
1447 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1448 gtk_container_add (GTK_CONTAINER (priv->font_color_toolitem), priv->font_color_button);
1449 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1450 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1451 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->font_color_toolitem), insert_index);
1452 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1454 G_CALLBACK (modest_msg_edit_window_color_button_change),
1457 /* Font size and face placeholder */
1458 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1459 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1461 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1462 priv->size_tool_button_label = gtk_label_new (NULL);
1463 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1464 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1465 size_text, "</span>", NULL);
1466 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1467 gtk_misc_set_alignment (GTK_MISC (priv->size_tool_button_label), 1.0, 0.5);
1469 hildon_helper_set_logical_font (priv->size_tool_button_label, "LargeSystemFont");
1470 hbox = gtk_hbox_new (MODEST_MARGIN_DEFAULT, FALSE);
1471 gtk_box_pack_start (GTK_BOX (hbox), priv->size_tool_button_label, TRUE, TRUE, 0);
1472 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1473 gtk_misc_set_alignment (GTK_MISC (arrow), 0.0, 0.5);
1474 gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
1475 gtk_widget_set_sensitive (arrow, FALSE);
1476 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), hbox);
1477 sizes_menu = gtk_menu_new ();
1478 priv->sizes_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1479 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1482 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1483 gtk_list_store_append (GTK_LIST_STORE (priv->sizes_model), &iter);
1485 gtk_list_store_set (GTK_LIST_STORE (priv->sizes_model), &iter,
1489 if (wp_font_size[size_index] == 12)
1490 priv->current_size_index = size_index;
1494 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_size_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_size_toolitem = tool_item;
1501 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1502 priv->font_tool_button_label = gtk_label_new (NULL);
1503 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1504 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1505 gtk_misc_set_alignment (GTK_MISC (priv->font_tool_button_label), 1.0, 0.5);
1507 hildon_helper_set_logical_font (priv->font_tool_button_label, "LargeSystemFont");
1508 hbox = gtk_hbox_new (MODEST_MARGIN_DEFAULT, FALSE);
1509 gtk_box_pack_start (GTK_BOX (hbox), priv->font_tool_button_label, TRUE, TRUE, 0);
1510 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1511 gtk_misc_set_alignment (GTK_MISC (arrow), 0.0, 0.5);
1512 gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
1513 gtk_widget_set_sensitive (arrow, FALSE);
1514 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), hbox);
1515 fonts_menu = gtk_menu_new ();
1516 priv->faces_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1517 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1520 gtk_list_store_append (GTK_LIST_STORE (priv->faces_model), &iter);
1522 gtk_list_store_set (GTK_LIST_STORE (priv->faces_model), &iter,
1523 0, wp_get_font_name (font_index),
1526 if (font_index == DEFAULT_FONT)
1527 priv->current_face_index = font_index;
1529 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_face_clicked), window);
1530 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1531 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1532 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1533 priv->font_face_toolitem = tool_item;
1535 /* Set expand and homogeneous for remaining items */
1536 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
1537 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1538 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1539 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1540 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1541 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1542 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1543 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1544 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1546 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1547 will not show the tool items added to the placeholders) */
1548 gtk_widget_show_all (parent_priv->toolbar);
1550 /* Set the no show all *after* showing all items. We do not
1551 want the toolbar to be shown with a show all because it
1552 could go agains the gconf setting regarding showing or not
1553 the toolbar of the editor window */
1554 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1560 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, const gchar *mailbox, gboolean preserve_is_rich)
1563 ModestWindowPrivate *parent_priv;
1564 ModestMsgEditWindowPrivate *priv;
1565 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1566 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1567 ModestWindowMgr *mgr = NULL;
1569 g_return_val_if_fail (msg, NULL);
1570 g_return_val_if_fail (account_name, NULL);
1572 mgr = modest_runtime_get_window_mgr ();
1574 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1576 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1577 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1579 /* Menubar. Update the state of some toggles */
1580 priv->from_field_protos = get_transports ();
1581 priv->original_mailbox = NULL;
1582 modest_selector_picker_set_pair_list (MODEST_SELECTOR_PICKER (priv->from_field), priv->from_field_protos);
1583 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1584 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1585 if (mailbox && modest_pair_list_find_by_first_as_string (priv->from_field_protos, mailbox)) {
1586 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) mailbox);
1587 priv->original_mailbox = g_strdup (mailbox);
1588 } else if (modest_account_mgr_account_is_multimailbox (modest_runtime_get_account_mgr (), account_name, NULL)) {
1589 /* We set the first mailbox as the active mailbox */
1590 priv->original_mailbox = multimailbox_get_default_mailbox (account_name);
1591 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field),
1592 (gpointer) priv->original_mailbox);
1594 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1596 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1597 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1599 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1600 hildon_touch_selector_get_current_text
1601 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1602 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1603 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1606 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1608 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1610 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1611 modest_window_set_active_mailbox (MODEST_WINDOW(obj), priv->original_mailbox);
1613 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1615 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1616 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1617 /* Add common dimming rules */
1618 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1619 modest_msg_edit_window_toolbar_dimming_entries,
1620 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1621 MODEST_WINDOW (obj));
1622 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_toolitem,
1623 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1624 MODEST_WINDOW (obj));
1625 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1626 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1627 MODEST_WINDOW (obj));
1628 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1629 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1630 MODEST_WINDOW (obj));
1631 /* Insert dimming rules group for this window */
1632 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1633 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1635 /* Setup app menu */
1636 setup_menu (MODEST_MSG_EDIT_WINDOW (obj));
1638 /* Checks the dimming rules */
1639 g_object_unref (toolbar_rules_group);
1640 g_object_unref (clipboard_rules_group);
1641 gtk_widget_hide (priv->priority_icon);
1642 gtk_widget_queue_resize (priv->subject_box);
1643 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1645 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1647 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1648 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1649 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1650 priv->update_caption_visibility = TRUE;
1652 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1654 /* Track account-removed signal, this window should be closed
1655 in the case we're creating a mail associated to the account
1657 priv->account_removed_handler_id =
1658 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1660 G_CALLBACK(on_account_removed),
1663 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1665 return (ModestWindow*) obj;
1669 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1671 GString **string_buffer = (GString **) user_data;
1673 *string_buffer = g_string_append (*string_buffer, buffer);
1679 * @result: A new string which should be freed with g_free().
1682 get_formatted_data (ModestMsgEditWindow *edit_window)
1684 ModestMsgEditWindowPrivate *priv;
1685 GString *string_buffer = g_string_new ("");
1687 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1689 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1691 modest_text_utils_hyperlinkify (string_buffer);
1693 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1695 return g_string_free (string_buffer, FALSE);
1700 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1703 const gchar *account_name;
1704 ModestMsgEditWindowPrivate *priv;
1705 TnyIterator *att_iter;
1706 const gchar *picker_active_id;
1708 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1710 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1712 picker_active_id = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1713 g_return_val_if_fail (picker_active_id, NULL);
1714 account_name = modest_utils_get_account_name_from_recipient (picker_active_id, NULL);
1716 /* don't free these (except from) */
1717 data = g_slice_new0 (MsgData);
1718 data->from = g_strdup ((gchar *) modest_selector_picker_get_active_display_name (MODEST_SELECTOR_PICKER (priv->from_field)));
1719 data->account_name = g_strdup (account_name);
1720 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1721 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1722 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1723 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1724 data->references = g_strdup (priv->references);
1725 data->in_reply_to = g_strdup (priv->in_reply_to);
1726 if (priv->draft_msg) {
1727 data->draft_msg = g_object_ref (priv->draft_msg);
1728 } else if (priv->outbox_msg) {
1729 data->draft_msg = g_object_ref (priv->outbox_msg);
1731 data->draft_msg = NULL;
1734 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1736 gtk_text_buffer_get_bounds (buf, &b, &e);
1737 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1739 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1740 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1742 data->html_body = NULL;
1744 /* deep-copy the data */
1745 att_iter = tny_list_create_iterator (priv->attachments);
1746 data->attachments = NULL;
1747 while (!tny_iterator_is_done (att_iter)) {
1748 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1749 if (!(TNY_IS_MIME_PART(part))) {
1750 g_warning ("strange data in attachment list");
1751 g_object_unref (part);
1752 tny_iterator_next (att_iter);
1755 data->attachments = g_list_append (data->attachments,
1757 tny_iterator_next (att_iter);
1759 g_object_unref (att_iter);
1761 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1762 att_iter = tny_list_create_iterator (priv->images);
1763 data->images = NULL;
1764 while (!tny_iterator_is_done (att_iter)) {
1765 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1767 if (!(TNY_IS_MIME_PART(part))) {
1768 g_warning ("strange data in attachment list");
1769 g_object_unref (part);
1770 tny_iterator_next (att_iter);
1773 cid = tny_mime_part_get_content_id (part);
1775 gchar *image_tag_id;
1776 GtkTextTag *image_tag;
1778 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1779 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1780 g_free (image_tag_id);
1782 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1784 ((gtk_text_iter_has_tag (&iter, image_tag))||
1785 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1786 data->images = g_list_append (data->images,
1787 g_object_ref (part));
1789 g_object_unref (part);
1790 tny_iterator_next (att_iter);
1792 g_object_unref (att_iter);
1794 data->priority_flags = priv->priority_flags;
1801 unref_gobject (GObject *obj, gpointer data)
1803 if (!G_IS_OBJECT(obj))
1805 g_object_unref (obj);
1809 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1812 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1820 g_free (data->from);
1821 g_free (data->subject);
1822 g_free (data->plain_body);
1823 g_free (data->html_body);
1824 g_free (data->account_name);
1825 g_free (data->references);
1826 g_free (data->in_reply_to);
1828 if (data->draft_msg != NULL) {
1829 g_object_unref (data->draft_msg);
1830 data->draft_msg = NULL;
1833 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1834 g_list_free (data->attachments);
1835 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1836 g_list_free (data->images);
1838 g_slice_free (MsgData, data);
1842 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1844 guint64 *parts_size)
1846 ModestMsgEditWindowPrivate *priv;
1848 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1850 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1852 /* TODO: add images */
1853 *parts_size += priv->images_size;
1854 *parts_count += priv->images_count;
1859 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1862 ModestMsgEditWindowPrivate *priv = NULL;
1863 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1865 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1867 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1869 return MODEST_MSG_EDIT_FORMAT_HTML;
1871 return MODEST_MSG_EDIT_FORMAT_TEXT;
1875 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1876 ModestMsgEditFormat format)
1878 ModestMsgEditWindowPrivate *priv;
1880 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1881 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1884 case MODEST_MSG_EDIT_FORMAT_HTML:
1885 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1887 case MODEST_MSG_EDIT_FORMAT_TEXT:
1888 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1891 g_return_if_reached ();
1895 ModestMsgEditFormatState *
1896 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1898 ModestMsgEditFormatState *format_state = NULL;
1899 ModestMsgEditWindowPrivate *priv;
1900 WPTextBufferFormat *buffer_format;
1902 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1904 buffer_format = g_new0 (WPTextBufferFormat, 1);
1905 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1907 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1909 format_state = g_new0 (ModestMsgEditFormatState, 1);
1910 format_state->bold = buffer_format->bold&0x1;
1911 format_state->italics = buffer_format->italic&0x1;
1912 format_state->bullet = buffer_format->bullet&0x1;
1913 format_state->color = buffer_format->color;
1914 format_state->font_size = buffer_format->font_size;
1915 format_state->font_family = wp_get_font_name (buffer_format->font);
1916 format_state->justification = buffer_format->justification;
1917 g_free (buffer_format);
1919 return format_state;
1924 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1925 const ModestMsgEditFormatState *format_state)
1927 ModestMsgEditWindowPrivate *priv;
1928 WPTextBufferFormat *buffer_format;
1929 WPTextBufferFormat *current_format;
1931 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1932 g_return_if_fail (format_state != NULL);
1934 buffer_format = g_new0 (WPTextBufferFormat, 1);
1935 current_format = g_new0 (WPTextBufferFormat, 1);
1937 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1938 gtk_widget_grab_focus (priv->msg_body);
1939 buffer_format->bold = (format_state->bold != FALSE);
1940 buffer_format->italic = (format_state->italics != FALSE);
1941 buffer_format->color = format_state->color;
1942 buffer_format->font_size = format_state->font_size;
1943 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1944 buffer_format->justification = format_state->justification;
1945 buffer_format->bullet = format_state->bullet;
1947 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1949 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1950 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1951 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1952 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1953 buffer_format->cs.font = (buffer_format->font != current_format->font);
1954 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1955 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1957 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1958 if (buffer_format->cs.bold) {
1959 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
1960 GINT_TO_POINTER (buffer_format->bold&0x1));
1962 if (buffer_format->cs.italic) {
1963 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
1964 GINT_TO_POINTER (buffer_format->italic&0x1));
1966 if (buffer_format->cs.color) {
1967 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1968 GINT_TO_POINTER (&(buffer_format->color)));
1970 if (buffer_format->cs.font_size) {
1971 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1972 GINT_TO_POINTER (buffer_format->font_size));
1974 if (buffer_format->cs.justification) {
1975 switch (buffer_format->justification) {
1976 case GTK_JUSTIFY_LEFT:
1977 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
1978 GINT_TO_POINTER(TRUE));
1980 case GTK_JUSTIFY_CENTER:
1981 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
1982 GINT_TO_POINTER(TRUE));
1984 case GTK_JUSTIFY_RIGHT:
1985 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
1986 GINT_TO_POINTER(TRUE));
1993 if (buffer_format->cs.font) {
1994 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1995 GINT_TO_POINTER (buffer_format->font));
1997 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1998 if (buffer_format->cs.bullet) {
1999 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
2000 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
2002 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
2004 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
2006 g_free (buffer_format);
2007 g_free (current_format);
2009 /* Check dimming rules */
2010 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
2011 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
2015 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
2017 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2019 ModestWindowPrivate *parent_priv;
2020 ModestMsgEditWindowPrivate *priv;
2022 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2023 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2025 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
2026 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu");
2027 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2028 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
2030 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatPlainTextMenu");
2031 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2032 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
2035 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2037 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2038 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
2040 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2041 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
2043 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
2044 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
2047 switch (buffer_format->justification)
2049 case GTK_JUSTIFY_LEFT:
2050 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2052 case GTK_JUSTIFY_CENTER:
2053 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2055 case GTK_JUSTIFY_RIGHT:
2056 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2063 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
2065 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
2066 G_CALLBACK (modest_msg_edit_window_color_button_change),
2068 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
2069 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
2070 G_CALLBACK (modest_msg_edit_window_color_button_change),
2073 if (priv->current_size_index != buffer_format->font_size) {
2077 path = gtk_tree_path_new_from_indices (buffer_format->font_size, -1);
2078 if (gtk_tree_model_get_iter (priv->sizes_model, &iter, path)) {
2082 priv->current_size_index = buffer_format->font_size;
2084 gtk_tree_model_get (priv->sizes_model, &iter, 0, &size_text, -1);
2085 markup = g_strconcat ("<span font_family='Sans'>",
2086 size_text, "</span>", NULL);
2088 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2092 gtk_tree_path_free (path);
2095 if (priv->current_face_index != buffer_format->font) {
2099 path = gtk_tree_path_new_from_indices (buffer_format->font, -1);
2100 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2104 priv->current_face_index = buffer_format->font;
2105 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2106 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2107 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2114 g_free (buffer_format);
2118 #ifdef MODEST_HILDON_VERSION_0
2120 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2123 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2124 ModestMsgEditWindowPrivate *priv;
2125 GtkWidget *dialog = NULL;
2127 GdkColor *new_color = NULL;
2129 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2130 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2132 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2133 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
2134 g_free (buffer_format);
2136 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2137 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2138 if (new_color != NULL) {
2139 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2140 (gpointer) new_color);
2143 gtk_widget_destroy (dialog);
2148 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2151 ModestMsgEditWindowPrivate *priv;
2152 GtkWidget *dialog = NULL;
2154 GdkColor *old_color = NULL;
2155 const GdkColor *new_color = NULL;
2157 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2158 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2160 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2161 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2163 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2164 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2165 if (new_color != NULL)
2166 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2168 gtk_widget_destroy (dialog);
2174 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2177 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2178 ModestMsgEditWindowPrivate *priv;
2179 GtkWidget *dialog = NULL;
2181 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2182 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2184 dialog = hildon_color_chooser_new ();
2185 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2186 g_free (buffer_format);
2188 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2190 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2191 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2194 gtk_widget_destroy (dialog);
2199 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2202 ModestMsgEditWindowPrivate *priv;
2203 GtkWidget *dialog = NULL;
2204 GdkColor *old_color = NULL;
2206 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2207 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2209 dialog = hildon_color_chooser_new ();
2210 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2212 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2214 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2215 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2217 gtk_widget_destroy (dialog);
2220 #endif /*!MODEST_HILDON_VERSION_0*/
2225 create_stream_for_uri (const gchar* uri)
2230 TnyStream *result = NULL;
2232 GnomeVFSHandle *handle = NULL;
2233 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2234 if (test == GNOME_VFS_OK) {
2235 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2236 /* Streams over OBEX (Bluetooth) are not seekable but
2237 * we expect them to be (we might need to read them
2238 * several times). So if this is a Bluetooth URI just
2239 * read the whole file into memory (this is not a fast
2240 * protocol so we can assume that these files are not
2241 * going to be very big) */
2242 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2243 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2244 TnyStream *memstream = tny_camel_mem_stream_new ();
2245 tny_stream_write_to_stream (vfssstream, memstream);
2246 g_object_unref (vfssstream);
2249 result = vfssstream;
2257 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2260 ModestMsgEditWindowPrivate *priv;
2261 GtkWidget *dialog = NULL;
2263 GSList *uris = NULL;
2264 GSList *uri_node = NULL;
2266 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2268 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2269 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2270 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2272 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2274 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2275 GTK_WINDOW (dialog), GTK_WINDOW (window));
2277 response = gtk_dialog_run (GTK_DIALOG (dialog));
2279 case GTK_RESPONSE_OK:
2281 gchar *current_folder;
2282 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2283 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2284 if (current_folder && current_folder != '\0') {
2286 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_INSERT_IMAGE_PATH,
2287 current_folder, &err);
2289 g_debug ("Error storing latest used folder: %s", err->message);
2293 g_free (current_folder);
2299 gtk_widget_destroy (dialog);
2301 g_object_ref (window);
2302 /* The operation could take some time so allow the dialog to be closed */
2303 while (gtk_events_pending ())
2304 gtk_main_iteration ();
2306 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2308 GnomeVFSHandle *handle = NULL;
2309 GnomeVFSResult result;
2310 GtkTextIter position;
2311 GtkTextMark *insert_mark;
2313 uri = (const gchar *) uri_node->data;
2314 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2315 if (result == GNOME_VFS_OK) {
2317 GnomeVFSFileInfo *info;
2318 gchar *filename, *basename, *escaped_filename;
2319 TnyMimePart *mime_part;
2321 const gchar *mime_type = NULL;
2322 GnomeVFSURI *vfs_uri;
2323 guint64 stream_size;
2325 gnome_vfs_close (handle);
2326 vfs_uri = gnome_vfs_uri_new (uri);
2328 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2329 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2330 g_free (escaped_filename);
2331 gnome_vfs_uri_unref (vfs_uri);
2332 info = gnome_vfs_file_info_new ();
2334 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2335 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2337 mime_type = gnome_vfs_file_info_get_mime_type (info);
2339 mime_part = tny_platform_factory_new_mime_part
2340 (modest_runtime_get_platform_factory ());
2342 TnyStream *stream = create_stream_for_uri (uri);
2344 if (stream == NULL) {
2346 modest_platform_information_banner (NULL, NULL,
2347 _FM("sfil_ib_opening_not_allowed"));
2349 g_object_unref (mime_part);
2350 gnome_vfs_file_info_unref (info);
2354 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2356 content_id = g_strdup_printf ("%d", priv->next_cid);
2357 tny_mime_part_set_content_id (mime_part, content_id);
2358 g_free (content_id);
2361 basename = g_path_get_basename (filename);
2362 tny_mime_part_set_filename (mime_part, basename);
2365 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, window);
2367 if (pixbuf != NULL) {
2368 priv->images_size += stream_size;
2369 priv->images_count ++;
2370 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2371 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2372 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position,
2373 tny_mime_part_get_content_id (mime_part), pixbuf);
2374 g_object_unref (pixbuf);
2376 tny_list_prepend (priv->images, (GObject *) mime_part);
2377 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2379 modest_platform_information_banner (NULL, NULL,
2380 _("mail_ib_file_operation_failed"));
2384 g_object_unref (mime_part);
2385 gnome_vfs_file_info_unref (info);
2389 g_object_unref (window);
2393 on_attach_file_response (GtkDialog *dialog,
2397 GSList *uris = NULL;
2399 GnomeVFSFileSize total_size, allowed_size;
2400 ModestMsgEditWindow *window;
2401 ModestMsgEditWindowPrivate *priv;
2406 case GTK_RESPONSE_OK:
2408 gchar *current_folder;
2410 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2411 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2412 if (current_folder && current_folder != '\0') {
2414 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_ATTACH_FILE_PATH,
2415 current_folder, &err);
2417 g_debug ("Error storing latest used folder: %s", err->message);
2421 g_free (current_folder);
2428 window = MODEST_MSG_EDIT_WINDOW (user_data);
2429 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2431 /* allowed size is the maximum size - what's already there */
2432 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2433 &att_num, &att_size);
2434 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2437 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2439 const gchar *uri = (const gchar *) uri_node->data;
2442 modest_msg_edit_window_attach_file_one (window, uri, allowed_size);
2444 if (total_size > allowed_size) {
2445 g_warning ("%s: total size: %u",
2446 __FUNCTION__, (unsigned int)total_size);
2449 allowed_size -= total_size;
2451 g_slist_foreach (uris, (GFunc) g_free, NULL);
2452 g_slist_free (uris);
2454 gtk_widget_destroy (GTK_WIDGET (dialog));
2458 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2460 GtkWidget *dialog = NULL;
2461 ModestMsgEditWindowPrivate *priv;
2464 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2466 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2468 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2471 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window),
2472 GTK_FILE_CHOOSER_ACTION_OPEN);
2473 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2474 conf_folder = modest_conf_get_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_ATTACH_FILE_PATH, NULL);
2475 if (conf_folder && conf_folder[0] != '\0') {
2476 gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (dialog), conf_folder);
2479 /* Set the default folder to images folder */
2480 docs_folder = g_build_filename (g_getenv (MODEST_MAEMO_UTILS_MYDOCS_ENV),
2481 ".documents", NULL);
2482 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), docs_folder);
2483 g_free (docs_folder);
2485 g_free (conf_folder);
2486 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2487 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2488 GTK_WINDOW (dialog), GTK_WINDOW (window));
2490 /* Connect to response & show */
2491 g_signal_connect (dialog, "response",
2492 G_CALLBACK (on_attach_file_response), window);
2493 gtk_widget_show (dialog);
2498 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2500 GnomeVFSFileSize allowed_size)
2503 GnomeVFSHandle *handle = NULL;
2504 ModestMsgEditWindowPrivate *priv;
2505 GnomeVFSResult result;
2506 GnomeVFSFileSize size = 0;
2507 g_return_val_if_fail (window, 0);
2508 g_return_val_if_fail (uri, 0);
2510 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2512 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2513 if (result == GNOME_VFS_OK) {
2514 TnyMimePart *mime_part;
2516 const gchar *mime_type = NULL;
2518 gchar *escaped_filename;
2521 GnomeVFSFileInfo *info;
2522 GnomeVFSURI *vfs_uri;
2524 gnome_vfs_close (handle);
2525 vfs_uri = gnome_vfs_uri_new (uri);
2528 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2529 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2530 g_free (escaped_filename);
2531 gnome_vfs_uri_unref (vfs_uri);
2533 info = gnome_vfs_file_info_new ();
2535 if (gnome_vfs_get_file_info (uri,
2537 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2539 mime_type = gnome_vfs_file_info_get_mime_type (info);
2540 mime_part = tny_platform_factory_new_mime_part
2541 (modest_runtime_get_platform_factory ());
2543 /* try to get the attachment's size; this may fail for weird
2544 * file systems, like obex, upnp... */
2545 if (allowed_size != 0 &&
2546 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2548 if (size > allowed_size) {
2549 modest_platform_information_banner (NULL, NULL,
2550 _FM("sfil_ib_opening_not_allowed"));
2555 g_warning ("%s: could not get attachment size", __FUNCTION__);
2557 stream = create_stream_for_uri (uri);
2559 if (stream == NULL) {
2561 modest_platform_information_banner (NULL, NULL, _FM("sfil_ib_opening_not_allowed"));
2563 g_object_unref (mime_part);
2565 gnome_vfs_file_info_unref (info);
2569 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2570 g_object_unref (stream);
2572 content_id = g_strdup_printf ("%d", priv->next_cid);
2573 tny_mime_part_set_content_id (mime_part, content_id);
2574 g_free (content_id);
2577 basename = g_path_get_basename (filename);
2578 tny_mime_part_set_filename (mime_part, basename);
2581 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2582 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2584 info->size == 0, info->size);
2585 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2586 gtk_widget_show_all (priv->attachments_caption);
2587 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2589 g_object_unref (mime_part);
2590 gnome_vfs_file_info_unref (info);
2597 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2600 ModestMsgEditWindowPrivate *priv;
2603 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2604 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2606 if (att_list == NULL) {
2607 att_list = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2608 if (!modest_maemo_utils_select_attachments (GTK_WINDOW (window), att_list, TRUE)) {
2609 g_object_unref (att_list);
2614 g_object_ref (att_list);
2617 if (tny_list_get_length (att_list) == 0) {
2618 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2620 gboolean dialog_response;
2621 gchar *message = NULL;
2622 gchar *filename = NULL;
2624 if (tny_list_get_length (att_list) == 1) {
2626 iter = tny_list_create_iterator (att_list);
2627 part = (TnyMimePart *) tny_iterator_get_current (iter);
2628 g_object_unref (iter);
2629 if (TNY_IS_MSG (part)) {
2630 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2632 filename = tny_header_dup_subject (header);
2633 g_object_unref (header);
2635 if (filename == NULL) {
2636 filename = g_strdup (_("mail_va_no_subject"));
2639 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2641 g_object_unref (part);
2643 filename = g_strdup ("");
2645 message = g_strdup_printf (ngettext("emev_nc_delete_attachment",
2646 "emev_nc_delete_attachments",
2647 tny_list_get_length (att_list)), filename);
2650 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
2654 if (dialog_response != GTK_RESPONSE_OK) {
2655 g_object_unref (att_list);
2659 for (iter = tny_list_create_iterator (att_list);
2660 !tny_iterator_is_done (iter);
2661 tny_iterator_next (iter)) {
2662 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2663 const gchar *att_id;
2664 tny_list_remove (priv->attachments, (GObject *) mime_part);
2666 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2668 if (tny_list_get_length (priv->attachments) == 0)
2669 gtk_widget_hide (priv->attachments_caption);
2670 att_id = tny_mime_part_get_content_id (mime_part);
2672 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2674 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2675 g_object_unref (mime_part);
2677 g_object_unref (iter);
2680 g_object_unref (att_list);
2682 /* if the last attachment has been removed, focus the Subject: field */
2683 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2684 gtk_widget_grab_focus (priv->subject_field);
2688 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2691 ModestMsgEditWindowPrivate *priv;
2692 GdkColor *new_color;
2693 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2695 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2696 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2699 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2701 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2703 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2705 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2710 font_size_clicked (GtkToolButton *button,
2711 ModestMsgEditWindow *window)
2713 ModestMsgEditWindowPrivate *priv;
2714 GtkWidget *selector, *dialog;
2716 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2718 selector = hildon_touch_selector_new ();
2719 hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector), priv->sizes_model, TRUE);
2720 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_size_index);
2722 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2723 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2724 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_size"));
2726 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2730 WPTextBufferFormat format;
2732 new_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2734 memset (&format, 0, sizeof (format));
2735 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2737 format.cs.font_size = TRUE;
2738 format.cs.text_position = TRUE;
2739 format.cs.font = TRUE;
2740 format.font_size = new_index;
2741 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2743 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2744 GINT_TO_POINTER (new_index)))
2745 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2747 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2748 size_text = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (selector));
2749 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
2750 size_text, "</span>", NULL);
2752 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2756 gtk_widget_destroy (dialog);
2758 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2763 font_face_clicked (GtkToolButton *button,
2764 ModestMsgEditWindow *window)
2766 ModestMsgEditWindowPrivate *priv;
2767 GtkWidget *selector, *dialog;
2768 GtkCellRenderer *renderer;
2770 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2772 selector = hildon_touch_selector_new ();
2773 renderer = gtk_cell_renderer_text_new ();
2774 hildon_touch_selector_append_column (HILDON_TOUCH_SELECTOR (selector), priv->faces_model,
2775 renderer, "family", 0, "text", 0, NULL);
2776 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_face_index);
2778 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2779 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2780 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_face"));
2782 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2783 gint new_font_index;
2787 new_font_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2788 path = gtk_tree_path_new_from_indices (new_font_index, -1);
2789 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2793 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2795 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2796 GINT_TO_POINTER(new_font_index)))
2797 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2799 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2800 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2802 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2806 gtk_tree_path_free (path);
2809 gtk_widget_destroy (dialog);
2811 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2816 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2819 ModestMsgEditWindowPrivate *priv = NULL;
2820 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2822 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2823 if (!priv->update_caption_visibility)
2826 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2828 gtk_widget_show (priv->cc_caption);
2830 gtk_widget_hide (priv->cc_caption);
2832 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2836 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2839 ModestMsgEditWindowPrivate *priv = NULL;
2840 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2842 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2843 if (!priv->update_caption_visibility)
2846 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2848 gtk_widget_show (priv->bcc_caption);
2850 gtk_widget_hide (priv->bcc_caption);
2852 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2856 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2857 ModestRecptEditor *editor)
2859 ModestMsgEditWindowPrivate *priv;
2861 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2862 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2864 /* we check for low-mem; in that case, show a warning, and don't allow
2865 * for the addressbook
2867 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2870 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2872 if (editor == NULL) {
2873 GtkWidget *view_focus;
2874 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2876 /* This code should be kept in sync with ModestRecptEditor. The
2877 textview inside the recpt editor is the one that really gets the
2878 focus. As it's inside a scrolled window, and this one inside the
2879 hbox recpt editor inherits from, we'll need to go up in the
2880 hierarchy to know if the text view is part of the recpt editor
2881 or if it's a different text entry */
2883 if (gtk_widget_get_parent (view_focus)) {
2884 GtkWidget *first_parent;
2886 first_parent = gtk_widget_get_parent (view_focus);
2887 if (gtk_widget_get_parent (first_parent) &&
2888 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2889 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2894 editor = MODEST_RECPT_EDITOR (priv->to_field);
2898 modest_address_book_select_addresses (editor);
2903 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2905 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2907 modest_msg_edit_window_open_addressbook (window, NULL);
2911 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2912 gboolean show_toolbar)
2914 ModestWindowPrivate *parent_priv;
2916 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2917 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2919 /* We can not just use the code of
2920 modest_msg_edit_window_setup_toolbar because it has a
2921 mixture of both initialization and creation code. */
2923 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2925 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2929 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2930 TnyHeaderFlags priority_flags)
2932 ModestMsgEditWindowPrivate *priv;
2933 ModestWindowPrivate *parent_priv;
2935 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2937 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2938 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2940 if (priv->priority_flags != priority_flags) {
2941 GtkAction *priority_action = NULL;
2943 priv->priority_flags = priority_flags;
2945 switch (priority_flags) {
2946 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2947 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2948 MODEST_HEADER_ICON_HIGH,
2949 HILDON_ICON_SIZE_SMALL);
2950 gtk_widget_show (priv->priority_icon);
2951 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2952 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2954 case TNY_HEADER_FLAG_LOW_PRIORITY:
2955 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2956 MODEST_HEADER_ICON_LOW,
2957 HILDON_ICON_SIZE_SMALL);
2958 gtk_widget_show (priv->priority_icon);
2959 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2960 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2963 gtk_widget_hide (priv->priority_icon);
2964 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2965 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2968 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2969 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2971 gtk_widget_queue_resize (priv->subject_box);
2975 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2978 ModestMsgEditWindowPrivate *priv;
2979 ModestWindowPrivate *parent_priv;
2980 gint current_format;
2982 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2984 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2985 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2987 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2988 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2990 if (current_format != file_format) {
2991 switch (file_format) {
2992 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2993 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2994 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
2996 case MODEST_FILE_FORMAT_PLAIN_TEXT:
3000 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
3001 response = gtk_dialog_run (GTK_DIALOG (dialog));
3002 gtk_widget_destroy (dialog);
3003 if (response == GTK_RESPONSE_OK) {
3004 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
3006 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
3007 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
3012 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3013 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3014 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3019 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
3022 ModestMsgEditWindowPrivate *priv;
3023 WPTextBufferFormat oldfmt, fmt;
3024 gint old_position = 0;
3028 GdkColor *color = NULL;
3029 gboolean bold, bold_set, italic, italic_set;
3030 gboolean underline, underline_set;
3031 gboolean strikethrough, strikethrough_set;
3032 gboolean position_set;
3033 gboolean font_size_set, font_set, color_set;
3036 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3037 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3039 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
3040 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
3041 GTK_WINDOW(dialog), GTK_WINDOW (window));
3043 /* First we get the currently selected font information */
3044 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
3046 switch (oldfmt.text_position) {
3047 case TEXT_POSITION_NORMAL:
3050 case TEXT_POSITION_SUPERSCRIPT:
3058 g_object_set (G_OBJECT (dialog),
3059 "bold", oldfmt.bold != FALSE,
3060 "bold-set", !oldfmt.cs.bold,
3061 "underline", oldfmt.underline != FALSE,
3062 "underline-set", !oldfmt.cs.underline,
3063 "italic", oldfmt.italic != FALSE,
3064 "italic-set", !oldfmt.cs.italic,
3065 "strikethrough", oldfmt.strikethrough != FALSE,
3066 "strikethrough-set", !oldfmt.cs.strikethrough,
3067 "color", &oldfmt.color,
3068 "color-set", !oldfmt.cs.color,
3069 "size", wp_font_size[oldfmt.font_size],
3070 "size-set", !oldfmt.cs.font_size,
3071 "position", old_position,
3072 "position-set", !oldfmt.cs.text_position,
3073 "family", wp_get_font_name (oldfmt.font),
3074 "family-set", !oldfmt.cs.font,
3077 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
3078 GTK_WINDOW (dialog), GTK_WINDOW (window));
3079 gtk_widget_show_all (dialog);
3080 priv->font_dialog = dialog;
3081 response = gtk_dialog_run (GTK_DIALOG (dialog));
3082 priv->font_dialog = NULL;
3083 if (response == GTK_RESPONSE_OK) {
3085 g_object_get( dialog,
3087 "bold-set", &bold_set,
3088 "underline", &underline,
3089 "underline-set", &underline_set,
3091 "italic-set", &italic_set,
3092 "strikethrough", &strikethrough,
3093 "strikethrough-set", &strikethrough_set,
3095 "color-set", &color_set,
3097 "size-set", &font_size_set,
3098 "family", &font_name,
3099 "family-set", &font_set,
3100 "position", &position,
3101 "position-set", &position_set,
3106 if (response == GTK_RESPONSE_OK) {
3107 memset(&fmt, 0, sizeof(fmt));
3113 fmt.italic = italic;
3114 fmt.cs.italic = TRUE;
3116 if (underline_set) {
3117 fmt.underline = underline;
3118 fmt.cs.underline = TRUE;
3120 if (strikethrough_set) {
3121 fmt.strikethrough = strikethrough;
3122 fmt.cs.strikethrough = TRUE;
3127 ? TEXT_POSITION_NORMAL
3128 : ( ( position == 1 )
3129 ? TEXT_POSITION_SUPERSCRIPT
3130 : TEXT_POSITION_SUBSCRIPT );
3131 fmt.cs.text_position = TRUE;
3132 fmt.font_size = oldfmt.font_size;
3136 fmt.cs.color = TRUE;
3139 fmt.font = wp_get_font_index(font_name,
3144 if (font_size_set) {
3145 fmt.cs.font_size = TRUE;
3146 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
3148 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
3149 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3151 gtk_widget_destroy (dialog);
3153 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
3157 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
3159 ModestMsgEditWindowPrivate *priv;
3161 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3162 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3164 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
3166 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3167 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3171 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
3173 ModestMsgEditWindowPrivate *priv;
3175 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3176 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3178 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
3180 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3181 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3186 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
3188 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3190 priv->can_undo = can_undo;
3194 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
3196 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3198 priv->can_redo = can_redo;
3202 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3204 ModestMsgEditWindowPrivate *priv;
3205 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3206 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3208 return priv->can_undo;
3212 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3214 ModestMsgEditWindowPrivate *priv;
3215 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3216 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3218 return priv->can_redo;
3223 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3226 GtkTextIter match_start, match_end;
3228 if (image_id == NULL)
3231 gtk_text_buffer_get_start_iter (buffer, &iter);
3233 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3234 GSList *tags = gtk_text_iter_get_tags (&match_start);
3236 for (node = tags; node != NULL; node = g_slist_next (node)) {
3237 GtkTextTag *tag = (GtkTextTag *) node->data;
3238 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3239 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3240 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3242 offset = gtk_text_iter_get_offset (&match_start);
3243 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3244 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3248 gtk_text_iter_forward_char (&iter);
3253 message_is_empty (ModestMsgEditWindow *window)
3255 ModestMsgEditWindowPrivate *priv = NULL;
3257 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3258 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3260 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3261 * so we can ignore markup.
3263 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3266 count = gtk_text_buffer_get_char_count (buf);
3272 msg_body_focus (GtkWidget *focus,
3273 GdkEventFocus *event,
3277 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3278 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3279 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3284 recpt_field_changed (GtkTextBuffer *buffer,
3285 ModestMsgEditWindow *editor)
3287 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3288 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3292 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3294 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3295 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3299 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3302 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3303 GtkTextBuffer *buffer;
3305 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3306 gtk_text_buffer_set_modified (buffer, modified);
3307 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3308 gtk_text_buffer_set_modified (buffer, modified);
3309 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3310 gtk_text_buffer_set_modified (buffer, modified);
3311 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3315 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3317 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3318 const char *account_name;
3319 GtkTextBuffer *buffer;
3321 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3322 if (gtk_text_buffer_get_modified (buffer))
3324 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3325 if (gtk_text_buffer_get_modified (buffer))
3327 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3328 if (gtk_text_buffer_get_modified (buffer))
3330 if (gtk_text_buffer_get_modified (priv->text_buffer))
3333 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3334 if (priv->original_mailbox) {
3335 if (!account_name || strcmp (account_name, priv->original_mailbox))
3337 } else if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3348 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3350 ModestMsgEditWindowPrivate *priv = NULL;
3352 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3353 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3355 /* check if there's no recipient added */
3356 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3357 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3358 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3359 /* no recipient contents, then select contacts */
3360 modest_msg_edit_window_open_addressbook (window, NULL);
3364 g_object_ref (window);
3365 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3366 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3367 g_object_unref (window);
3370 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3371 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3372 g_object_unref (window);
3375 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3376 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3377 g_object_unref (window);
3381 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3382 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3383 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3384 g_object_unref (window);
3391 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3392 ModestMsgEditWindow *window)
3394 modest_msg_edit_window_offer_attach_file (window);
3398 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3400 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3402 return priv->clipboard_text;
3406 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3408 ModestMsgEditWindow *window)
3410 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3411 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3414 /* It could happen that the window was already closed */
3415 if (!GTK_WIDGET_VISIBLE (window))
3418 g_object_ref (window);
3419 text = gtk_clipboard_wait_for_text (selection_clipboard);
3421 if (priv->clipboard_text != NULL) {
3422 g_free (priv->clipboard_text);
3424 priv->clipboard_text = text;
3426 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3428 g_object_unref (window);
3431 static gboolean clipboard_owner_change_idle (gpointer userdata)
3433 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3434 ModestMsgEditWindowPrivate *priv;
3436 gdk_threads_enter ();
3437 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3438 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3440 priv->clipboard_owner_idle = 0;
3441 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3442 gdk_threads_leave ();
3448 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3450 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3451 if (priv->clipboard_owner_idle == 0) {
3452 priv->clipboard_owner_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
3453 clipboard_owner_change_idle,
3454 g_object_ref (window),
3460 subject_field_move_cursor (GtkEntry *entry,
3461 GtkMovementStep step,
3466 /* It could happen that the window was already closed */
3467 if (!GTK_WIDGET_VISIBLE (window))
3470 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3474 update_window_title (ModestMsgEditWindow *window)
3476 ModestMsgEditWindowPrivate *priv = NULL;
3477 const gchar *subject;
3479 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3480 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3481 if (subject == NULL || subject[0] == '\0')
3482 subject = _("mail_va_new_email");
3484 gtk_window_set_title (GTK_WINDOW (window), subject);
3489 subject_field_changed (GtkEditable *editable,
3490 ModestMsgEditWindow *window)
3492 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3493 update_window_title (window);
3494 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3495 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3496 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3500 subject_field_insert_text (GtkEditable *editable,
3502 gint new_text_length,
3504 ModestMsgEditWindow *window)
3506 GString *result = g_string_new ("");
3508 gint result_len = 0;
3509 const gchar *entry_text = NULL;
3512 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3513 old_length = g_utf8_strlen (entry_text, -1);
3515 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3516 gunichar c = g_utf8_get_char_validated (current, 8);
3517 /* Invalid unichar, stop */
3523 result = g_string_append_unichar (result, c);
3527 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3528 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3531 /* Prevent endless recursion */
3532 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3533 g_signal_emit_by_name (editable, "insert-text",
3534 (gpointer) result->str, (gpointer) result->len,
3535 (gpointer) position, (gpointer) window);
3536 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3540 if (result_len + old_length > 1000) {
3541 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3542 _CS("ckdg_ib_maximum_characters_reached"));
3544 g_string_free (result, TRUE);
3548 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3551 ModestMsgEditWindowPrivate *priv = NULL;
3553 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3554 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3556 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3559 gtk_widget_show_all (priv->find_toolbar);
3560 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3562 gtk_widget_hide_all (priv->find_toolbar);
3563 gtk_widget_grab_focus (priv->msg_body);
3568 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3570 GtkTextIter *match_start,
3571 GtkTextIter *match_end)
3573 GtkTextIter end_iter;
3574 gchar *str_casefold;
3577 gchar *range_casefold;
3580 gboolean result = FALSE;
3587 gtk_text_iter_forward_to_end (&end_iter);
3589 str_casefold = g_utf8_casefold (str, -1);
3590 str_chars_n = strlen (str);
3592 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3593 range_casefold = g_utf8_casefold (range_text, -1);
3594 range_chars_n = strlen (range_casefold);
3596 if (range_chars_n < str_chars_n) {
3597 g_free (str_casefold);
3598 g_free (range_text);
3599 g_free (range_casefold);
3603 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3604 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3605 if (!g_utf8_collate (range_subtext, str_casefold)) {
3606 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3608 if (!gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3609 match_start, match_end, NULL)) {
3610 g_warning ("Matched string with collate, but not matched in model");
3612 g_free (found_text);
3614 g_free (range_subtext);
3618 g_free (str_casefold);
3619 g_free (range_text);
3620 g_free (range_casefold);
3627 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3628 ModestMsgEditWindow *window)
3630 gchar *current_search = NULL;
3631 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3633 GtkTextIter selection_start, selection_end;
3634 GtkTextIter match_start, match_end;
3635 gboolean continue_search = FALSE;
3637 if (message_is_empty (window)) {
3638 g_free (priv->last_search);
3639 priv->last_search = NULL;
3640 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3644 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3645 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3646 g_free (current_search);
3647 g_free (priv->last_search);
3648 priv->last_search = NULL;
3649 /* Information banner about empty search */
3650 hildon_banner_show_information (NULL, NULL, _CS("ecdg_ib_find_rep_enter_text"));
3654 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3655 continue_search = TRUE;
3657 g_free (priv->last_search);
3658 priv->last_search = g_strdup (current_search);
3661 if (continue_search) {
3662 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3663 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3664 &match_start, &match_end);
3666 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_search_complete"));
3668 GtkTextIter buffer_start;
3669 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3670 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3671 &match_start, &match_end);
3673 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_no_matches"));
3676 /* Mark as selected the string found in search */
3678 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3679 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3680 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3682 g_free (priv->last_search);
3683 priv->last_search = NULL;
3685 g_free (current_search);
3689 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3691 ModestMsgEditWindowPrivate *priv;
3693 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3698 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3701 ModestMsgEditWindowPrivate *priv;
3703 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3708 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3709 ModestMsgEditWindow *window)
3711 modest_msg_edit_window_toggle_find_toolbar (window, FALSE);
3715 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3718 ModestMsgEditWindowPrivate *priv;
3719 TnyHeader *header = NULL;
3721 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3722 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3724 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3726 if (priv->draft_msg != NULL) {
3727 g_object_unref (priv->draft_msg);
3730 if (draft != NULL) {
3731 g_object_ref (draft);
3732 header = tny_msg_get_header (draft);
3733 if (priv->msg_uid) {
3734 g_free (priv->msg_uid);
3735 priv->msg_uid = NULL;
3737 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3740 priv->draft_msg = draft;
3744 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3745 GtkTextIter *start, GtkTextIter *end,
3748 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3749 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3752 if (tag == NULL) return;
3753 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3754 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3755 replace_with_images (window, priv->images);
3760 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3763 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3765 g_return_if_fail (TNY_IS_MIME_PART (part));
3766 tny_list_prepend (priv->attachments, (GObject *) part);
3767 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3768 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3769 gtk_widget_show_all (priv->attachments_caption);
3770 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3774 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3776 ModestMsgEditWindowPrivate *priv;
3778 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3779 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3781 return priv->msg_uid;
3785 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3786 ModestMsgEditWindowWidgetType widget_type)
3788 ModestMsgEditWindowPrivate *priv;
3790 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3791 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3793 switch (widget_type) {
3794 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3795 return priv->msg_body;
3797 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3798 return priv->to_field;
3800 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3801 return priv->cc_field;
3803 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3804 return priv->bcc_field;
3806 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3807 return priv->subject_field;
3809 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3810 return priv->attachments_view;
3818 remove_tags (WPTextBuffer *buffer)
3820 GtkTextIter start, end;
3822 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3823 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3825 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3829 on_account_removed (TnyAccountStore *account_store,
3830 TnyAccount *account,
3833 /* Do nothing if it's a store account, because we use the
3834 transport to send the messages */
3835 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3836 const gchar *parent_acc = NULL;
3837 const gchar *our_acc = NULL;
3839 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3840 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3841 /* Close this window if I'm showing a message of the removed account */
3842 if (strcmp (parent_acc, our_acc) == 0)
3843 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3847 static void update_signature (ModestMsgEditWindow *self,
3848 const gchar *old_account,
3849 const gchar *new_account)
3851 ModestMsgEditWindowPrivate *priv;
3852 gboolean has_old_signature, has_new_signature;
3854 GtkTextIter match_start, match_end;
3855 ModestAccountMgr *mgr;
3857 gchar *full_signature;
3859 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3861 gtk_text_buffer_begin_user_action (priv->text_buffer);
3863 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
3864 mgr = modest_runtime_get_account_mgr ();
3868 signature = modest_account_mgr_get_signature_from_recipient (mgr, old_account, &has_old_signature);
3869 if (has_old_signature) {
3870 full_signature = g_strconcat ("\n--\n", signature, NULL);
3871 if (gtk_text_iter_forward_search (&iter, full_signature, 0, &match_start, &match_end, NULL)) {
3872 gtk_text_buffer_delete (priv->text_buffer, &match_start, &match_end);
3874 } else if (gtk_text_iter_forward_search (&iter, _("mcen_ia_editor_original_message"), 0,
3875 &match_start, &match_end, NULL)) {
3878 g_free (full_signature);
3883 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3884 signature = modest_account_mgr_get_signature_from_recipient (mgr, new_account, &has_new_signature);
3885 if (has_new_signature) {
3886 full_signature = g_strconcat ("\n--\n", signature, NULL);
3887 gtk_text_buffer_insert (priv->text_buffer, &iter, full_signature, -1);
3888 g_free (full_signature);
3891 gtk_text_buffer_end_user_action (priv->text_buffer);
3895 from_field_changed (HildonPickerButton *button,
3896 ModestMsgEditWindow *self)
3898 ModestMsgEditWindowPrivate *priv;
3899 gchar *old_account, *new_account;
3901 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3903 old_account = priv->last_from_account;
3904 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3905 new_account = priv->last_from_account;
3907 update_signature (self, old_account, new_account);
3911 typedef struct _MessageSettingsHelper {
3912 ModestMsgEditWindow *window;
3913 GSList *priority_group;
3914 GSList *format_group;
3915 GtkToggleButton *current_priority;
3916 GtkToggleButton *current_format;
3917 } MessageSettingsHelper;
3920 on_priority_toggle (GtkToggleButton *button,
3921 MessageSettingsHelper *helper)
3924 ModestMsgEditWindowPrivate *priv;
3926 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3927 if (gtk_toggle_button_get_active (button)) {
3929 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3930 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3931 if ((node_button != button) &&
3932 gtk_toggle_button_get_active (node_button)) {
3933 gtk_toggle_button_set_active (node_button, FALSE);
3936 helper->current_priority = button;
3938 gboolean found = FALSE;
3939 /* If no one is active, activate it again */
3940 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3941 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3942 if (gtk_toggle_button_get_active (node_button)) {
3948 gtk_toggle_button_set_active (button, TRUE);
3954 on_format_toggle (GtkToggleButton *button,
3955 MessageSettingsHelper *helper)
3958 ModestMsgEditWindowPrivate *priv;
3960 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3961 if (gtk_toggle_button_get_active (button)) {
3963 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
3964 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3965 if ((node_button != button) &&
3966 gtk_toggle_button_get_active (node_button)) {
3967 gtk_toggle_button_set_active (node_button, FALSE);
3970 helper->current_format = button;
3972 gboolean found = FALSE;
3973 /* If no one is active, activate it again */
3974 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
3975 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3976 if (gtk_toggle_button_get_active (node_button)) {
3982 gtk_toggle_button_set_active (button, TRUE);
3989 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
3994 GtkWidget *priority_hbox;
3995 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
3996 GtkWidget *captioned;
3997 GtkSizeGroup *title_sizegroup, *value_sizegroup;
3998 GtkWidget *format_hbox;
3999 GtkWidget *html_toggle, *text_toggle;
4000 ModestMsgEditWindowPrivate *priv;
4001 MessageSettingsHelper helper = {0,};
4003 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4004 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
4005 helper.window = window;
4006 helper.priority_group = NULL;
4007 helper.format_group = NULL;
4009 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4010 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4012 dialog = gtk_dialog_new_with_buttons (_("mcen_me_message_settings"), NULL,
4013 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
4014 _HL("wdgt_bd_done"), GTK_RESPONSE_ACCEPT, NULL);
4015 vbox = gtk_vbox_new (FALSE, 0);
4016 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
4017 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DOUBLE, 0);
4018 gtk_container_add (GTK_CONTAINER (align), vbox);
4019 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), align);
4020 gtk_widget_show (align);
4021 gtk_widget_show (vbox);
4023 /* Priority toggles */
4024 priority_hbox = gtk_hbox_new (TRUE, 0);
4025 high_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4026 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
4027 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
4028 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
4029 medium_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4030 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
4031 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
4032 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
4033 low_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4034 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
4035 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
4036 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
4037 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, TRUE, TRUE, 0);
4038 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, TRUE, TRUE, 0);
4039 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, TRUE, TRUE, 0);
4040 gtk_widget_show_all (priority_hbox);
4041 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
4042 _("mcen_me_editor_message_priority"), FALSE, priority_hbox);
4043 gtk_widget_show (captioned);
4044 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
4046 /* format toggles */
4047 format_hbox = gtk_hbox_new (TRUE, 0);
4048 html_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4049 gtk_button_set_label (GTK_BUTTON (html_toggle), _("mcen_me_editor_formatted_text"));
4050 helper.format_group = g_slist_prepend (helper.format_group, html_toggle);
4051 g_object_set_data (G_OBJECT (html_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_HTML));
4052 g_object_set_data (G_OBJECT (html_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_FORMATTED_TEXT));
4053 text_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4054 gtk_button_set_label (GTK_BUTTON (text_toggle), _("mcen_me_editor_plain_text"));
4055 helper.format_group = g_slist_prepend (helper.format_group, text_toggle);
4056 g_object_set_data (G_OBJECT (text_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_TEXT));
4057 g_object_set_data (G_OBJECT (text_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_PLAIN_TEXT));
4058 gtk_box_pack_start (GTK_BOX (format_hbox), html_toggle, TRUE, TRUE, 0);
4059 gtk_box_pack_start (GTK_BOX (format_hbox), text_toggle, TRUE, TRUE, 0);
4060 gtk_widget_show_all (format_hbox);
4061 gtk_widget_show (format_hbox);
4062 gtk_box_pack_start (GTK_BOX (vbox), format_hbox, FALSE, FALSE, 0);
4065 g_object_unref (title_sizegroup);
4066 g_object_unref (value_sizegroup);
4068 /* Set current values */
4069 switch (priv->priority_flags) {
4070 case TNY_HEADER_FLAG_HIGH_PRIORITY:
4071 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (high_toggle), TRUE);
4072 helper.current_priority = GTK_TOGGLE_BUTTON (high_toggle);
4074 case TNY_HEADER_FLAG_LOW_PRIORITY:
4075 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (low_toggle), TRUE);
4076 helper.current_priority = GTK_TOGGLE_BUTTON (low_toggle);
4079 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (medium_toggle), TRUE);
4080 helper.current_priority = GTK_TOGGLE_BUTTON (medium_toggle);
4084 switch (modest_msg_edit_window_get_format (window)) {
4085 case MODEST_MSG_EDIT_FORMAT_TEXT:
4086 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_toggle), TRUE);
4087 helper.current_format = GTK_TOGGLE_BUTTON (text_toggle);
4089 case MODEST_MSG_EDIT_FORMAT_HTML:
4091 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (html_toggle), TRUE);
4092 helper.current_format = GTK_TOGGLE_BUTTON (html_toggle);
4096 /* Signal connects */
4097 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4098 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4099 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4100 g_signal_connect (G_OBJECT (html_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4101 g_signal_connect (G_OBJECT (text_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4103 /* Save settings if the user clicked on done */
4104 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
4105 TnyHeaderFlags flags;
4106 ModestMsgEditFormat old_format, new_format;
4108 /* Set priority flags */
4109 flags = (TnyHeaderFlags) g_object_get_data (G_OBJECT (helper.current_priority), "priority");
4110 if (priv->priority_flags != flags)
4111 modest_msg_edit_window_set_priority_flags (window, flags);
4113 /* Set edit format */
4114 old_format = modest_msg_edit_window_get_format (window);
4115 new_format = (ModestMsgEditFormat) g_object_get_data (G_OBJECT (helper.current_format), "format");
4116 if (old_format != new_format) {
4117 gint file_format = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (helper.current_format), "file-format"));
4118 modest_msg_edit_window_set_file_format (window, file_format);
4122 gtk_widget_destroy (dialog);
4123 g_slist_free (helper.priority_group);
4127 on_message_settings (GtkAction *action,
4128 ModestMsgEditWindow *window)
4130 modest_msg_edit_window_show_msg_settings_dialog (window);
4134 on_cc_button_toggled (HildonCheckButton *button,
4135 ModestMsgEditWindow *window)
4137 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4139 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
4140 hildon_check_button_get_active (button));
4144 on_bcc_button_toggled (HildonCheckButton *button,
4145 ModestMsgEditWindow *window)
4147 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4149 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
4150 hildon_check_button_get_active (button));
4154 setup_menu (ModestMsgEditWindow *self)
4156 ModestMsgEditWindowPrivate *priv = NULL;
4158 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
4160 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4162 /* Settings menu buttons */
4163 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_checknames"), NULL,
4164 APP_MENU_CALLBACK (modest_ui_actions_on_check_names),
4166 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_undo"), "<Ctrl>z",
4167 APP_MENU_CALLBACK (modest_ui_actions_on_undo),
4168 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_undo));
4170 priv->cc_button = hildon_check_button_new (0);
4171 gtk_button_set_label (GTK_BUTTON (priv->cc_button), _("mcen_me_editor_showcc"));
4172 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button),
4174 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->cc_button),
4176 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
4177 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
4178 priv->bcc_button = hildon_check_button_new (0);
4179 gtk_button_set_label (GTK_BUTTON (priv->bcc_button), _("mcen_me_editor_showbcc"));
4180 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button),
4182 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->bcc_button),
4184 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
4185 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
4187 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_attach_inlineimage"), NULL,
4188 APP_MENU_CALLBACK (modest_ui_actions_on_insert_image),
4189 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_set_style));
4190 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_remove_attachments"), NULL,
4191 APP_MENU_CALLBACK (modest_ui_actions_on_remove_attachments),
4192 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
4193 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_message_settings"), NULL,
4194 APP_MENU_CALLBACK (on_message_settings),
4196 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_viewer_find"), "<Ctrl>f",
4197 APP_MENU_CALLBACK (modest_ui_actions_on_toggle_find_in_page),