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>
42 #include <modest-account-mgr.h>
43 #include <modest-account-mgr-helpers.h>
45 #include <widgets/modest-msg-edit-window.h>
46 #include <modest-selector-picker.h>
47 #include <widgets/modest-recpt-editor.h>
48 #include <widgets/modest-attachments-view.h>
50 #include <modest-runtime.h>
52 #include "modest-platform.h"
53 #include "modest-icon-names.h"
54 #include "modest-widget-memory.h"
55 #include "modest-window-priv.h"
56 #include "modest-mail-operation.h"
57 #include "modest-tny-platform-factory.h"
58 #include "modest-tny-msg.h"
59 #include "modest-tny-folder.h"
60 #include "modest-tny-account.h"
61 #include "modest-address-book.h"
62 #include "modest-text-utils.h"
63 #include <tny-simple-list.h>
64 #include <wptextview.h>
65 #include <wptextbuffer.h>
66 #include <hildon/hildon-pannable-area.h>
67 #include "modest-msg-edit-window-ui-dimming.h"
69 #include "modest-hildon-includes.h"
70 #ifdef MODEST_HAVE_HILDON0_WIDGETS
71 #include <hildon-widgets/hildon-color-chooser.h>
73 #include "widgets/modest-msg-edit-window-ui.h"
74 #ifdef MODEST_HAVE_HILDON0_WIDGETS
75 #include <libgnomevfs/gnome-vfs-mime-utils.h>
77 #include <libgnomevfs/gnome-vfs-mime.h>
79 #include <modest-utils.h>
80 #include "modest-maemo-utils.h"
81 #include <modest-ui-constants.h>
84 #define DEFAULT_FONT_SIZE 3
85 #define DEFAULT_FONT 2
86 #define DEFAULT_SIZE_BUTTON_FONT_FAMILY "Sans"
87 #define DEFAULT_MAIN_VBOX_SPACING 6
88 #define SUBJECT_MAX_LENGTH 1000
89 #define IMAGE_MAX_WIDTH 560
90 #define DEFAULT_FONT_SCALE 1.5
91 #define ATTACHMENT_BUTTON_WIDTH 118
93 static gboolean is_wp_text_buffer_started = FALSE;
95 static void modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass);
96 static void modest_msg_edit_window_init (ModestMsgEditWindow *obj);
97 static void modest_msg_edit_window_finalize (GObject *obj);
99 static gboolean msg_body_focus (GtkWidget *focus, GdkEventFocus *event, gpointer userdata);
100 static void body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
101 static void recpt_field_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
103 static void text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window);
104 static void text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window);
105 static void text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window);
106 static void text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
107 GtkTextIter *start, GtkTextIter *end,
109 static void text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id);
110 static void subject_field_changed (GtkEditable *editable, ModestMsgEditWindow *window);
111 static void subject_field_insert_text (GtkEditable *editable,
113 gint new_text_length,
115 ModestMsgEditWindow *window);
116 static void modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
118 static void modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
120 static void modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
122 static void modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
124 static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
125 ModestRecptEditor *editor);
126 static void modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
127 ModestMsgEditWindow *window);
129 /* ModestWindow methods implementation */
130 static void modest_msg_edit_window_disconnect_signals (ModestWindow *window);
131 static void modest_msg_edit_window_show_toolbar (ModestWindow *window,
132 gboolean show_toolbar);
133 static void modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
135 ModestMsgEditWindow *window);
136 static void modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window);
137 static void subject_field_move_cursor (GtkEntry *entry,
138 GtkMovementStep step,
142 static void update_window_title (ModestMsgEditWindow *window);
145 static void modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
146 ModestMsgEditWindow *window);
147 static void modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
148 ModestMsgEditWindow *window);
149 static gboolean gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
151 GtkTextIter *match_start,
152 GtkTextIter *match_end);
154 static void remove_tags (WPTextBuffer *buffer);
156 static void on_account_removed (TnyAccountStore *account_store,
160 static void init_window (ModestMsgEditWindow *obj);
162 gboolean scroll_drag_timeout (gpointer userdata);
163 static void correct_scroll (ModestMsgEditWindow *w);
164 static void correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused);
165 static void text_buffer_end_user_action (GtkTextBuffer *buffer,
166 ModestMsgEditWindow *userdata);
167 static void text_buffer_mark_set (GtkTextBuffer *buffer,
170 ModestMsgEditWindow *userdata);
171 static void on_message_settings (GtkAction *action,
172 ModestMsgEditWindow *window);
173 static void setup_menu (ModestMsgEditWindow *self);
175 static void DEBUG_BUFFER (WPTextBuffer *buffer)
179 g_message ("BEGIN BUFFER OF SIZE %d", gtk_text_buffer_get_char_count (GTK_TEXT_BUFFER (buffer)));
181 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &iter);
182 while (!gtk_text_iter_is_end (&iter)) {
183 GString *output = g_string_new ("");
184 GSList *toggled_tags;
187 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
188 g_string_append_printf (output, "%d: CLOSED [ ", gtk_text_iter_get_offset (&iter));
189 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
190 GtkTextTag *tag = (GtkTextTag *) node->data;
192 g_object_get (G_OBJECT (tag), "name", &name, NULL);
193 output = g_string_append (output, name);
194 g_string_append (output, " ");
196 output = g_string_append (output, "] OPENED [ ");
197 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
198 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
199 GtkTextTag *tag = (GtkTextTag *) node->data;
201 g_object_get (G_OBJECT (tag), "name", &name, NULL);
202 output = g_string_append (output, name);
203 g_string_append (output, " ");
205 output = g_string_append (output, "]\n");
206 g_message ("%s", output->str);
207 g_string_free (output, TRUE);
208 gtk_text_iter_forward_to_tag_toggle (&iter, NULL);
210 g_message ("END BUFFER");
214 static const GtkActionEntry hildon2_msg_edit_action_entries [] = {
215 { "MessageSettings", NULL, N_("mcen_me_message_settings"), NULL, NULL, G_CALLBACK (on_message_settings)},
219 /* static gboolean */
220 /* on_key_pressed (GtkWidget *self, */
221 /* GdkEventKey *event, */
222 /* gpointer user_data); */
224 /* list my signals */
231 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
232 struct _ModestMsgEditWindowPrivate {
235 GtkWidget *header_box;
237 ModestPairList *from_field_protos;
238 GtkWidget *from_field;
239 gchar *original_account_name;
243 GtkWidget *bcc_field;
244 GtkWidget *subject_field;
245 GtkWidget *attachments_view;
246 GtkWidget *priority_icon;
247 GtkWidget *add_attachment_button;
249 GtkWidget *cc_caption;
250 GtkWidget *bcc_caption;
251 gboolean update_caption_visibility;
252 GtkWidget *attachments_caption;
254 GtkTextBuffer *text_buffer;
256 GtkWidget *font_size_toolitem;
257 GtkWidget *font_face_toolitem;
258 GtkWidget *font_color_button;
259 GtkWidget *font_color_toolitem;
260 GSList *font_items_group;
261 GtkWidget *font_tool_button_label;
262 GSList *size_items_group;
263 GtkWidget *size_tool_button_label;
265 GtkWidget *find_toolbar;
268 GtkWidget *font_dialog;
271 guint correct_scroll_idle;
272 guint scroll_drag_timeout_id;
276 TnyList *attachments;
281 TnyHeaderFlags priority_flags;
283 gboolean can_undo, can_redo;
284 gulong clipboard_change_handler_id;
285 gulong default_clipboard_change_handler_id;
286 gulong account_removed_handler_id;
287 guint clipboard_owner_idle;
288 gchar *clipboard_text;
297 GtkWidget *cc_button;
298 GtkWidget *bcc_button;
301 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
302 MODEST_TYPE_MSG_EDIT_WINDOW, \
303 ModestMsgEditWindowPrivate))
305 static GtkWindowClass *parent_class = NULL;
307 /* uncomment the following if you have defined any signals */
308 /* static guint signals[LAST_SIGNAL] = {0}; */
311 modest_msg_edit_window_get_type (void)
313 static GType my_type = 0;
315 static const GTypeInfo my_info = {
316 sizeof(ModestMsgEditWindowClass),
317 NULL, /* base init */
318 NULL, /* base finalize */
319 (GClassInitFunc) modest_msg_edit_window_class_init,
320 NULL, /* class finalize */
321 NULL, /* class data */
322 sizeof(ModestMsgEditWindow),
324 (GInstanceInitFunc) modest_msg_edit_window_init,
327 my_type = g_type_register_static (MODEST_TYPE_HILDON2_WINDOW,
328 "ModestMsgEditWindow",
336 save_state (ModestWindow *self)
338 modest_widget_memory_save (modest_runtime_get_conf(),
339 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
344 restore_settings (ModestMsgEditWindow *self)
346 ModestConf *conf = NULL;
348 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
350 conf = modest_runtime_get_conf ();
352 /* Dim at start clipboard actions */
353 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
354 gtk_action_set_sensitive (action, FALSE);
355 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
356 gtk_action_set_sensitive (action, FALSE);
357 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
358 gtk_action_set_sensitive (action, FALSE);
360 modest_widget_memory_restore (conf, G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
365 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
367 GObjectClass *gobject_class;
368 ModestWindowClass *modest_window_class;
369 gobject_class = (GObjectClass*) klass;
370 modest_window_class = (ModestWindowClass*) klass;
372 parent_class = g_type_class_peek_parent (klass);
373 gobject_class->finalize = modest_msg_edit_window_finalize;
375 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
376 modest_window_class->save_state_func = save_state;
377 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
379 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
383 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
385 ModestMsgEditWindowPrivate *priv;
386 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
388 priv->msg_body = NULL;
390 priv->from_field = NULL;
391 priv->to_field = NULL;
392 priv->cc_field = NULL;
393 priv->bcc_field = NULL;
394 priv->subject_field = NULL;
395 priv->attachments = TNY_LIST (tny_simple_list_new ());
396 priv->images = TNY_LIST (tny_simple_list_new ());
397 priv->images_size = 0;
398 priv->images_count = 0;
401 priv->cc_caption = NULL;
402 priv->bcc_caption = NULL;
403 priv->update_caption_visibility = FALSE;
405 priv->priority_flags = 0;
407 priv->find_toolbar = NULL;
408 priv->last_search = NULL;
410 priv->draft_msg = NULL;
411 priv->outbox_msg = NULL;
412 priv->msg_uid = NULL;
414 priv->can_undo = FALSE;
415 priv->can_redo = FALSE;
416 priv->clipboard_change_handler_id = 0;
417 priv->default_clipboard_change_handler_id = 0;
418 priv->account_removed_handler_id = 0;
419 priv->clipboard_owner_idle = 0;
420 priv->clipboard_text = NULL;
423 priv->scroll_drag_timeout_id = 0;
424 priv->correct_scroll_idle = 0;
425 priv->last_upper = 0.0;
427 priv->font_dialog = NULL;
428 priv->app_menu = NULL;
430 if (!is_wp_text_buffer_started) {
431 is_wp_text_buffer_started = TRUE;
432 wp_text_buffer_library_init ();
437 hildon_program_add_window (hildon_program_get_instance(),
443 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
445 static ModestPairList*
446 get_transports (void)
448 GSList *transports = NULL;
450 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
451 GSList *accounts = modest_account_mgr_account_names (account_mgr,
452 TRUE /* only enabled accounts. */);
454 GSList *cursor = accounts;
456 gchar *account_name = cursor->data;
457 gchar *from_string = NULL;
459 from_string = modest_account_mgr_get_from_string (account_mgr,
463 if (from_string && account_name) {
464 gchar *name = account_name;
465 ModestPair *pair = modest_pair_new ((gpointer) name,
466 (gpointer) from_string , TRUE);
467 transports = g_slist_prepend (transports, pair);
470 cursor = cursor->next;
472 g_slist_free (accounts); /* only free the accounts, not the elements,
473 * because they are used in the pairlist */
477 static void window_focus (GtkWindow *window,
481 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
485 scroll_drag_timeout (gpointer userdata)
487 ModestMsgEditWindow *win = (ModestMsgEditWindow *) userdata;
488 ModestMsgEditWindowPrivate *priv;
490 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(win);
492 correct_scroll_without_drag_check (win, TRUE);
494 priv->scroll_drag_timeout_id = 0;
500 correct_scroll_without_drag_check_idle (gpointer userdata)
502 ModestMsgEditWindow *w = (ModestMsgEditWindow *) userdata;
503 ModestMsgEditWindowPrivate *priv;
505 GdkRectangle rectangle;
510 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
512 insert = gtk_text_buffer_get_insert (priv->text_buffer);
513 gtk_text_buffer_get_iter_at_mark (priv->text_buffer, &iter, insert);
515 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &iter, &rectangle);
516 offset = priv->msg_body->allocation.y;
518 new_value = (offset + rectangle.y);
520 hildon_pannable_area_jump_to (HILDON_PANNABLE_AREA (priv->pannable), -1, new_value);
522 priv->correct_scroll_idle = 0;
527 correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused)
529 ModestMsgEditWindowPrivate *priv;
531 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
533 if (only_if_focused && !gtk_widget_is_focus (priv->msg_body))
536 if (priv->correct_scroll_idle > 0) {
540 priv->correct_scroll_idle = g_idle_add ((GSourceFunc) correct_scroll_without_drag_check_idle,
545 correct_scroll (ModestMsgEditWindow *w)
547 ModestMsgEditWindowPrivate *priv;
549 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
550 if (gtk_grab_get_current () == priv->msg_body) {
551 if (priv->scroll_drag_timeout_id == 0) {
552 priv->scroll_drag_timeout_id = g_timeout_add (500, (GSourceFunc) scroll_drag_timeout,
558 correct_scroll_without_drag_check (w, TRUE);
562 text_buffer_end_user_action (GtkTextBuffer *buffer,
563 ModestMsgEditWindow *userdata)
566 correct_scroll (userdata);
570 text_buffer_mark_set (GtkTextBuffer *buffer,
573 ModestMsgEditWindow *userdata)
575 gtk_text_buffer_begin_user_action (buffer);
576 gtk_text_buffer_end_user_action (buffer);
580 cut_clipboard_check (GtkTextView *text_view,
583 GtkTextBuffer *buffer;
585 buffer = gtk_text_view_get_buffer (text_view);
586 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
587 g_signal_stop_emission_by_name ((gpointer )text_view, "cut-clipboard");
592 copy_clipboard_check (GtkTextView *text_view,
595 GtkTextBuffer *buffer;
597 buffer = gtk_text_view_get_buffer (text_view);
598 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
599 g_signal_stop_emission_by_name ((gpointer )text_view, "copy-clipboard");
604 attachment_deleted (ModestAttachmentsView *attachments_view,
607 modest_msg_edit_window_remove_attachments (MODEST_MSG_EDIT_WINDOW (user_data),
612 connect_signals (ModestMsgEditWindow *obj)
614 ModestMsgEditWindowPrivate *priv;
616 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
618 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
619 G_CALLBACK (text_buffer_refresh_attributes), obj);
620 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
621 G_CALLBACK (text_buffer_can_undo), obj);
622 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
623 G_CALLBACK (text_buffer_can_redo), obj);
624 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
625 G_CALLBACK (body_changed), obj);
626 g_signal_connect (G_OBJECT (priv->text_buffer), "modified-changed",
627 G_CALLBACK (body_changed), obj);
628 g_signal_connect (G_OBJECT (priv->text_buffer), "end-user-action",
629 G_CALLBACK (text_buffer_end_user_action), obj);
630 g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
631 G_CALLBACK (text_buffer_mark_set), obj);
632 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
633 G_CALLBACK (text_buffer_apply_tag), obj);
634 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
635 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
636 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
637 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
638 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
639 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
641 g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
642 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
644 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
645 G_CALLBACK (msg_body_focus), obj);
646 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
647 G_CALLBACK (msg_body_focus), obj);
648 g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
649 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
650 "changed", G_CALLBACK (recpt_field_changed), obj);
651 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
652 "changed", G_CALLBACK (recpt_field_changed), obj);
653 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
654 "changed", G_CALLBACK (recpt_field_changed), obj);
655 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
656 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
657 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
659 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
660 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
662 priv->clipboard_change_handler_id =
663 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
664 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
665 priv->default_clipboard_change_handler_id =
666 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
667 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
669 g_signal_connect (G_OBJECT (priv->msg_body), "cut-clipboard", G_CALLBACK (cut_clipboard_check), NULL);
670 g_signal_connect (G_OBJECT (priv->msg_body), "copy-clipboard", G_CALLBACK (copy_clipboard_check), NULL);
671 g_signal_connect (G_OBJECT (priv->attachments_view), "delete", G_CALLBACK (attachment_deleted), obj);
675 init_wp_text_view_style ()
677 static gboolean initialized = FALSE;
680 gtk_rc_parse_string ("class \"WPTextView\" style \"fremantle-textview\"");
686 init_window (ModestMsgEditWindow *obj)
688 GtkWidget *to_caption, *subject_caption;
689 GtkWidget *main_vbox;
690 ModestMsgEditWindowPrivate *priv;
691 GtkActionGroup *action_group;
692 ModestWindowPrivate *parent_priv;
693 GdkPixbuf *window_icon = NULL;
694 GError *error = NULL;
696 GtkSizeGroup *title_size_group;
697 GtkSizeGroup *value_size_group;
698 GtkWidget *subject_box;
699 GtkWidget *attachment_icon;
700 GtkWidget *window_box;
701 #if (GTK_MINOR_VERSION >= 10)
702 GdkAtom deserialize_type;
705 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
706 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
708 parent_priv->ui_manager = gtk_ui_manager_new();
709 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
710 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
712 /* Add common actions */
713 gtk_action_group_add_actions (action_group,
714 modest_msg_edit_action_entries,
715 G_N_ELEMENTS (modest_msg_edit_action_entries),
717 gtk_action_group_add_actions (action_group,
718 hildon2_msg_edit_action_entries,
719 G_N_ELEMENTS (hildon2_msg_edit_action_entries),
721 gtk_action_group_add_toggle_actions (action_group,
722 modest_msg_edit_toggle_action_entries,
723 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
725 gtk_action_group_add_radio_actions (action_group,
726 modest_msg_edit_alignment_radio_action_entries,
727 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
729 G_CALLBACK (modest_ui_actions_on_change_justify),
731 gtk_action_group_add_radio_actions (action_group,
732 modest_msg_edit_priority_action_entries,
733 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
735 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
737 gtk_action_group_add_radio_actions (action_group,
738 modest_msg_edit_file_format_action_entries,
739 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
740 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
741 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
743 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
744 g_object_unref (action_group);
746 /* Load the UI definition */
747 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
750 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
751 g_clear_error (&error);
754 /* Add accelerators */
755 gtk_window_add_accel_group (GTK_WINDOW (obj),
756 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
758 parent_priv->menubar = NULL;
760 title_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
761 value_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
763 /* Note: This ModestPairList* must exist for as long as the picker
764 * that uses it, because the ModestSelectorPicker uses the ID opaquely,
765 * so it can't know how to manage its memory. */
766 priv->from_field = modest_selector_picker_new (MODEST_EDITABLE_SIZE,
767 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL,
769 modest_maemo_utils_set_hbutton_layout (title_size_group, value_size_group,
770 _("mail_va_from"), priv->from_field);
772 priv->to_field = modest_recpt_editor_new ();
773 priv->cc_field = modest_recpt_editor_new ();
774 priv->bcc_field = modest_recpt_editor_new ();
775 subject_box = gtk_hbox_new (FALSE, 0);
776 priv->priority_icon = gtk_image_new ();
777 gtk_box_pack_start (GTK_BOX (subject_box), priv->priority_icon, FALSE, FALSE, 0);
778 priv->subject_field = hildon_entry_new (MODEST_EDITABLE_SIZE);
779 gtk_entry_set_max_length (GTK_ENTRY (priv->subject_field) ,SUBJECT_MAX_LENGTH);
780 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
781 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
782 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
783 gtk_box_pack_start (GTK_BOX (subject_box), priv->subject_field, TRUE, TRUE, 0);
784 priv->add_attachment_button = hildon_button_new (MODEST_EDITABLE_SIZE, HILDON_BUTTON_ARRANGEMENT_VERTICAL);
785 gtk_widget_set_size_request (priv->add_attachment_button, ATTACHMENT_BUTTON_WIDTH, -1);
786 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
787 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
788 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, HILDON_ICON_SIZE_FINGER);
789 hildon_button_set_image (HILDON_BUTTON (priv->add_attachment_button), attachment_icon);
790 gtk_box_pack_start (GTK_BOX (subject_box), priv->add_attachment_button, FALSE, FALSE, 0);
791 priv->attachments_view = modest_attachments_view_new (NULL);
793 priv->header_box = gtk_vbox_new (FALSE, 0);
795 to_caption = modest_maemo_utils_create_captioned_with_size_type
796 (title_size_group, value_size_group,
797 _("mail_va_to"), FALSE, priv->to_field,
798 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
799 priv->cc_caption = modest_maemo_utils_create_captioned_with_size_type
800 (title_size_group, value_size_group,
801 _("mail_va_cc"), FALSE, priv->cc_field,
802 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
803 priv->bcc_caption = modest_maemo_utils_create_captioned_with_size_type
804 (title_size_group, value_size_group,
805 _("mail_va_hotfix1"), FALSE, priv->bcc_field,
806 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
807 subject_caption = modest_maemo_utils_create_captioned (title_size_group, value_size_group,
808 _("mail_va_subject"), FALSE, subject_box);
809 priv->attachments_caption = modest_maemo_utils_create_captioned_with_size_type (title_size_group, value_size_group,
810 _("mail_va_attachment"),
812 priv->attachments_view,
813 HILDON_SIZE_AUTO_WIDTH |
814 HILDON_SIZE_AUTO_HEIGHT);
815 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), value_size_group); */
816 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), value_size_group); */
817 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), value_size_group); */
818 g_object_unref (title_size_group);
819 g_object_unref (value_size_group);
821 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->from_field, FALSE, FALSE, 0);
822 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
823 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
824 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
825 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
826 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
827 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
829 init_wp_text_view_style ();
831 priv->msg_body = wp_text_view_new ();
834 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
835 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
836 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
837 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
838 #if (GTK_MINOR_VERSION >= 10)
839 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
840 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
842 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
843 deserialize_type, TRUE);
845 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
847 priv->find_toolbar = hildon_find_toolbar_new (NULL);
848 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
850 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
852 priv->pannable = hildon_pannable_area_new ();
854 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
856 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
857 priv->frame = gtk_frame_new (NULL);
858 gtk_box_pack_start (GTK_BOX(main_vbox), priv->frame, TRUE, TRUE, 0);
860 hildon_pannable_area_add_with_viewport (HILDON_PANNABLE_AREA (priv->pannable), main_vbox);
861 gtk_container_set_focus_vadjustment (GTK_CONTAINER (main_vbox),
862 hildon_pannable_area_get_vadjustment (HILDON_PANNABLE_AREA (priv->pannable)));
863 gtk_widget_show_all (GTK_WIDGET(priv->pannable));
865 window_box = gtk_vbox_new (FALSE, 0);
866 gtk_container_add (GTK_CONTAINER(obj), window_box);
868 gtk_box_pack_start (GTK_BOX (window_box), priv->pannable, TRUE, TRUE, 0);
870 gtk_container_add (GTK_CONTAINER (priv->frame), priv->msg_body);
872 /* Set window icon */
873 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
875 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
876 g_object_unref (window_icon);
881 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
883 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
885 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
886 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
887 priv->clipboard_change_handler_id))
888 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
889 priv->clipboard_change_handler_id);
890 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
891 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
892 priv->default_clipboard_change_handler_id))
893 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
894 priv->default_clipboard_change_handler_id);
896 if (priv->account_removed_handler_id &&
897 g_signal_handler_is_connected (modest_runtime_get_account_store (),
898 priv->account_removed_handler_id))
899 g_signal_handler_disconnect(modest_runtime_get_account_store (),
900 priv->account_removed_handler_id);
904 modest_msg_edit_window_finalize (GObject *obj)
906 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
908 /* Sanity check: shouldn't be needed, the window mgr should
909 call this function before */
910 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
912 if (priv->font_dialog != NULL) {
913 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
916 if (priv->clipboard_text != NULL) {
917 g_free (priv->clipboard_text);
918 priv->clipboard_text = NULL;
921 if (priv->draft_msg != NULL) {
922 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
923 if (TNY_IS_HEADER (header)) {
924 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
925 modest_window_mgr_unregister_header (mgr, header);
927 g_object_unref (priv->draft_msg);
928 priv->draft_msg = NULL;
930 if (priv->outbox_msg != NULL) {
931 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
932 if (TNY_IS_HEADER (header)) {
933 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
934 modest_window_mgr_unregister_header (mgr, header);
936 g_object_unref (priv->outbox_msg);
937 priv->outbox_msg = NULL;
939 if (priv->correct_scroll_idle > 0) {
940 g_source_remove (priv->correct_scroll_idle);
941 priv->correct_scroll_idle = 0;
943 if (priv->scroll_drag_timeout_id > 0) {
944 g_source_remove (priv->scroll_drag_timeout_id);
945 priv->scroll_drag_timeout_id = 0;
947 if (priv->clipboard_owner_idle > 0) {
948 g_source_remove (priv->clipboard_owner_idle);
949 priv->clipboard_owner_idle = 0;
951 if (priv->original_account_name)
952 g_free (priv->original_account_name);
953 g_free (priv->msg_uid);
954 g_free (priv->last_search);
955 g_slist_free (priv->font_items_group);
956 g_slist_free (priv->size_items_group);
957 g_object_unref (priv->attachments);
958 g_object_unref (priv->images);
960 /* This had to stay alive for as long as the picker that used it: */
961 modest_pair_list_free (priv->from_field_protos);
963 G_OBJECT_CLASS(parent_class)->finalize (obj);
967 pixbuf_from_stream (TnyStream *stream, const gchar *mime_type, guint64 *stream_size)
969 GdkPixbufLoader *loader;
975 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
977 if (loader == NULL) {
983 tny_stream_reset (TNY_STREAM (stream));
984 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
985 GError *error = NULL;
986 unsigned char read_buffer[128];
988 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
990 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
992 g_error_free (error);
997 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
999 g_object_ref (pixbuf);
1000 gdk_pixbuf_loader_close (loader, NULL);
1001 g_object_unref (loader);
1006 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1007 GdkPixbuf *new_pixbuf;
1009 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1010 gdk_pixbuf_get_width (pixbuf);
1011 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1012 g_object_unref (pixbuf);
1013 pixbuf = new_pixbuf;
1017 *stream_size = size;
1023 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1025 ModestMsgEditWindowPrivate *priv;
1028 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1030 for (iter = tny_list_create_iterator (attachments);
1031 !tny_iterator_is_done (iter);
1032 tny_iterator_next (iter)) {
1033 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1034 const gchar *cid = tny_mime_part_get_content_id (part);
1035 const gchar *mime_type = tny_mime_part_get_content_type (part);
1036 if ((cid != NULL)&&(mime_type != NULL)) {
1037 guint64 stream_size;
1038 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1039 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
1042 g_object_unref (stream);
1044 if (pixbuf != NULL) {
1045 priv->images_count ++;
1046 priv->images_size += stream_size;
1047 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1048 g_object_unref (pixbuf);
1051 g_object_unref (part);
1053 g_object_unref (iter);
1057 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1059 TnyMimePart *parent = NULL;
1060 const gchar *content_type = NULL;
1061 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1063 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1065 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1066 parent = g_object_ref (msg);
1067 } else if (content_type && !g_strcasecmp (content_type, "multipart/mixed")) {
1068 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1071 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1072 iter = tny_list_create_iterator (parts);
1073 while (!tny_iterator_is_done (iter)) {
1075 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1076 content_type = tny_mime_part_get_content_type (part);
1077 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1081 g_object_unref (part);
1083 tny_iterator_next (iter);
1085 g_object_unref (iter);
1086 g_object_unref (parts);
1089 if (parent != NULL) {
1090 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1093 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1094 iter = tny_list_create_iterator (parts);
1095 while (!tny_iterator_is_done (iter)) {
1097 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1098 content_type = tny_mime_part_get_content_type (part);
1099 if (content_type && g_str_has_prefix (content_type, "image/")) {
1100 tny_list_prepend (priv->images, (GObject *) part);
1102 g_object_unref (part);
1103 tny_iterator_next (iter);
1105 g_object_unref (iter);
1106 g_object_unref (parts);
1107 g_object_unref (parent);
1112 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1115 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1117 for (iter = tny_list_create_iterator (attachments) ;
1118 !tny_iterator_is_done (iter);
1119 tny_iterator_next (iter)) {
1120 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1121 const gchar *cid = tny_mime_part_get_content_id (part);
1123 char *invalid = NULL;
1124 gint int_cid = strtol (cid, &invalid, 10);
1125 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1126 priv->next_cid = int_cid + 1;
1129 g_object_unref (part);
1131 g_object_unref (iter);
1135 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1138 gchar *to, *cc, *bcc, *subject;
1140 ModestMsgEditWindowPrivate *priv;
1141 ModestWindowPrivate *parent_priv;
1143 TnyHeaderFlags priority_flags;
1144 TnyFolder *msg_folder;
1145 gboolean is_html = FALSE;
1146 gboolean field_view_set;
1148 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1149 g_return_if_fail (TNY_IS_MSG (msg));
1151 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1152 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1154 header = tny_msg_get_header (msg);
1155 to = tny_header_dup_to (header);
1156 cc = tny_header_dup_cc (header);
1157 bcc = tny_header_dup_bcc (header);
1158 subject = tny_header_dup_subject (header);
1159 priority_flags = tny_header_get_priority (header);
1162 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
1164 field_view_set = TRUE;
1166 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
1167 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1168 gtk_widget_show (priv->cc_caption);
1169 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1170 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1171 gtk_widget_hide (priv->cc_caption);
1172 field_view_set = FALSE;
1174 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button), field_view_set);
1176 field_view_set = TRUE;
1178 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
1179 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1180 gtk_widget_show (priv->bcc_caption);
1181 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1182 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1183 gtk_widget_hide (priv->bcc_caption);
1184 field_view_set = FALSE;
1186 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button), field_view_set);
1190 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1191 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1194 update_window_title (self);
1196 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1197 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1199 if ((body == NULL)||(body[0] == '\0')) {
1201 body = modest_text_utils_convert_to_html ("");
1204 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1205 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1208 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1211 /* Add attachments to the view */
1212 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1213 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1214 if (tny_list_get_length (priv->attachments) == 0) {
1215 gtk_widget_hide (priv->attachments_caption);
1217 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1218 gtk_widget_show_all (priv->attachments_caption);
1220 get_related_images (self, msg);
1221 update_next_cid (self, priv->attachments);
1222 update_next_cid (self, priv->images);
1223 replace_with_images (self, priv->images);
1225 if (preserve_is_rich && !is_html) {
1226 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1227 /* Get the default format required from configuration */
1228 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1229 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1232 /* Set the default focus depending on having already a To: field or not */
1233 if ((!to)||(*to == '\0')) {
1234 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1236 gtk_widget_grab_focus (priv->msg_body);
1239 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1241 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1242 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1244 modest_msg_edit_window_set_modified (self, FALSE);
1246 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1247 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1248 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1249 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1251 if (priv->msg_uid) {
1252 g_free (priv->msg_uid);
1253 priv->msg_uid = NULL;
1256 /* we should set a reference to the incoming message if it is a draft */
1257 msg_folder = tny_msg_get_folder (msg);
1259 if (modest_tny_folder_is_local_folder (msg_folder)) {
1260 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1261 if (type == TNY_FOLDER_TYPE_INVALID)
1262 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1264 if (type == TNY_FOLDER_TYPE_DRAFTS)
1265 priv->draft_msg = g_object_ref(msg);
1266 if (type == TNY_FOLDER_TYPE_OUTBOX)
1267 priv->outbox_msg = g_object_ref(msg);
1268 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1270 g_object_unref (msg_folder);
1280 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
1283 GList *item_children, *node;
1284 GtkWidget *bin_child;
1286 bin_child = gtk_bin_get_child (GTK_BIN(item));
1288 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
1290 for (node = item_children; node != NULL; node = g_list_next (node)) {
1291 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
1292 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
1295 g_list_free (item_children);
1299 menu_tool_button_dont_expand (GtkMenuToolButton *item)
1302 GList *item_children, *node;
1304 box = gtk_bin_get_child (GTK_BIN (item));
1305 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
1306 item_children = gtk_container_get_children (GTK_CONTAINER (box));
1308 for (node = item_children; node != NULL; node = g_list_next (node)) {
1309 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
1310 if (GTK_IS_TOGGLE_BUTTON (node->data))
1311 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
1312 else if (GTK_IS_BUTTON (node->data))
1313 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
1315 g_list_free (item_children);
1320 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1322 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1323 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1324 GtkWidget *placeholder;
1325 GtkWidget *tool_item;
1330 GtkWidget *sizes_menu;
1331 GtkWidget *fonts_menu;
1332 GSList *radio_group = NULL;
1333 GSList *node = NULL;
1337 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1338 gtk_toolbar_set_show_arrow (GTK_TOOLBAR (parent_priv->toolbar), FALSE);
1339 gtk_toolbar_set_icon_size (GTK_TOOLBAR (parent_priv->toolbar), HILDON_ICON_SIZE_FINGER);
1340 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1342 /* Font color placeholder */
1343 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1344 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1347 priv->font_color_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1348 priv->font_color_button = hildon_color_button_new ();
1349 gtk_widget_set_size_request (priv->font_color_button, -1, 48);
1350 GTK_WIDGET_UNSET_FLAGS (priv->font_color_toolitem, GTK_CAN_FOCUS);
1351 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1352 gtk_container_add (GTK_CONTAINER (priv->font_color_toolitem), priv->font_color_button);
1353 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1354 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1355 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->font_color_toolitem), insert_index);
1356 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1358 G_CALLBACK (modest_msg_edit_window_color_button_change),
1361 /* Font size and face placeholder */
1362 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1363 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1365 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1366 priv->size_tool_button_label = gtk_label_new (NULL);
1367 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1368 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1369 size_text,"</span>", NULL);
1370 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1372 hildon_helper_set_logical_font (priv->size_tool_button_label, "LargeSystemFont");
1373 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
1374 sizes_menu = gtk_menu_new ();
1375 priv->size_items_group = NULL;
1377 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1378 GtkWidget *size_menu_item;
1380 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1381 size_menu_item = gtk_radio_menu_item_new_with_label (radio_group, size_text);
1382 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (size_menu_item));
1383 gtk_menu_shell_append (GTK_MENU_SHELL (sizes_menu), size_menu_item);
1384 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (size_menu_item), (wp_font_size[size_index] == 12));
1385 gtk_widget_show (size_menu_item);
1387 priv->size_items_group = g_slist_prepend (priv->size_items_group, size_menu_item);
1391 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1392 GtkWidget *item = (GtkWidget *) node->data;
1393 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_size_change),
1397 priv->size_items_group = g_slist_reverse (priv->size_items_group);
1398 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), sizes_menu);
1399 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1400 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1401 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), FALSE);
1402 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), FALSE);
1403 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1404 priv->font_size_toolitem = tool_item;
1407 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1408 priv->font_tool_button_label = gtk_label_new (NULL);
1409 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1410 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1412 hildon_helper_set_logical_font (priv->font_tool_button_label, "LargeSystemFont");
1413 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
1414 fonts_menu = gtk_menu_new ();
1415 priv->font_items_group = NULL;
1417 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1418 GtkWidget *font_menu_item;
1419 GtkWidget *child_label;
1421 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
1422 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
1423 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
1424 wp_get_font_name (font_index), "</span>", NULL);
1425 gtk_label_set_markup (GTK_LABEL (child_label), markup);
1428 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
1429 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
1430 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
1431 gtk_widget_show (font_menu_item);
1433 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
1436 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1437 GtkWidget *item = (GtkWidget *) node->data;
1438 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
1441 priv->font_items_group = g_slist_reverse (priv->font_items_group);
1442 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
1443 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1444 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1445 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), FALSE);
1446 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), FALSE);
1447 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1448 priv->font_face_toolitem = tool_item;
1450 /* Set expand and homogeneous for remaining items */
1451 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
1452 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1453 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1454 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1455 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1456 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1457 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1458 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1459 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1461 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1462 will not show the tool items added to the placeholders) */
1463 gtk_widget_show_all (parent_priv->toolbar);
1465 /* Set the no show all *after* showing all items. We do not
1466 want the toolbar to be shown with a show all because it
1467 could go agains the gconf setting regarding showing or not
1468 the toolbar of the editor window */
1469 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1475 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, gboolean preserve_is_rich)
1478 ModestWindowPrivate *parent_priv;
1479 ModestMsgEditWindowPrivate *priv;
1480 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1481 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1482 ModestWindowMgr *mgr = NULL;
1484 g_return_val_if_fail (msg, NULL);
1485 g_return_val_if_fail (account_name, NULL);
1487 mgr = modest_runtime_get_window_mgr ();
1489 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1491 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1492 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1494 /* Menubar. Update the state of some toggles */
1495 priv->from_field_protos = get_transports ();
1496 modest_selector_picker_set_pair_list (MODEST_SELECTOR_PICKER (priv->from_field), priv->from_field_protos);
1497 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1498 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1500 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1501 hildon_touch_selector_get_current_text
1502 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1503 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1504 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1507 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1509 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1511 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1513 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1515 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1516 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1517 /* Add common dimming rules */
1518 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1519 modest_msg_edit_window_toolbar_dimming_entries,
1520 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1521 MODEST_WINDOW (obj));
1522 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_toolitem,
1523 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1524 MODEST_WINDOW (obj));
1525 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1526 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1527 MODEST_WINDOW (obj));
1528 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1529 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1530 MODEST_WINDOW (obj));
1531 /* Insert dimming rules group for this window */
1532 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1533 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1535 /* Setup app menu */
1536 setup_menu (MODEST_MSG_EDIT_WINDOW (obj));
1538 /* Checks the dimming rules */
1539 g_object_unref (toolbar_rules_group);
1540 g_object_unref (clipboard_rules_group);
1541 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1543 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1545 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1546 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1547 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1548 priv->update_caption_visibility = TRUE;
1550 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1552 /* Track account-removed signal, this window should be closed
1553 in the case we're creating a mail associated to the account
1555 priv->account_removed_handler_id =
1556 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1558 G_CALLBACK(on_account_removed),
1561 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1563 return (ModestWindow*) obj;
1567 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1569 GString **string_buffer = (GString **) user_data;
1571 *string_buffer = g_string_append (*string_buffer, buffer);
1577 * @result: A new string which should be freed with g_free().
1580 get_formatted_data (ModestMsgEditWindow *edit_window)
1582 ModestMsgEditWindowPrivate *priv;
1583 GString *string_buffer = g_string_new ("");
1585 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1587 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1589 modest_text_utils_hyperlinkify (string_buffer);
1591 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1593 return g_string_free (string_buffer, FALSE);
1598 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1601 const gchar *account_name;
1602 ModestMsgEditWindowPrivate *priv;
1603 TnyIterator *att_iter;
1605 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1607 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1609 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1610 g_return_val_if_fail (account_name, NULL);
1613 /* don't free these (except from) */
1614 data = g_slice_new0 (MsgData);
1615 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1617 data->account_name = g_strdup (account_name);
1618 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1619 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1620 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1621 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1622 if (priv->draft_msg) {
1623 data->draft_msg = g_object_ref (priv->draft_msg);
1624 } else if (priv->outbox_msg) {
1625 data->draft_msg = g_object_ref (priv->outbox_msg);
1627 data->draft_msg = NULL;
1630 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1632 gtk_text_buffer_get_bounds (buf, &b, &e);
1633 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1635 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1636 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1638 data->html_body = NULL;
1640 /* deep-copy the data */
1641 att_iter = tny_list_create_iterator (priv->attachments);
1642 data->attachments = NULL;
1643 while (!tny_iterator_is_done (att_iter)) {
1644 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1645 if (!(TNY_IS_MIME_PART(part))) {
1646 g_warning ("strange data in attachment list");
1647 g_object_unref (part);
1648 tny_iterator_next (att_iter);
1651 data->attachments = g_list_append (data->attachments,
1653 tny_iterator_next (att_iter);
1655 g_object_unref (att_iter);
1657 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1658 att_iter = tny_list_create_iterator (priv->images);
1659 data->images = NULL;
1660 while (!tny_iterator_is_done (att_iter)) {
1661 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1663 if (!(TNY_IS_MIME_PART(part))) {
1664 g_warning ("strange data in attachment list");
1665 g_object_unref (part);
1666 tny_iterator_next (att_iter);
1669 cid = tny_mime_part_get_content_id (part);
1671 gchar *image_tag_id;
1672 GtkTextTag *image_tag;
1674 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1675 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1676 g_free (image_tag_id);
1678 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1680 ((gtk_text_iter_has_tag (&iter, image_tag))||
1681 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1682 data->images = g_list_append (data->images,
1683 g_object_ref (part));
1685 g_object_unref (part);
1686 tny_iterator_next (att_iter);
1688 g_object_unref (att_iter);
1690 data->priority_flags = priv->priority_flags;
1697 unref_gobject (GObject *obj, gpointer data)
1699 if (!G_IS_OBJECT(obj))
1701 g_object_unref (obj);
1705 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1708 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1716 g_free (data->from);
1717 g_free (data->subject);
1718 g_free (data->plain_body);
1719 g_free (data->html_body);
1720 g_free (data->account_name);
1722 if (data->draft_msg != NULL) {
1723 g_object_unref (data->draft_msg);
1724 data->draft_msg = NULL;
1727 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1728 g_list_free (data->attachments);
1729 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1730 g_list_free (data->images);
1732 g_slice_free (MsgData, data);
1736 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1738 guint64 *parts_size)
1740 ModestMsgEditWindowPrivate *priv;
1742 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1744 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1746 /* TODO: add images */
1747 *parts_size += priv->images_size;
1748 *parts_count += priv->images_count;
1753 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1756 ModestMsgEditWindowPrivate *priv = NULL;
1757 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1759 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1761 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1763 return MODEST_MSG_EDIT_FORMAT_HTML;
1765 return MODEST_MSG_EDIT_FORMAT_TEXT;
1769 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1770 ModestMsgEditFormat format)
1772 ModestMsgEditWindowPrivate *priv;
1774 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1775 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1778 case MODEST_MSG_EDIT_FORMAT_HTML:
1779 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1781 case MODEST_MSG_EDIT_FORMAT_TEXT:
1782 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1785 g_return_if_reached ();
1789 ModestMsgEditFormatState *
1790 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1792 ModestMsgEditFormatState *format_state = NULL;
1793 ModestMsgEditWindowPrivate *priv;
1794 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1796 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1797 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1799 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1801 format_state = g_new0 (ModestMsgEditFormatState, 1);
1802 format_state->bold = buffer_format->bold&0x1;
1803 format_state->italics = buffer_format->italic&0x1;
1804 format_state->bullet = buffer_format->bullet&0x1;
1805 format_state->color = buffer_format->color;
1806 format_state->font_size = buffer_format->font_size;
1807 format_state->font_family = wp_get_font_name (buffer_format->font);
1808 format_state->justification = buffer_format->justification;
1809 g_free (buffer_format);
1811 return format_state;
1816 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1817 const ModestMsgEditFormatState *format_state)
1819 ModestMsgEditWindowPrivate *priv;
1820 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1821 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1822 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1823 g_return_if_fail (format_state != NULL);
1825 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1826 gtk_widget_grab_focus (priv->msg_body);
1827 buffer_format->bold = (format_state->bold != FALSE);
1828 buffer_format->italic = (format_state->italics != FALSE);
1829 buffer_format->color = format_state->color;
1830 buffer_format->font_size = format_state->font_size;
1831 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1832 buffer_format->justification = format_state->justification;
1833 buffer_format->bullet = format_state->bullet;
1835 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1837 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1838 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1839 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1840 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1841 buffer_format->cs.font = (buffer_format->font != current_format->font);
1842 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1843 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1845 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1846 if (buffer_format->cs.bold) {
1847 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
1848 GINT_TO_POINTER (buffer_format->bold&0x1));
1850 if (buffer_format->cs.italic) {
1851 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
1852 GINT_TO_POINTER (buffer_format->italic&0x1));
1854 if (buffer_format->cs.color) {
1855 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1856 GINT_TO_POINTER (&(buffer_format->color)));
1858 if (buffer_format->cs.font_size) {
1859 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1860 GINT_TO_POINTER (buffer_format->font_size));
1862 if (buffer_format->cs.justification) {
1863 switch (buffer_format->justification) {
1864 case GTK_JUSTIFY_LEFT:
1865 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
1866 GINT_TO_POINTER(TRUE));
1868 case GTK_JUSTIFY_CENTER:
1869 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
1870 GINT_TO_POINTER(TRUE));
1872 case GTK_JUSTIFY_RIGHT:
1873 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
1874 GINT_TO_POINTER(TRUE));
1881 if (buffer_format->cs.font) {
1882 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1883 GINT_TO_POINTER (buffer_format->font));
1885 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1886 if (buffer_format->cs.bullet) {
1887 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
1888 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
1890 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1892 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
1894 g_free (buffer_format);
1895 g_free (current_format);
1897 /* Check dimming rules */
1898 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1899 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1903 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1905 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1907 ModestWindowPrivate *parent_priv;
1908 ModestMsgEditWindowPrivate *priv;
1909 GtkWidget *new_size_menuitem;
1910 GtkWidget *new_font_menuitem;
1912 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1913 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1915 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1916 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu");
1917 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1918 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1920 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatPlainTextMenu");
1921 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1922 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1925 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1927 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1928 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1930 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1931 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1933 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
1934 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
1937 switch (buffer_format->justification)
1939 case GTK_JUSTIFY_LEFT:
1940 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
1942 case GTK_JUSTIFY_CENTER:
1943 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
1945 case GTK_JUSTIFY_RIGHT:
1946 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
1953 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
1955 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1956 G_CALLBACK (modest_msg_edit_window_color_button_change),
1958 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1959 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1960 G_CALLBACK (modest_msg_edit_window_color_button_change),
1963 new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group,
1964 buffer_format->font_size))->data);
1965 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1969 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1970 markup = g_strconcat ("<span font_family='Sans'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1971 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1973 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1974 G_CALLBACK (modest_msg_edit_window_size_change),
1976 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
1977 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
1978 G_CALLBACK (modest_msg_edit_window_size_change),
1982 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
1983 buffer_format->font))->data);
1984 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
1988 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
1989 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1990 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1992 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
1993 G_CALLBACK (modest_msg_edit_window_font_change),
1995 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
1996 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
1997 G_CALLBACK (modest_msg_edit_window_font_change),
2001 g_free (buffer_format);
2005 #ifdef MODEST_HILDON_VERSION_0
2007 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2010 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2011 ModestMsgEditWindowPrivate *priv;
2012 GtkWidget *dialog = NULL;
2014 GdkColor *new_color = NULL;
2016 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2017 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2019 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2020 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
2021 g_free (buffer_format);
2023 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2024 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2025 if (new_color != NULL) {
2026 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2027 (gpointer) new_color);
2030 gtk_widget_destroy (dialog);
2035 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2038 ModestMsgEditWindowPrivate *priv;
2039 GtkWidget *dialog = NULL;
2041 GdkColor *old_color = NULL;
2042 const GdkColor *new_color = NULL;
2044 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2045 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2047 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2048 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2050 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2051 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2052 if (new_color != NULL)
2053 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2055 gtk_widget_destroy (dialog);
2061 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2064 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2065 ModestMsgEditWindowPrivate *priv;
2066 GtkWidget *dialog = NULL;
2068 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2069 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2071 dialog = hildon_color_chooser_new ();
2072 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2073 g_free (buffer_format);
2075 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2077 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2078 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2081 gtk_widget_destroy (dialog);
2086 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2089 ModestMsgEditWindowPrivate *priv;
2090 GtkWidget *dialog = NULL;
2091 GdkColor *old_color = NULL;
2093 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2094 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2096 dialog = hildon_color_chooser_new ();
2097 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2099 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2101 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2102 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2104 gtk_widget_destroy (dialog);
2107 #endif /*!MODEST_HILDON_VERSION_0*/
2112 create_stream_for_uri (const gchar* uri)
2117 TnyStream *result = NULL;
2119 GnomeVFSHandle *handle = NULL;
2120 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2121 if (test == GNOME_VFS_OK) {
2122 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2123 /* Streams over OBEX (Bluetooth) are not seekable but
2124 * we expect them to be (we might need to read them
2125 * several times). So if this is a Bluetooth URI just
2126 * read the whole file into memory (this is not a fast
2127 * protocol so we can assume that these files are not
2128 * going to be very big) */
2129 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2130 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2131 TnyStream *memstream = tny_camel_mem_stream_new ();
2132 tny_stream_write_to_stream (vfssstream, memstream);
2133 g_object_unref (vfssstream);
2136 result = vfssstream;
2144 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2147 ModestMsgEditWindowPrivate *priv;
2148 GtkWidget *dialog = NULL;
2150 GSList *uris = NULL;
2151 GSList *uri_node = NULL;
2153 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2155 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2156 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2157 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2159 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2161 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2162 GTK_WINDOW (dialog), GTK_WINDOW (window));
2164 response = gtk_dialog_run (GTK_DIALOG (dialog));
2166 case GTK_RESPONSE_OK:
2167 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2172 gtk_widget_destroy (dialog);
2174 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2176 GnomeVFSHandle *handle = NULL;
2177 GnomeVFSResult result;
2178 GtkTextIter position;
2179 GtkTextMark *insert_mark;
2181 uri = (const gchar *) uri_node->data;
2182 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2183 if (result == GNOME_VFS_OK) {
2185 GnomeVFSFileInfo *info;
2186 gchar *filename, *basename, *escaped_filename;
2187 TnyMimePart *mime_part;
2189 const gchar *mime_type = NULL;
2190 GnomeVFSURI *vfs_uri;
2191 guint64 stream_size;
2193 gnome_vfs_close (handle);
2194 vfs_uri = gnome_vfs_uri_new (uri);
2196 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2197 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2198 g_free (escaped_filename);
2199 gnome_vfs_uri_unref (vfs_uri);
2200 info = gnome_vfs_file_info_new ();
2202 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2203 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2205 mime_type = gnome_vfs_file_info_get_mime_type (info);
2207 mime_part = tny_platform_factory_new_mime_part
2208 (modest_runtime_get_platform_factory ());
2210 TnyStream *stream = create_stream_for_uri (uri);
2212 if (stream == NULL) {
2214 modest_platform_information_banner (NULL, NULL,
2215 _FM("sfil_ib_opening_not_allowed"));
2217 g_object_unref (mime_part);
2218 gnome_vfs_file_info_unref (info);
2222 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2224 content_id = g_strdup_printf ("%d", priv->next_cid);
2225 tny_mime_part_set_content_id (mime_part, content_id);
2226 g_free (content_id);
2229 basename = g_path_get_basename (filename);
2230 tny_mime_part_set_filename (mime_part, basename);
2233 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
2235 if (pixbuf != NULL) {
2236 priv->images_size += stream_size;
2237 priv->images_count ++;
2238 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2239 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2240 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
2241 g_object_unref (pixbuf);
2244 tny_list_prepend (priv->images, (GObject *) mime_part);
2245 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2247 g_object_unref (mime_part);
2248 gnome_vfs_file_info_unref (info);
2257 on_attach_file_response (GtkDialog *dialog,
2261 GSList *uris = NULL;
2263 GnomeVFSFileSize total_size, allowed_size;
2264 ModestMsgEditWindow *window;
2265 ModestMsgEditWindowPrivate *priv;
2270 case GTK_RESPONSE_OK:
2271 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2277 window = MODEST_MSG_EDIT_WINDOW (user_data);
2278 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2280 /* allowed size is the maximum size - what's already there */
2281 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2282 &att_num, &att_size);
2283 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2286 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2288 const gchar *uri = (const gchar *) uri_node->data;
2291 modest_msg_edit_window_attach_file_one (window, uri, allowed_size);
2293 if (total_size > allowed_size) {
2294 g_warning ("%s: total size: %u",
2295 __FUNCTION__, (unsigned int)total_size);
2298 allowed_size -= total_size;
2300 g_slist_foreach (uris, (GFunc) g_free, NULL);
2301 g_slist_free (uris);
2303 gtk_widget_destroy (GTK_WIDGET (dialog));
2307 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2309 GtkWidget *dialog = NULL;
2310 ModestMsgEditWindowPrivate *priv;
2312 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2314 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2316 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2319 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window),
2320 GTK_FILE_CHOOSER_ACTION_OPEN);
2321 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2322 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2323 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2324 GTK_WINDOW (dialog), GTK_WINDOW (window));
2326 /* Connect to response & show */
2327 g_signal_connect (dialog, "response",
2328 G_CALLBACK (on_attach_file_response), window);
2329 gtk_widget_show (dialog);
2334 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2336 GnomeVFSFileSize allowed_size)
2339 GnomeVFSHandle *handle = NULL;
2340 ModestMsgEditWindowPrivate *priv;
2341 GnomeVFSResult result;
2342 GnomeVFSFileSize size = 0;
2343 g_return_val_if_fail (window, 0);
2344 g_return_val_if_fail (uri, 0);
2346 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2348 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2349 if (result == GNOME_VFS_OK) {
2350 TnyMimePart *mime_part;
2352 const gchar *mime_type = NULL;
2354 gchar *escaped_filename;
2357 GnomeVFSFileInfo *info;
2358 GnomeVFSURI *vfs_uri;
2360 gnome_vfs_close (handle);
2361 vfs_uri = gnome_vfs_uri_new (uri);
2364 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2365 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2366 g_free (escaped_filename);
2367 gnome_vfs_uri_unref (vfs_uri);
2369 info = gnome_vfs_file_info_new ();
2371 if (gnome_vfs_get_file_info (uri,
2373 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2375 mime_type = gnome_vfs_file_info_get_mime_type (info);
2376 mime_part = tny_platform_factory_new_mime_part
2377 (modest_runtime_get_platform_factory ());
2379 /* try to get the attachment's size; this may fail for weird
2380 * file systems, like obex, upnp... */
2381 if (allowed_size != 0 &&
2382 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2384 if (size > allowed_size) {
2385 modest_platform_information_banner (NULL, NULL,
2386 _FM("sfil_ib_opening_not_allowed"));
2390 g_warning ("%s: could not get attachment size", __FUNCTION__);
2392 stream = create_stream_for_uri (uri);
2394 if (stream == NULL) {
2396 modest_platform_information_banner (NULL, NULL, _FM("sfil_ib_opening_not_allowed"));
2398 g_object_unref (mime_part);
2399 gnome_vfs_file_info_unref (info);
2403 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2404 g_object_unref (stream);
2406 content_id = g_strdup_printf ("%d", priv->next_cid);
2407 tny_mime_part_set_content_id (mime_part, content_id);
2408 g_free (content_id);
2411 basename = g_path_get_basename (filename);
2412 tny_mime_part_set_filename (mime_part, basename);
2415 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2416 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2418 info->size == 0, info->size);
2419 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2420 gtk_widget_show_all (priv->attachments_caption);
2421 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2423 g_object_unref (mime_part);
2424 gnome_vfs_file_info_unref (info);
2431 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2434 ModestMsgEditWindowPrivate *priv;
2437 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2438 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2440 if (att_list == NULL) {
2441 att_list = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2442 if (!modest_maemo_utils_select_attachments (GTK_WINDOW (window), att_list)) {
2443 g_object_unref (att_list);
2448 g_object_ref (att_list);
2451 if (tny_list_get_length (att_list) == 0) {
2452 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2454 gboolean dialog_response;
2455 gchar *message = NULL;
2456 gchar *filename = NULL;
2458 if (tny_list_get_length (att_list) == 1) {
2460 iter = tny_list_create_iterator (att_list);
2461 part = (TnyMimePart *) tny_iterator_get_current (iter);
2462 g_object_unref (iter);
2463 if (TNY_IS_MSG (part)) {
2464 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2466 filename = tny_header_dup_subject (header);
2467 g_object_unref (header);
2469 if (filename == NULL) {
2470 filename = g_strdup (_("mail_va_no_subject"));
2473 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2475 g_object_unref (part);
2477 filename = g_strdup ("");
2479 message = g_strdup_printf (ngettext("emev_nc_delete_attachment",
2480 "emev_nc_delete_attachments",
2481 tny_list_get_length (att_list)), filename);
2484 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
2488 if (dialog_response != GTK_RESPONSE_OK) {
2489 g_object_unref (att_list);
2493 for (iter = tny_list_create_iterator (att_list);
2494 !tny_iterator_is_done (iter);
2495 tny_iterator_next (iter)) {
2496 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2497 const gchar *att_id;
2498 tny_list_remove (priv->attachments, (GObject *) mime_part);
2500 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2502 if (tny_list_get_length (priv->attachments) == 0)
2503 gtk_widget_hide (priv->attachments_caption);
2504 att_id = tny_mime_part_get_content_id (mime_part);
2506 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2508 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2509 g_object_unref (mime_part);
2511 g_object_unref (iter);
2514 g_object_unref (att_list);
2516 /* if the last attachment has been removed, focus the Subject: field */
2517 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2518 gtk_widget_grab_focus (priv->subject_field);
2522 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2525 ModestMsgEditWindowPrivate *priv;
2526 GdkColor *new_color;
2527 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2529 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2530 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2533 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2535 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2537 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2539 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2544 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
2547 ModestMsgEditWindowPrivate *priv;
2548 gint new_size_index;
2549 ModestMsgEditWindow *window;
2552 window = MODEST_MSG_EDIT_WINDOW (userdata);
2553 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2554 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2556 if (gtk_check_menu_item_get_active (menu_item)) {
2558 WPTextBufferFormat format;
2560 memset (&format, 0, sizeof (format));
2561 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2563 label = gtk_bin_get_child (GTK_BIN (menu_item));
2565 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
2566 format.cs.font_size = TRUE;
2567 format.cs.text_position = TRUE;
2568 format.cs.font = TRUE;
2569 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
2570 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2572 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2573 GINT_TO_POINTER (wp_get_font_size_index (new_size_index, 12))))
2574 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2576 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2577 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
2578 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2584 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
2587 ModestMsgEditWindowPrivate *priv;
2588 gint new_font_index;
2589 ModestMsgEditWindow *window;
2592 window = MODEST_MSG_EDIT_WINDOW (userdata);
2593 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2594 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2596 if (gtk_check_menu_item_get_active (menu_item)) {
2599 label = gtk_bin_get_child (GTK_BIN (menu_item));
2601 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
2603 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2604 GINT_TO_POINTER(new_font_index)))
2605 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2607 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2608 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2609 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2615 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2618 ModestMsgEditWindowPrivate *priv = NULL;
2619 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2621 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2622 if (!priv->update_caption_visibility)
2625 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2627 gtk_widget_show (priv->cc_caption);
2629 gtk_widget_hide (priv->cc_caption);
2631 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2635 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2638 ModestMsgEditWindowPrivate *priv = NULL;
2639 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2641 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2642 if (!priv->update_caption_visibility)
2645 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2647 gtk_widget_show (priv->bcc_caption);
2649 gtk_widget_hide (priv->bcc_caption);
2651 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2655 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2656 ModestRecptEditor *editor)
2658 ModestMsgEditWindowPrivate *priv;
2660 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2661 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2663 /* we check for low-mem; in that case, show a warning, and don't allow
2664 * for the addressbook
2666 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2669 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2671 if (editor == NULL) {
2672 GtkWidget *view_focus;
2673 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2675 /* This code should be kept in sync with ModestRecptEditor. The
2676 textview inside the recpt editor is the one that really gets the
2677 focus. As it's inside a scrolled window, and this one inside the
2678 hbox recpt editor inherits from, we'll need to go up in the
2679 hierarchy to know if the text view is part of the recpt editor
2680 or if it's a different text entry */
2682 if (gtk_widget_get_parent (view_focus)) {
2683 GtkWidget *first_parent;
2685 first_parent = gtk_widget_get_parent (view_focus);
2686 if (gtk_widget_get_parent (first_parent) &&
2687 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2688 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2693 editor = MODEST_RECPT_EDITOR (priv->to_field);
2697 modest_address_book_select_addresses (editor);
2702 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2704 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2706 modest_msg_edit_window_open_addressbook (window, NULL);
2710 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2711 gboolean show_toolbar)
2713 ModestWindowPrivate *parent_priv;
2715 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2716 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2718 /* We can not just use the code of
2719 modest_msg_edit_window_setup_toolbar because it has a
2720 mixture of both initialization and creation code. */
2722 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2724 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2728 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2729 TnyHeaderFlags priority_flags)
2731 ModestMsgEditWindowPrivate *priv;
2732 ModestWindowPrivate *parent_priv;
2734 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2736 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2737 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2739 if (priv->priority_flags != priority_flags) {
2740 GtkAction *priority_action = NULL;
2742 priv->priority_flags = priority_flags;
2744 switch (priority_flags) {
2745 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2746 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2747 MODEST_HEADER_ICON_HIGH,
2748 HILDON_ICON_SIZE_XSMALL);
2749 gtk_widget_show (priv->priority_icon);
2750 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2751 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2753 case TNY_HEADER_FLAG_LOW_PRIORITY:
2754 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2755 MODEST_HEADER_ICON_LOW,
2756 HILDON_ICON_SIZE_XSMALL);
2757 gtk_widget_show (priv->priority_icon);
2758 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2759 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2762 gtk_widget_hide (priv->priority_icon);
2763 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2764 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2767 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2768 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2773 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2776 ModestMsgEditWindowPrivate *priv;
2777 ModestWindowPrivate *parent_priv;
2778 gint current_format;
2780 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2782 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2783 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2785 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2786 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2788 if (current_format != file_format) {
2789 switch (file_format) {
2790 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2791 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2792 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
2794 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2798 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2799 response = gtk_dialog_run (GTK_DIALOG (dialog));
2800 gtk_widget_destroy (dialog);
2801 if (response == GTK_RESPONSE_OK) {
2802 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2804 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
2805 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
2810 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2811 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2812 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2817 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2820 ModestMsgEditWindowPrivate *priv;
2821 WPTextBufferFormat oldfmt, fmt;
2822 gint old_position = 0;
2826 GdkColor *color = NULL;
2827 gboolean bold, bold_set, italic, italic_set;
2828 gboolean underline, underline_set;
2829 gboolean strikethrough, strikethrough_set;
2830 gboolean position_set;
2831 gboolean font_size_set, font_set, color_set;
2834 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2835 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2837 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2838 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
2839 GTK_WINDOW(dialog), GTK_WINDOW (window));
2841 /* First we get the currently selected font information */
2842 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2844 switch (oldfmt.text_position) {
2845 case TEXT_POSITION_NORMAL:
2848 case TEXT_POSITION_SUPERSCRIPT:
2856 g_object_set (G_OBJECT (dialog),
2857 "bold", oldfmt.bold != FALSE,
2858 "bold-set", !oldfmt.cs.bold,
2859 "underline", oldfmt.underline != FALSE,
2860 "underline-set", !oldfmt.cs.underline,
2861 "italic", oldfmt.italic != FALSE,
2862 "italic-set", !oldfmt.cs.italic,
2863 "strikethrough", oldfmt.strikethrough != FALSE,
2864 "strikethrough-set", !oldfmt.cs.strikethrough,
2865 "color", &oldfmt.color,
2866 "color-set", !oldfmt.cs.color,
2867 "size", wp_font_size[oldfmt.font_size],
2868 "size-set", !oldfmt.cs.font_size,
2869 "position", old_position,
2870 "position-set", !oldfmt.cs.text_position,
2871 "family", wp_get_font_name (oldfmt.font),
2872 "family-set", !oldfmt.cs.font,
2875 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2876 GTK_WINDOW (dialog), GTK_WINDOW (window));
2877 gtk_widget_show_all (dialog);
2878 priv->font_dialog = dialog;
2879 response = gtk_dialog_run (GTK_DIALOG (dialog));
2880 priv->font_dialog = NULL;
2881 if (response == GTK_RESPONSE_OK) {
2883 g_object_get( dialog,
2885 "bold-set", &bold_set,
2886 "underline", &underline,
2887 "underline-set", &underline_set,
2889 "italic-set", &italic_set,
2890 "strikethrough", &strikethrough,
2891 "strikethrough-set", &strikethrough_set,
2893 "color-set", &color_set,
2895 "size-set", &font_size_set,
2896 "family", &font_name,
2897 "family-set", &font_set,
2898 "position", &position,
2899 "position-set", &position_set,
2904 if (response == GTK_RESPONSE_OK) {
2905 memset(&fmt, 0, sizeof(fmt));
2911 fmt.italic = italic;
2912 fmt.cs.italic = TRUE;
2914 if (underline_set) {
2915 fmt.underline = underline;
2916 fmt.cs.underline = TRUE;
2918 if (strikethrough_set) {
2919 fmt.strikethrough = strikethrough;
2920 fmt.cs.strikethrough = TRUE;
2925 ? TEXT_POSITION_NORMAL
2926 : ( ( position == 1 )
2927 ? TEXT_POSITION_SUPERSCRIPT
2928 : TEXT_POSITION_SUBSCRIPT );
2929 fmt.cs.text_position = TRUE;
2930 fmt.font_size = oldfmt.font_size;
2934 fmt.cs.color = TRUE;
2937 fmt.font = wp_get_font_index(font_name,
2942 if (font_size_set) {
2943 fmt.cs.font_size = TRUE;
2944 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
2946 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2947 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2949 gtk_widget_destroy (dialog);
2951 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2955 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2957 ModestMsgEditWindowPrivate *priv;
2959 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2960 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2962 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2964 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2965 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2969 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
2971 ModestMsgEditWindowPrivate *priv;
2973 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2974 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2976 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
2978 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2979 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2984 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
2986 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2988 priv->can_undo = can_undo;
2992 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
2994 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2996 priv->can_redo = can_redo;
3000 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3002 ModestMsgEditWindowPrivate *priv;
3003 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3004 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3006 return priv->can_undo;
3010 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3012 ModestMsgEditWindowPrivate *priv;
3013 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3014 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3016 return priv->can_redo;
3021 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3024 GtkTextIter match_start, match_end;
3026 if (image_id == NULL)
3029 gtk_text_buffer_get_start_iter (buffer, &iter);
3031 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3032 GSList *tags = gtk_text_iter_get_tags (&match_start);
3034 for (node = tags; node != NULL; node = g_slist_next (node)) {
3035 GtkTextTag *tag = (GtkTextTag *) node->data;
3036 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3037 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3038 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3040 offset = gtk_text_iter_get_offset (&match_start);
3041 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3042 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3046 gtk_text_iter_forward_char (&iter);
3051 message_is_empty (ModestMsgEditWindow *window)
3053 ModestMsgEditWindowPrivate *priv = NULL;
3055 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3056 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3058 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3059 * so we can ignore markup.
3061 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3064 count = gtk_text_buffer_get_char_count (buf);
3070 msg_body_focus (GtkWidget *focus,
3071 GdkEventFocus *event,
3075 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3076 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3077 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3082 recpt_field_changed (GtkTextBuffer *buffer,
3083 ModestMsgEditWindow *editor)
3085 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3086 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3090 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3092 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3093 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3097 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3100 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3101 GtkTextBuffer *buffer;
3103 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3104 gtk_text_buffer_set_modified (buffer, modified);
3105 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3106 gtk_text_buffer_set_modified (buffer, modified);
3107 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3108 gtk_text_buffer_set_modified (buffer, modified);
3109 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3113 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3115 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3116 const char *account_name;
3117 GtkTextBuffer *buffer;
3119 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3120 if (gtk_text_buffer_get_modified (buffer))
3122 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3123 if (gtk_text_buffer_get_modified (buffer))
3125 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3126 if (gtk_text_buffer_get_modified (buffer))
3128 if (gtk_text_buffer_get_modified (priv->text_buffer))
3130 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3131 if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3142 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3144 ModestMsgEditWindowPrivate *priv = NULL;
3146 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3147 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3149 /* check if there's no recipient added */
3150 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3151 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3152 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3153 /* no recipient contents, then select contacts */
3154 modest_msg_edit_window_open_addressbook (window, NULL);
3158 g_object_ref (window);
3159 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3160 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3161 g_object_unref (window);
3164 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3165 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3166 g_object_unref (window);
3169 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3170 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3171 g_object_unref (window);
3175 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3176 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3177 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3178 g_object_unref (window);
3185 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3186 ModestMsgEditWindow *window)
3188 modest_msg_edit_window_offer_attach_file (window);
3192 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3194 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3196 return priv->clipboard_text;
3200 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3202 ModestMsgEditWindow *window)
3204 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3205 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3207 if (!GTK_WIDGET_VISIBLE (window))
3210 g_object_ref (window);
3211 text = gtk_clipboard_wait_for_text (selection_clipboard);
3213 if (priv->clipboard_text != NULL) {
3214 g_free (priv->clipboard_text);
3216 priv->clipboard_text = text;
3218 if (GTK_WIDGET_VISIBLE (window)) {
3219 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3221 g_object_unref (window);
3224 static gboolean clipboard_owner_change_idle (gpointer userdata)
3226 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3227 ModestMsgEditWindowPrivate *priv;
3229 gdk_threads_enter ();
3230 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3231 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3233 priv->clipboard_owner_idle = 0;
3234 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3235 gdk_threads_leave ();
3241 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3243 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3244 if (priv->clipboard_owner_idle == 0) {
3245 priv->clipboard_owner_idle = g_idle_add (clipboard_owner_change_idle, window);
3250 subject_field_move_cursor (GtkEntry *entry,
3251 GtkMovementStep step,
3256 if (!GTK_WIDGET_VISIBLE (window))
3259 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3263 update_window_title (ModestMsgEditWindow *window)
3265 ModestMsgEditWindowPrivate *priv = NULL;
3266 const gchar *subject;
3268 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3269 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3270 if (subject == NULL || subject[0] == '\0')
3271 subject = _("mail_va_new_email");
3273 gtk_window_set_title (GTK_WINDOW (window), subject);
3278 subject_field_changed (GtkEditable *editable,
3279 ModestMsgEditWindow *window)
3281 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3282 update_window_title (window);
3283 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3284 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3285 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3289 subject_field_insert_text (GtkEditable *editable,
3291 gint new_text_length,
3293 ModestMsgEditWindow *window)
3295 GString *result = g_string_new ("");
3297 gint result_len = 0;
3298 const gchar *entry_text = NULL;
3301 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3302 old_length = g_utf8_strlen (entry_text, -1);
3304 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3305 gunichar c = g_utf8_get_char_validated (current, 8);
3306 /* Invalid unichar, stop */
3312 result = g_string_append_unichar (result, c);
3316 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3317 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3320 /* Prevent endless recursion */
3321 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3322 g_signal_emit_by_name (editable, "insert-text",
3323 (gpointer) result->str, (gpointer) result->len,
3324 (gpointer) position, (gpointer) window);
3325 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3329 if (result_len + old_length > 1000) {
3330 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3331 _CS("ckdg_ib_maximum_characters_reached"));
3333 g_string_free (result, TRUE);
3337 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3340 ModestMsgEditWindowPrivate *priv = NULL;
3342 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3343 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3345 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3348 gtk_widget_show_all (priv->find_toolbar);
3349 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3351 gtk_widget_hide_all (priv->find_toolbar);
3352 gtk_widget_grab_focus (priv->msg_body);
3357 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3359 GtkTextIter *match_start,
3360 GtkTextIter *match_end)
3362 GtkTextIter end_iter;
3363 gchar *str_casefold;
3366 gchar *range_casefold;
3369 gboolean result = FALSE;
3376 gtk_text_iter_forward_to_end (&end_iter);
3378 str_casefold = g_utf8_casefold (str, -1);
3379 str_chars_n = strlen (str);
3381 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3382 range_casefold = g_utf8_casefold (range_text, -1);
3383 range_chars_n = strlen (range_casefold);
3385 if (range_chars_n < str_chars_n) {
3386 g_free (str_casefold);
3387 g_free (range_text);
3388 g_free (range_casefold);
3392 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3393 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3394 if (!g_utf8_collate (range_subtext, str_casefold)) {
3395 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3397 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3398 match_start, match_end, NULL);
3399 g_free (found_text);
3401 g_free (range_subtext);
3405 g_free (str_casefold);
3406 g_free (range_text);
3407 g_free (range_casefold);
3414 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3415 ModestMsgEditWindow *window)
3417 gchar *current_search = NULL;
3418 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3420 GtkTextIter selection_start, selection_end;
3421 GtkTextIter match_start, match_end;
3422 gboolean continue_search = FALSE;
3424 if (message_is_empty (window)) {
3425 g_free (priv->last_search);
3426 priv->last_search = NULL;
3427 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3431 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3432 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3433 g_free (current_search);
3434 g_free (priv->last_search);
3435 priv->last_search = NULL;
3436 /* Information banner about empty search */
3437 hildon_banner_show_information (NULL, NULL, _CS("ecdg_ib_find_rep_enter_text"));
3441 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3442 continue_search = TRUE;
3444 g_free (priv->last_search);
3445 priv->last_search = g_strdup (current_search);
3448 if (continue_search) {
3449 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3450 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3451 &match_start, &match_end);
3453 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_search_complete"));
3455 GtkTextIter buffer_start;
3456 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3457 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3458 &match_start, &match_end);
3460 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_no_matches"));
3463 /* Mark as selected the string found in search */
3465 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3466 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3467 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3469 g_free (priv->last_search);
3470 priv->last_search = NULL;
3472 g_free (current_search);
3476 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3478 ModestMsgEditWindowPrivate *priv;
3480 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3485 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3488 ModestMsgEditWindowPrivate *priv;
3490 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3495 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3496 ModestMsgEditWindow *window)
3498 modest_msg_edit_window_toggle_find_toolbar (window, FALSE);
3502 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3505 ModestMsgEditWindowPrivate *priv;
3506 TnyHeader *header = NULL;
3508 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3509 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3511 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3512 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3514 if (priv->draft_msg != NULL) {
3515 g_object_unref (priv->draft_msg);
3518 if (draft != NULL) {
3519 g_object_ref (draft);
3520 header = tny_msg_get_header (draft);
3521 if (priv->msg_uid) {
3522 g_free (priv->msg_uid);
3523 priv->msg_uid = NULL;
3525 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3526 if (GTK_WIDGET_REALIZED (window)) {
3527 if (!modest_window_mgr_register_window (mgr, MODEST_WINDOW (window), NULL)) {
3528 gtk_widget_destroy (GTK_WIDGET (window));
3534 priv->draft_msg = draft;
3538 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3539 GtkTextIter *start, GtkTextIter *end,
3542 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3543 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3546 if (tag == NULL) return;
3547 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3548 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3549 replace_with_images (window, priv->images);
3554 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3557 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3559 g_return_if_fail (TNY_IS_MIME_PART (part));
3560 tny_list_prepend (priv->attachments, (GObject *) part);
3561 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3562 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3563 gtk_widget_show_all (priv->attachments_caption);
3564 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3568 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3570 ModestMsgEditWindowPrivate *priv;
3572 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3573 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3575 return priv->msg_uid;
3579 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3580 ModestMsgEditWindowWidgetType widget_type)
3582 ModestMsgEditWindowPrivate *priv;
3584 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3585 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3587 switch (widget_type) {
3588 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3589 return priv->msg_body;
3591 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3592 return priv->to_field;
3594 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3595 return priv->cc_field;
3597 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3598 return priv->bcc_field;
3600 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3601 return priv->subject_field;
3603 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3604 return priv->attachments_view;
3612 remove_tags (WPTextBuffer *buffer)
3614 GtkTextIter start, end;
3616 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3617 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3619 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3623 on_account_removed (TnyAccountStore *account_store,
3624 TnyAccount *account,
3627 /* Do nothing if it's a store account, because we use the
3628 transport to send the messages */
3629 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3630 const gchar *parent_acc = NULL;
3631 const gchar *our_acc = NULL;
3633 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3634 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3635 /* Close this window if I'm showing a message of the removed account */
3636 if (strcmp (parent_acc, our_acc) == 0)
3637 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3641 typedef struct _MessageSettingsHelper {
3642 ModestMsgEditWindow *window;
3643 GSList *priority_group;
3644 GSList *format_group;
3645 GtkToggleButton *current_priority;
3646 GtkToggleButton *current_format;
3647 } MessageSettingsHelper;
3650 on_priority_toggle (GtkToggleButton *button,
3651 MessageSettingsHelper *helper)
3654 ModestMsgEditWindowPrivate *priv;
3656 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3657 if (gtk_toggle_button_get_active (button)) {
3659 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3660 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3661 if ((node_button != button) &&
3662 gtk_toggle_button_get_active (node_button)) {
3663 gtk_toggle_button_set_active (node_button, FALSE);
3666 helper->current_priority = button;
3668 gboolean found = FALSE;
3669 /* If no one is active, activate it again */
3670 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3671 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3672 if (gtk_toggle_button_get_active (node_button)) {
3678 gtk_toggle_button_set_active (button, TRUE);
3684 on_format_toggle (GtkToggleButton *button,
3685 MessageSettingsHelper *helper)
3688 ModestMsgEditWindowPrivate *priv;
3690 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3691 if (gtk_toggle_button_get_active (button)) {
3693 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
3694 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3695 if ((node_button != button) &&
3696 gtk_toggle_button_get_active (node_button)) {
3697 gtk_toggle_button_set_active (node_button, FALSE);
3700 helper->current_format = button;
3702 gboolean found = FALSE;
3703 /* If no one is active, activate it again */
3704 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
3705 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3706 if (gtk_toggle_button_get_active (node_button)) {
3712 gtk_toggle_button_set_active (button, TRUE);
3719 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
3723 GtkWidget *priority_hbox;
3724 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
3725 GtkWidget *captioned;
3726 GtkSizeGroup *title_sizegroup, *value_sizegroup;
3727 GtkWidget *format_hbox;
3728 GtkWidget *html_toggle, *text_toggle;
3729 ModestMsgEditWindowPrivate *priv;
3730 MessageSettingsHelper helper = {0,};
3732 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3733 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3734 helper.window = window;
3735 helper.priority_group = NULL;
3737 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3738 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3740 dialog = gtk_dialog_new_with_buttons (_("mcen_me_message_settings"), NULL,
3741 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
3742 _HL("wdgt_bd_done"), GTK_RESPONSE_ACCEPT, NULL);
3743 vbox = gtk_vbox_new (FALSE, 0);
3744 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), vbox);
3745 gtk_widget_show (vbox);
3747 /* Priority toggles */
3748 priority_hbox = gtk_hbox_new (TRUE, 0);
3749 high_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3750 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
3751 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
3752 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
3753 medium_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3754 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
3755 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
3756 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
3757 low_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3758 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
3759 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
3760 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
3761 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, TRUE, TRUE, 0);
3762 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, TRUE, TRUE, 0);
3763 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, TRUE, TRUE, 0);
3764 gtk_widget_show_all (priority_hbox);
3765 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
3766 _("mcen_me_editor_message_priority"), FALSE, priority_hbox);
3767 gtk_widget_show (captioned);
3768 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
3770 /* format toggles */
3771 format_hbox = gtk_hbox_new (TRUE, 0);
3772 html_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3773 gtk_button_set_label (GTK_BUTTON (html_toggle), _("mcen_me_editor_formatted_text"));
3774 helper.format_group = g_slist_prepend (helper.format_group, html_toggle);
3775 g_object_set_data (G_OBJECT (html_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_HTML));
3776 g_object_set_data (G_OBJECT (html_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_FORMATTED_TEXT));
3777 text_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3778 gtk_button_set_label (GTK_BUTTON (text_toggle), _("mcen_me_editor_plain_text"));
3779 helper.format_group = g_slist_prepend (helper.format_group, text_toggle);
3780 g_object_set_data (G_OBJECT (text_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_TEXT));
3781 g_object_set_data (G_OBJECT (text_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_PLAIN_TEXT));
3782 gtk_box_pack_start (GTK_BOX (format_hbox), html_toggle, TRUE, TRUE, 0);
3783 gtk_box_pack_start (GTK_BOX (format_hbox), text_toggle, TRUE, TRUE, 0);
3784 gtk_widget_show_all (format_hbox);
3785 gtk_widget_show (format_hbox);
3786 gtk_box_pack_start (GTK_BOX (vbox), format_hbox, FALSE, FALSE, 0);
3789 g_object_unref (title_sizegroup);
3790 g_object_unref (value_sizegroup);
3792 /* Set current values */
3793 switch (priv->priority_flags) {
3794 case TNY_HEADER_FLAG_HIGH_PRIORITY:
3795 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (high_toggle), TRUE);
3797 case TNY_HEADER_FLAG_LOW_PRIORITY:
3798 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (low_toggle), TRUE);
3801 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (medium_toggle), TRUE);
3805 switch (modest_msg_edit_window_get_format (window)) {
3806 case MODEST_MSG_EDIT_FORMAT_TEXT:
3807 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_toggle), TRUE);
3809 case MODEST_MSG_EDIT_FORMAT_HTML:
3811 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (html_toggle), TRUE);
3815 /* Signal connects */
3816 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3817 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3818 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3819 g_signal_connect (G_OBJECT (html_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
3820 g_signal_connect (G_OBJECT (text_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
3822 /* Save settings if the user clicked on done */
3823 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
3824 TnyHeaderFlags flags;
3825 ModestMsgEditFormat old_format, new_format;
3827 /* Set priority flags */
3828 flags = (TnyHeaderFlags) g_object_get_data (G_OBJECT (helper.current_priority), "priority");
3829 if (priv->priority_flags != flags)
3830 modest_msg_edit_window_set_priority_flags (window, flags);
3832 /* Set edit format */
3833 old_format = modest_msg_edit_window_get_format (window);
3834 new_format = (ModestMsgEditFormat) g_object_get_data (G_OBJECT (helper.current_format), "format");
3835 if (old_format != new_format) {
3836 gint file_format = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (helper.current_format), "file-format"));
3837 modest_msg_edit_window_set_file_format (window, file_format);
3841 gtk_widget_destroy (dialog);
3842 g_slist_free (helper.priority_group);
3846 on_message_settings (GtkAction *action,
3847 ModestMsgEditWindow *window)
3849 modest_msg_edit_window_show_msg_settings_dialog (window);
3853 on_cc_button_toggled (HildonCheckButton *button,
3854 ModestMsgEditWindow *window)
3856 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
3858 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
3859 hildon_check_button_get_active (button));
3863 on_bcc_button_toggled (HildonCheckButton *button,
3864 ModestMsgEditWindow *window)
3866 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
3868 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
3869 hildon_check_button_get_active (button));
3873 setup_menu (ModestMsgEditWindow *self)
3875 ModestMsgEditWindowPrivate *priv = NULL;
3877 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
3879 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3881 /* Settings menu buttons */
3882 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_checknames"), NULL,
3883 APP_MENU_CALLBACK (modest_ui_actions_on_check_names),
3885 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_undo"), "<Ctrl>z",
3886 APP_MENU_CALLBACK (modest_ui_actions_on_undo),
3887 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_undo));
3889 priv->cc_button = hildon_check_button_new (0);
3890 gtk_button_set_label (GTK_BUTTON (priv->cc_button), _("mcen_me_editor_showcc"));
3891 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button),
3893 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->cc_button),
3895 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
3896 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
3897 priv->bcc_button = hildon_check_button_new (0);
3898 gtk_button_set_label (GTK_BUTTON (priv->bcc_button), _("mcen_me_editor_showbcc"));
3899 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button),
3901 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->bcc_button),
3903 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
3904 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
3906 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_attach_inlineimage"), NULL,
3907 APP_MENU_CALLBACK (modest_ui_actions_on_insert_image),
3908 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_set_style));
3909 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_remove_attachments"), NULL,
3910 APP_MENU_CALLBACK (modest_ui_actions_on_remove_attachments),
3911 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
3912 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_message_settings"), NULL,
3913 APP_MENU_CALLBACK (on_message_settings),
3915 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_viewer_find"), "<Ctrl>f",
3916 APP_MENU_CALLBACK (modest_ui_actions_on_toggle_find_in_page),