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 from_field_changed (HildonPickerButton *button,
176 ModestMsgEditWindow *self);
177 static void DEBUG_BUFFER (WPTextBuffer *buffer)
181 g_message ("BEGIN BUFFER OF SIZE %d", gtk_text_buffer_get_char_count (GTK_TEXT_BUFFER (buffer)));
183 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &iter);
184 while (!gtk_text_iter_is_end (&iter)) {
185 GString *output = g_string_new ("");
186 GSList *toggled_tags;
189 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
190 g_string_append_printf (output, "%d: CLOSED [ ", gtk_text_iter_get_offset (&iter));
191 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
192 GtkTextTag *tag = (GtkTextTag *) node->data;
194 g_object_get (G_OBJECT (tag), "name", &name, NULL);
195 output = g_string_append (output, name);
196 g_string_append (output, " ");
198 output = g_string_append (output, "] OPENED [ ");
199 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
200 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
201 GtkTextTag *tag = (GtkTextTag *) node->data;
203 g_object_get (G_OBJECT (tag), "name", &name, NULL);
204 output = g_string_append (output, name);
205 g_string_append (output, " ");
207 output = g_string_append (output, "]\n");
208 g_message ("%s", output->str);
209 g_string_free (output, TRUE);
210 gtk_text_iter_forward_to_tag_toggle (&iter, NULL);
212 g_message ("END BUFFER");
216 static const GtkActionEntry hildon2_msg_edit_action_entries [] = {
217 { "MessageSettings", NULL, N_("mcen_me_message_settings"), NULL, NULL, G_CALLBACK (on_message_settings)},
221 /* static gboolean */
222 /* on_key_pressed (GtkWidget *self, */
223 /* GdkEventKey *event, */
224 /* gpointer user_data); */
226 /* list my signals */
233 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
234 struct _ModestMsgEditWindowPrivate {
237 GtkWidget *header_box;
239 ModestPairList *from_field_protos;
240 GtkWidget *from_field;
241 gchar *last_from_account;
242 gchar *original_account_name;
246 GtkWidget *bcc_field;
247 GtkWidget *subject_field;
248 GtkWidget *attachments_view;
249 GtkWidget *priority_icon;
250 GtkWidget *add_attachment_button;
252 GtkWidget *cc_caption;
253 GtkWidget *bcc_caption;
254 gboolean update_caption_visibility;
255 GtkWidget *attachments_caption;
257 GtkTextBuffer *text_buffer;
259 GtkWidget *font_size_toolitem;
260 GtkWidget *font_face_toolitem;
261 GtkWidget *font_color_button;
262 GtkWidget *font_color_toolitem;
263 GSList *font_items_group;
264 GtkWidget *font_tool_button_label;
265 GSList *size_items_group;
266 GtkWidget *size_tool_button_label;
268 GtkWidget *find_toolbar;
271 GtkWidget *font_dialog;
274 guint correct_scroll_idle;
275 guint scroll_drag_timeout_id;
279 TnyList *attachments;
284 TnyHeaderFlags priority_flags;
286 gboolean can_undo, can_redo;
287 gulong clipboard_change_handler_id;
288 gulong default_clipboard_change_handler_id;
289 gulong account_removed_handler_id;
290 guint clipboard_owner_idle;
291 gchar *clipboard_text;
300 GtkWidget *cc_button;
301 GtkWidget *bcc_button;
304 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
305 MODEST_TYPE_MSG_EDIT_WINDOW, \
306 ModestMsgEditWindowPrivate))
308 static GtkWindowClass *parent_class = NULL;
310 /* uncomment the following if you have defined any signals */
311 /* static guint signals[LAST_SIGNAL] = {0}; */
314 modest_msg_edit_window_get_type (void)
316 static GType my_type = 0;
318 static const GTypeInfo my_info = {
319 sizeof(ModestMsgEditWindowClass),
320 NULL, /* base init */
321 NULL, /* base finalize */
322 (GClassInitFunc) modest_msg_edit_window_class_init,
323 NULL, /* class finalize */
324 NULL, /* class data */
325 sizeof(ModestMsgEditWindow),
327 (GInstanceInitFunc) modest_msg_edit_window_init,
330 my_type = g_type_register_static (MODEST_TYPE_HILDON2_WINDOW,
331 "ModestMsgEditWindow",
339 save_state (ModestWindow *self)
341 modest_widget_memory_save (modest_runtime_get_conf(),
342 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
347 restore_settings (ModestMsgEditWindow *self)
349 ModestConf *conf = NULL;
351 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
353 conf = modest_runtime_get_conf ();
355 /* Dim at start clipboard actions */
356 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
357 gtk_action_set_sensitive (action, FALSE);
358 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
359 gtk_action_set_sensitive (action, FALSE);
360 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
361 gtk_action_set_sensitive (action, FALSE);
363 modest_widget_memory_restore (conf, G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
368 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
370 GObjectClass *gobject_class;
371 ModestWindowClass *modest_window_class;
372 gobject_class = (GObjectClass*) klass;
373 modest_window_class = (ModestWindowClass*) klass;
375 parent_class = g_type_class_peek_parent (klass);
376 gobject_class->finalize = modest_msg_edit_window_finalize;
378 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
379 modest_window_class->save_state_func = save_state;
380 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
382 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
386 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
388 ModestMsgEditWindowPrivate *priv;
389 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
391 priv->msg_body = NULL;
393 priv->from_field = NULL;
394 priv->to_field = NULL;
395 priv->cc_field = NULL;
396 priv->bcc_field = NULL;
397 priv->subject_field = NULL;
398 priv->attachments = TNY_LIST (tny_simple_list_new ());
399 priv->images = TNY_LIST (tny_simple_list_new ());
400 priv->images_size = 0;
401 priv->images_count = 0;
404 priv->cc_caption = NULL;
405 priv->bcc_caption = NULL;
406 priv->update_caption_visibility = FALSE;
408 priv->priority_flags = 0;
410 priv->find_toolbar = NULL;
411 priv->last_search = NULL;
413 priv->draft_msg = NULL;
414 priv->outbox_msg = NULL;
415 priv->msg_uid = NULL;
417 priv->can_undo = FALSE;
418 priv->can_redo = FALSE;
419 priv->clipboard_change_handler_id = 0;
420 priv->default_clipboard_change_handler_id = 0;
421 priv->account_removed_handler_id = 0;
422 priv->clipboard_owner_idle = 0;
423 priv->clipboard_text = NULL;
426 priv->scroll_drag_timeout_id = 0;
427 priv->correct_scroll_idle = 0;
428 priv->last_upper = 0.0;
430 priv->font_dialog = NULL;
431 priv->app_menu = NULL;
433 if (!is_wp_text_buffer_started) {
434 is_wp_text_buffer_started = TRUE;
435 wp_text_buffer_library_init ();
440 hildon_program_add_window (hildon_program_get_instance(),
446 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
448 static ModestPairList*
449 get_transports (void)
451 GSList *transports = NULL;
453 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
454 GSList *accounts = modest_account_mgr_account_names (account_mgr,
455 TRUE /* only enabled accounts. */);
457 GSList *cursor = accounts;
459 gchar *account_name = cursor->data;
460 gchar *from_string = NULL;
462 from_string = modest_account_mgr_get_from_string (account_mgr,
466 if (from_string && account_name) {
467 gchar *name = account_name;
468 ModestPair *pair = modest_pair_new ((gpointer) name,
469 (gpointer) from_string , TRUE);
470 transports = g_slist_prepend (transports, pair);
473 cursor = cursor->next;
475 g_slist_free (accounts); /* only free the accounts, not the elements,
476 * because they are used in the pairlist */
480 static void window_focus (GtkWindow *window,
484 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
488 scroll_drag_timeout (gpointer userdata)
490 ModestMsgEditWindow *win = (ModestMsgEditWindow *) userdata;
491 ModestMsgEditWindowPrivate *priv;
493 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(win);
495 correct_scroll_without_drag_check (win, TRUE);
497 priv->scroll_drag_timeout_id = 0;
503 correct_scroll_without_drag_check_idle (gpointer userdata)
505 ModestMsgEditWindow *w = (ModestMsgEditWindow *) userdata;
506 ModestMsgEditWindowPrivate *priv;
508 GdkRectangle rectangle;
513 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
515 if (!gtk_widget_is_focus (priv->msg_body))
518 insert = gtk_text_buffer_get_insert (priv->text_buffer);
519 gtk_text_buffer_get_iter_at_mark (priv->text_buffer, &iter, insert);
521 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &iter, &rectangle);
522 offset = priv->msg_body->allocation.y;
524 new_value = (offset + rectangle.y);
526 hildon_pannable_area_jump_to (HILDON_PANNABLE_AREA (priv->pannable), -1, new_value);
528 priv->correct_scroll_idle = 0;
533 correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused)
535 ModestMsgEditWindowPrivate *priv;
537 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
539 if (only_if_focused && !gtk_widget_is_focus (priv->msg_body))
542 if (priv->correct_scroll_idle > 0) {
546 priv->correct_scroll_idle = g_idle_add ((GSourceFunc) correct_scroll_without_drag_check_idle,
551 correct_scroll (ModestMsgEditWindow *w)
553 ModestMsgEditWindowPrivate *priv;
555 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
556 if (gtk_grab_get_current () == priv->msg_body) {
557 if (priv->scroll_drag_timeout_id == 0) {
558 priv->scroll_drag_timeout_id = g_timeout_add (500, (GSourceFunc) scroll_drag_timeout,
564 correct_scroll_without_drag_check (w, TRUE);
568 text_buffer_end_user_action (GtkTextBuffer *buffer,
569 ModestMsgEditWindow *userdata)
572 correct_scroll (userdata);
576 text_buffer_mark_set (GtkTextBuffer *buffer,
579 ModestMsgEditWindow *userdata)
581 gtk_text_buffer_begin_user_action (buffer);
582 gtk_text_buffer_end_user_action (buffer);
586 cut_clipboard_check (GtkTextView *text_view,
589 GtkTextBuffer *buffer;
591 buffer = gtk_text_view_get_buffer (text_view);
592 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
593 g_signal_stop_emission_by_name ((gpointer )text_view, "cut-clipboard");
598 copy_clipboard_check (GtkTextView *text_view,
601 GtkTextBuffer *buffer;
603 buffer = gtk_text_view_get_buffer (text_view);
604 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
605 g_signal_stop_emission_by_name ((gpointer )text_view, "copy-clipboard");
610 attachment_deleted (ModestAttachmentsView *attachments_view,
613 modest_msg_edit_window_remove_attachments (MODEST_MSG_EDIT_WINDOW (user_data),
618 connect_signals (ModestMsgEditWindow *obj)
620 ModestMsgEditWindowPrivate *priv;
622 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
624 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
625 G_CALLBACK (text_buffer_refresh_attributes), obj);
626 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
627 G_CALLBACK (text_buffer_can_undo), obj);
628 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
629 G_CALLBACK (text_buffer_can_redo), obj);
630 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
631 G_CALLBACK (body_changed), obj);
632 g_signal_connect (G_OBJECT (priv->text_buffer), "modified-changed",
633 G_CALLBACK (body_changed), obj);
634 g_signal_connect (G_OBJECT (priv->text_buffer), "end-user-action",
635 G_CALLBACK (text_buffer_end_user_action), obj);
636 g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
637 G_CALLBACK (text_buffer_mark_set), obj);
638 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
639 G_CALLBACK (text_buffer_apply_tag), obj);
640 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
641 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
642 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
643 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
644 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
645 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
647 g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
648 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
649 g_signal_connect (G_OBJECT (priv->from_field), "value-changed",
650 G_CALLBACK (from_field_changed), obj);
652 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
653 G_CALLBACK (msg_body_focus), obj);
654 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
655 G_CALLBACK (msg_body_focus), obj);
656 g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
657 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
658 "changed", G_CALLBACK (recpt_field_changed), obj);
659 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
660 "changed", G_CALLBACK (recpt_field_changed), obj);
661 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
662 "changed", G_CALLBACK (recpt_field_changed), obj);
663 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
664 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
665 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
667 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
668 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
670 priv->clipboard_change_handler_id =
671 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
672 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
673 priv->default_clipboard_change_handler_id =
674 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
675 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
677 g_signal_connect (G_OBJECT (priv->msg_body), "cut-clipboard", G_CALLBACK (cut_clipboard_check), NULL);
678 g_signal_connect (G_OBJECT (priv->msg_body), "copy-clipboard", G_CALLBACK (copy_clipboard_check), NULL);
679 g_signal_connect (G_OBJECT (priv->attachments_view), "delete", G_CALLBACK (attachment_deleted), obj);
683 init_wp_text_view_style ()
685 static gboolean initialized = FALSE;
688 gtk_rc_parse_string ("class \"WPTextView\" style \"fremantle-textview\"");
694 init_window (ModestMsgEditWindow *obj)
696 GtkWidget *to_caption, *subject_caption;
697 GtkWidget *main_vbox;
698 ModestMsgEditWindowPrivate *priv;
699 GtkActionGroup *action_group;
700 ModestWindowPrivate *parent_priv;
701 GdkPixbuf *window_icon = NULL;
702 GError *error = NULL;
704 GtkSizeGroup *title_size_group;
705 GtkSizeGroup *value_size_group;
706 GtkWidget *subject_box;
707 GtkWidget *attachment_icon;
708 GtkWidget *window_box;
709 #if (GTK_MINOR_VERSION >= 10)
710 GdkAtom deserialize_type;
713 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
714 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
716 parent_priv->ui_manager = gtk_ui_manager_new();
717 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
718 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
720 /* Add common actions */
721 gtk_action_group_add_actions (action_group,
722 modest_msg_edit_action_entries,
723 G_N_ELEMENTS (modest_msg_edit_action_entries),
725 gtk_action_group_add_actions (action_group,
726 hildon2_msg_edit_action_entries,
727 G_N_ELEMENTS (hildon2_msg_edit_action_entries),
729 gtk_action_group_add_toggle_actions (action_group,
730 modest_msg_edit_toggle_action_entries,
731 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
733 gtk_action_group_add_radio_actions (action_group,
734 modest_msg_edit_alignment_radio_action_entries,
735 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
737 G_CALLBACK (modest_ui_actions_on_change_justify),
739 gtk_action_group_add_radio_actions (action_group,
740 modest_msg_edit_priority_action_entries,
741 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
743 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
745 gtk_action_group_add_radio_actions (action_group,
746 modest_msg_edit_file_format_action_entries,
747 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
748 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
749 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
751 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
752 g_object_unref (action_group);
754 /* Load the UI definition */
755 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
758 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
759 g_clear_error (&error);
762 /* Add accelerators */
763 gtk_window_add_accel_group (GTK_WINDOW (obj),
764 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
766 parent_priv->menubar = NULL;
768 title_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
769 value_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
771 /* Note: This ModestPairList* must exist for as long as the picker
772 * that uses it, because the ModestSelectorPicker uses the ID opaquely,
773 * so it can't know how to manage its memory. */
774 priv->from_field = modest_selector_picker_new (MODEST_EDITABLE_SIZE,
775 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL,
777 modest_maemo_utils_set_hbutton_layout (title_size_group, value_size_group,
778 _("mail_va_from"), priv->from_field);
780 priv->to_field = modest_recpt_editor_new ();
781 priv->cc_field = modest_recpt_editor_new ();
782 priv->bcc_field = modest_recpt_editor_new ();
783 subject_box = gtk_hbox_new (FALSE, 0);
784 priv->priority_icon = gtk_image_new ();
785 gtk_box_pack_start (GTK_BOX (subject_box), priv->priority_icon, FALSE, FALSE, 0);
786 priv->subject_field = hildon_entry_new (MODEST_EDITABLE_SIZE);
787 gtk_entry_set_max_length (GTK_ENTRY (priv->subject_field) ,SUBJECT_MAX_LENGTH);
788 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
789 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
790 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
791 gtk_box_pack_start (GTK_BOX (subject_box), priv->subject_field, TRUE, TRUE, 0);
792 priv->add_attachment_button = hildon_button_new (MODEST_EDITABLE_SIZE, HILDON_BUTTON_ARRANGEMENT_VERTICAL);
793 gtk_widget_set_size_request (priv->add_attachment_button, ATTACHMENT_BUTTON_WIDTH, -1);
794 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
795 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
796 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, HILDON_ICON_SIZE_FINGER);
797 hildon_button_set_image (HILDON_BUTTON (priv->add_attachment_button), attachment_icon);
798 gtk_box_pack_start (GTK_BOX (subject_box), priv->add_attachment_button, FALSE, FALSE, 0);
799 priv->attachments_view = modest_attachments_view_new (NULL);
800 modest_attachments_view_set_style (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
801 MODEST_ATTACHMENTS_VIEW_STYLE_NO_FOCUS);
803 priv->header_box = gtk_vbox_new (FALSE, 0);
805 to_caption = modest_maemo_utils_create_captioned_with_size_type
806 (title_size_group, value_size_group,
807 _("mail_va_to"), FALSE, priv->to_field,
808 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
809 priv->cc_caption = modest_maemo_utils_create_captioned_with_size_type
810 (title_size_group, value_size_group,
811 _("mail_va_cc"), FALSE, priv->cc_field,
812 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
813 priv->bcc_caption = modest_maemo_utils_create_captioned_with_size_type
814 (title_size_group, value_size_group,
815 _("mail_va_hotfix1"), FALSE, priv->bcc_field,
816 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
817 subject_caption = modest_maemo_utils_create_captioned (title_size_group, value_size_group,
818 _("mail_va_subject"), FALSE, subject_box);
819 priv->attachments_caption = modest_maemo_utils_create_captioned_with_size_type (title_size_group, value_size_group,
820 _("mail_va_attachment"),
822 priv->attachments_view,
823 HILDON_SIZE_AUTO_WIDTH |
824 HILDON_SIZE_AUTO_HEIGHT);
825 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), value_size_group); */
826 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), value_size_group); */
827 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), value_size_group); */
828 g_object_unref (title_size_group);
829 g_object_unref (value_size_group);
831 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->from_field, FALSE, FALSE, 0);
832 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
833 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
834 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
835 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
836 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
837 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
839 init_wp_text_view_style ();
841 priv->msg_body = wp_text_view_new ();
844 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
845 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
846 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
847 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
848 #if (GTK_MINOR_VERSION >= 10)
849 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
850 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
852 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
853 deserialize_type, TRUE);
855 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
857 priv->find_toolbar = hildon_find_toolbar_new (NULL);
858 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
860 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
862 priv->pannable = hildon_pannable_area_new ();
864 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
866 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
867 priv->frame = gtk_frame_new (NULL);
868 gtk_box_pack_start (GTK_BOX(main_vbox), priv->frame, TRUE, TRUE, 0);
870 hildon_pannable_area_add_with_viewport (HILDON_PANNABLE_AREA (priv->pannable), main_vbox);
871 gtk_container_set_focus_vadjustment (GTK_CONTAINER (main_vbox),
872 hildon_pannable_area_get_vadjustment (HILDON_PANNABLE_AREA (priv->pannable)));
873 gtk_widget_show_all (GTK_WIDGET(priv->pannable));
875 window_box = gtk_vbox_new (FALSE, 0);
876 gtk_container_add (GTK_CONTAINER(obj), window_box);
878 gtk_box_pack_start (GTK_BOX (window_box), priv->pannable, TRUE, TRUE, 0);
880 gtk_container_add (GTK_CONTAINER (priv->frame), priv->msg_body);
882 /* Set window icon */
883 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
885 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
886 g_object_unref (window_icon);
891 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
893 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
895 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
896 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
897 priv->clipboard_change_handler_id))
898 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
899 priv->clipboard_change_handler_id);
900 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
901 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
902 priv->default_clipboard_change_handler_id))
903 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
904 priv->default_clipboard_change_handler_id);
906 if (priv->account_removed_handler_id &&
907 g_signal_handler_is_connected (modest_runtime_get_account_store (),
908 priv->account_removed_handler_id))
909 g_signal_handler_disconnect(modest_runtime_get_account_store (),
910 priv->account_removed_handler_id);
914 modest_msg_edit_window_finalize (GObject *obj)
916 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
918 /* Sanity check: shouldn't be needed, the window mgr should
919 call this function before */
920 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
922 if (priv->font_dialog != NULL) {
923 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
926 if (priv->clipboard_text != NULL) {
927 g_free (priv->clipboard_text);
928 priv->clipboard_text = NULL;
931 if (priv->draft_msg != NULL) {
932 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
933 if (TNY_IS_HEADER (header)) {
934 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
935 modest_window_mgr_unregister_header (mgr, header);
937 g_object_unref (priv->draft_msg);
938 priv->draft_msg = NULL;
940 if (priv->outbox_msg != NULL) {
941 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
942 if (TNY_IS_HEADER (header)) {
943 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
944 modest_window_mgr_unregister_header (mgr, header);
946 g_object_unref (priv->outbox_msg);
947 priv->outbox_msg = NULL;
949 if (priv->correct_scroll_idle > 0) {
950 g_source_remove (priv->correct_scroll_idle);
951 priv->correct_scroll_idle = 0;
953 if (priv->scroll_drag_timeout_id > 0) {
954 g_source_remove (priv->scroll_drag_timeout_id);
955 priv->scroll_drag_timeout_id = 0;
957 if (priv->clipboard_owner_idle > 0) {
958 g_source_remove (priv->clipboard_owner_idle);
959 priv->clipboard_owner_idle = 0;
961 if (priv->original_account_name)
962 g_free (priv->original_account_name);
963 g_free (priv->msg_uid);
964 g_free (priv->last_search);
965 g_slist_free (priv->font_items_group);
966 g_slist_free (priv->size_items_group);
967 g_object_unref (priv->attachments);
968 g_object_unref (priv->images);
970 /* This had to stay alive for as long as the picker that used it: */
971 modest_pair_list_free (priv->from_field_protos);
973 G_OBJECT_CLASS(parent_class)->finalize (obj);
977 pixbuf_from_stream (TnyStream *stream, const gchar *mime_type, guint64 *stream_size)
979 GdkPixbufLoader *loader;
985 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
987 if (loader == NULL) {
993 tny_stream_reset (TNY_STREAM (stream));
994 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
995 GError *error = NULL;
996 unsigned char read_buffer[128];
998 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
1000 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
1002 g_error_free (error);
1007 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1009 g_object_ref (pixbuf);
1010 gdk_pixbuf_loader_close (loader, NULL);
1011 g_object_unref (loader);
1016 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1017 GdkPixbuf *new_pixbuf;
1019 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1020 gdk_pixbuf_get_width (pixbuf);
1021 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1022 g_object_unref (pixbuf);
1023 pixbuf = new_pixbuf;
1027 *stream_size = size;
1033 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1035 ModestMsgEditWindowPrivate *priv;
1038 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1040 for (iter = tny_list_create_iterator (attachments);
1041 !tny_iterator_is_done (iter);
1042 tny_iterator_next (iter)) {
1043 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1044 const gchar *cid = tny_mime_part_get_content_id (part);
1045 const gchar *mime_type = tny_mime_part_get_content_type (part);
1046 if ((cid != NULL)&&(mime_type != NULL)) {
1047 guint64 stream_size;
1048 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1049 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
1052 g_object_unref (stream);
1054 if (pixbuf != NULL) {
1055 priv->images_count ++;
1056 priv->images_size += stream_size;
1057 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1058 g_object_unref (pixbuf);
1061 g_object_unref (part);
1063 g_object_unref (iter);
1067 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1069 TnyMimePart *parent = NULL;
1070 const gchar *content_type = NULL;
1071 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1073 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1075 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1076 parent = g_object_ref (msg);
1077 } else if (content_type && !g_strcasecmp (content_type, "multipart/mixed")) {
1078 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1081 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1082 iter = tny_list_create_iterator (parts);
1083 while (!tny_iterator_is_done (iter)) {
1085 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1086 content_type = tny_mime_part_get_content_type (part);
1087 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1091 g_object_unref (part);
1093 tny_iterator_next (iter);
1095 g_object_unref (iter);
1096 g_object_unref (parts);
1099 if (parent != NULL) {
1100 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1103 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1104 iter = tny_list_create_iterator (parts);
1105 while (!tny_iterator_is_done (iter)) {
1107 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1108 content_type = tny_mime_part_get_content_type (part);
1109 if (content_type && g_str_has_prefix (content_type, "image/")) {
1110 tny_list_prepend (priv->images, (GObject *) part);
1112 g_object_unref (part);
1113 tny_iterator_next (iter);
1115 g_object_unref (iter);
1116 g_object_unref (parts);
1117 g_object_unref (parent);
1122 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1125 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1127 for (iter = tny_list_create_iterator (attachments) ;
1128 !tny_iterator_is_done (iter);
1129 tny_iterator_next (iter)) {
1130 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1131 const gchar *cid = tny_mime_part_get_content_id (part);
1133 char *invalid = NULL;
1134 gint int_cid = strtol (cid, &invalid, 10);
1135 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1136 priv->next_cid = int_cid + 1;
1139 g_object_unref (part);
1141 g_object_unref (iter);
1145 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1148 gchar *to, *cc, *bcc, *subject;
1150 ModestMsgEditWindowPrivate *priv;
1151 ModestWindowPrivate *parent_priv;
1153 TnyHeaderFlags priority_flags;
1154 TnyFolder *msg_folder;
1155 gboolean is_html = FALSE;
1156 gboolean field_view_set;
1158 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1159 g_return_if_fail (TNY_IS_MSG (msg));
1161 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1162 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1164 header = tny_msg_get_header (msg);
1165 to = tny_header_dup_to (header);
1166 cc = tny_header_dup_cc (header);
1167 bcc = tny_header_dup_bcc (header);
1168 subject = tny_header_dup_subject (header);
1169 priority_flags = tny_header_get_priority (header);
1172 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
1174 field_view_set = TRUE;
1176 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
1177 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1178 gtk_widget_show (priv->cc_caption);
1179 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1180 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1181 gtk_widget_hide (priv->cc_caption);
1182 field_view_set = FALSE;
1184 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button), field_view_set);
1186 field_view_set = TRUE;
1188 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
1189 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1190 gtk_widget_show (priv->bcc_caption);
1191 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1192 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1193 gtk_widget_hide (priv->bcc_caption);
1194 field_view_set = FALSE;
1196 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button), field_view_set);
1200 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1201 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1204 update_window_title (self);
1206 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1207 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1209 if ((body == NULL)||(body[0] == '\0')) {
1211 body = modest_text_utils_convert_to_html ("");
1214 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1215 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1218 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1221 /* Add attachments to the view */
1222 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1223 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1224 if (tny_list_get_length (priv->attachments) == 0) {
1225 gtk_widget_hide (priv->attachments_caption);
1227 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1228 gtk_widget_show_all (priv->attachments_caption);
1230 get_related_images (self, msg);
1231 update_next_cid (self, priv->attachments);
1232 update_next_cid (self, priv->images);
1233 replace_with_images (self, priv->images);
1235 if (preserve_is_rich && !is_html) {
1236 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1237 /* Get the default format required from configuration */
1238 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1239 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1242 /* Set the default focus depending on having already a To: field or not */
1243 if ((!to)||(*to == '\0')) {
1244 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1246 gtk_widget_grab_focus (priv->msg_body);
1249 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1251 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1252 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1254 modest_msg_edit_window_set_modified (self, FALSE);
1256 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1257 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1258 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1259 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1261 if (priv->msg_uid) {
1262 g_free (priv->msg_uid);
1263 priv->msg_uid = NULL;
1266 /* we should set a reference to the incoming message if it is a draft */
1267 msg_folder = tny_msg_get_folder (msg);
1269 if (modest_tny_folder_is_local_folder (msg_folder)) {
1270 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1271 if (type == TNY_FOLDER_TYPE_INVALID)
1272 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1274 if (type == TNY_FOLDER_TYPE_DRAFTS)
1275 priv->draft_msg = g_object_ref(msg);
1276 if (type == TNY_FOLDER_TYPE_OUTBOX)
1277 priv->outbox_msg = g_object_ref(msg);
1278 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1280 g_object_unref (msg_folder);
1290 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
1293 GList *item_children, *node;
1294 GtkWidget *bin_child;
1296 bin_child = gtk_bin_get_child (GTK_BIN(item));
1298 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
1300 for (node = item_children; node != NULL; node = g_list_next (node)) {
1301 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
1302 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
1305 g_list_free (item_children);
1309 menu_tool_button_dont_expand (GtkMenuToolButton *item)
1312 GList *item_children, *node;
1314 box = gtk_bin_get_child (GTK_BIN (item));
1315 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
1316 item_children = gtk_container_get_children (GTK_CONTAINER (box));
1318 for (node = item_children; node != NULL; node = g_list_next (node)) {
1319 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
1320 if (GTK_IS_TOGGLE_BUTTON (node->data))
1321 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
1322 else if (GTK_IS_BUTTON (node->data))
1323 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
1325 g_list_free (item_children);
1330 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1332 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1333 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1334 GtkWidget *placeholder;
1335 GtkWidget *tool_item;
1340 GtkWidget *sizes_menu;
1341 GtkWidget *fonts_menu;
1342 GSList *radio_group = NULL;
1343 GSList *node = NULL;
1347 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1348 gtk_toolbar_set_show_arrow (GTK_TOOLBAR (parent_priv->toolbar), FALSE);
1349 gtk_toolbar_set_icon_size (GTK_TOOLBAR (parent_priv->toolbar), HILDON_ICON_SIZE_FINGER);
1350 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1352 /* Font color placeholder */
1353 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1354 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1357 priv->font_color_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1358 priv->font_color_button = hildon_color_button_new ();
1359 gtk_widget_set_size_request (priv->font_color_button, -1, 48);
1360 GTK_WIDGET_UNSET_FLAGS (priv->font_color_toolitem, GTK_CAN_FOCUS);
1361 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1362 gtk_container_add (GTK_CONTAINER (priv->font_color_toolitem), priv->font_color_button);
1363 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1364 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1365 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->font_color_toolitem), insert_index);
1366 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1368 G_CALLBACK (modest_msg_edit_window_color_button_change),
1371 /* Font size and face placeholder */
1372 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1373 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1375 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1376 priv->size_tool_button_label = gtk_label_new (NULL);
1377 hildon_helper_set_logical_color (GTK_WIDGET (priv->size_tool_button_label), GTK_RC_TEXT,
1378 GTK_STATE_INSENSITIVE, "SecondaryTextColor");
1379 hildon_helper_set_logical_color (GTK_WIDGET (priv->size_tool_button_label), GTK_RC_FG,
1380 GTK_STATE_INSENSITIVE, "SecondaryTextColor");
1381 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1382 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1383 size_text,"</span>", NULL);
1384 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1386 hildon_helper_set_logical_font (priv->size_tool_button_label, "LargeSystemFont");
1387 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
1388 sizes_menu = gtk_menu_new ();
1389 priv->size_items_group = NULL;
1391 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1392 GtkWidget *size_menu_item;
1394 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1395 size_menu_item = gtk_radio_menu_item_new_with_label (radio_group, size_text);
1396 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (size_menu_item));
1397 gtk_menu_shell_append (GTK_MENU_SHELL (sizes_menu), size_menu_item);
1398 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (size_menu_item), (wp_font_size[size_index] == 12));
1399 gtk_widget_show (size_menu_item);
1401 priv->size_items_group = g_slist_prepend (priv->size_items_group, size_menu_item);
1405 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1406 GtkWidget *item = (GtkWidget *) node->data;
1407 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_size_change),
1411 priv->size_items_group = g_slist_reverse (priv->size_items_group);
1412 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), sizes_menu);
1413 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1414 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1415 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), FALSE);
1416 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), FALSE);
1417 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1418 priv->font_size_toolitem = tool_item;
1421 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1422 priv->font_tool_button_label = gtk_label_new (NULL);
1423 hildon_helper_set_logical_color (GTK_WIDGET (priv->font_tool_button_label), GTK_RC_TEXT,
1424 GTK_STATE_INSENSITIVE, "SecondaryTextColor");
1425 hildon_helper_set_logical_color (GTK_WIDGET (priv->font_tool_button_label), GTK_RC_FG,
1426 GTK_STATE_INSENSITIVE, "SecondaryTextColor");
1427 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1428 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1430 hildon_helper_set_logical_font (priv->font_tool_button_label, "LargeSystemFont");
1431 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
1432 fonts_menu = gtk_menu_new ();
1433 priv->font_items_group = NULL;
1435 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1436 GtkWidget *font_menu_item;
1437 GtkWidget *child_label;
1439 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
1440 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
1441 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
1442 wp_get_font_name (font_index), "</span>", NULL);
1443 gtk_label_set_markup (GTK_LABEL (child_label), markup);
1446 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
1447 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
1448 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
1449 gtk_widget_show (font_menu_item);
1451 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
1454 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1455 GtkWidget *item = (GtkWidget *) node->data;
1456 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
1459 priv->font_items_group = g_slist_reverse (priv->font_items_group);
1460 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
1461 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1462 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1463 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), FALSE);
1464 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), FALSE);
1465 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1466 priv->font_face_toolitem = tool_item;
1468 /* Set expand and homogeneous for remaining items */
1469 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
1470 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1471 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1472 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1473 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1474 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1475 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1476 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1477 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1479 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1480 will not show the tool items added to the placeholders) */
1481 gtk_widget_show_all (parent_priv->toolbar);
1483 /* Set the no show all *after* showing all items. We do not
1484 want the toolbar to be shown with a show all because it
1485 could go agains the gconf setting regarding showing or not
1486 the toolbar of the editor window */
1487 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1493 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, gboolean preserve_is_rich)
1496 ModestWindowPrivate *parent_priv;
1497 ModestMsgEditWindowPrivate *priv;
1498 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1499 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1500 ModestWindowMgr *mgr = NULL;
1502 g_return_val_if_fail (msg, NULL);
1503 g_return_val_if_fail (account_name, NULL);
1505 mgr = modest_runtime_get_window_mgr ();
1507 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1509 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1510 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1512 /* Menubar. Update the state of some toggles */
1513 priv->from_field_protos = get_transports ();
1514 modest_selector_picker_set_pair_list (MODEST_SELECTOR_PICKER (priv->from_field), priv->from_field_protos);
1515 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1516 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1517 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1519 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1520 hildon_touch_selector_get_current_text
1521 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1522 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1523 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1526 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1528 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1530 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1532 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1534 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1535 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1536 /* Add common dimming rules */
1537 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1538 modest_msg_edit_window_toolbar_dimming_entries,
1539 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1540 MODEST_WINDOW (obj));
1541 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_toolitem,
1542 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1543 MODEST_WINDOW (obj));
1544 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1545 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1546 MODEST_WINDOW (obj));
1547 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1548 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1549 MODEST_WINDOW (obj));
1550 /* Insert dimming rules group for this window */
1551 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1552 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1554 /* Setup app menu */
1555 setup_menu (MODEST_MSG_EDIT_WINDOW (obj));
1557 /* Checks the dimming rules */
1558 g_object_unref (toolbar_rules_group);
1559 g_object_unref (clipboard_rules_group);
1560 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1562 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1564 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1565 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1566 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1567 priv->update_caption_visibility = TRUE;
1569 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1571 /* Track account-removed signal, this window should be closed
1572 in the case we're creating a mail associated to the account
1574 priv->account_removed_handler_id =
1575 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1577 G_CALLBACK(on_account_removed),
1580 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1582 return (ModestWindow*) obj;
1586 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1588 GString **string_buffer = (GString **) user_data;
1590 *string_buffer = g_string_append (*string_buffer, buffer);
1596 * @result: A new string which should be freed with g_free().
1599 get_formatted_data (ModestMsgEditWindow *edit_window)
1601 ModestMsgEditWindowPrivate *priv;
1602 GString *string_buffer = g_string_new ("");
1604 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1606 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1608 modest_text_utils_hyperlinkify (string_buffer);
1610 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1612 return g_string_free (string_buffer, FALSE);
1617 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1620 const gchar *account_name;
1621 ModestMsgEditWindowPrivate *priv;
1622 TnyIterator *att_iter;
1624 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1626 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1628 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1629 g_return_val_if_fail (account_name, NULL);
1632 /* don't free these (except from) */
1633 data = g_slice_new0 (MsgData);
1634 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1636 data->account_name = g_strdup (account_name);
1637 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1638 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1639 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1640 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1641 if (priv->draft_msg) {
1642 data->draft_msg = g_object_ref (priv->draft_msg);
1643 } else if (priv->outbox_msg) {
1644 data->draft_msg = g_object_ref (priv->outbox_msg);
1646 data->draft_msg = NULL;
1649 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1651 gtk_text_buffer_get_bounds (buf, &b, &e);
1652 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1654 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1655 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1657 data->html_body = NULL;
1659 /* deep-copy the data */
1660 att_iter = tny_list_create_iterator (priv->attachments);
1661 data->attachments = NULL;
1662 while (!tny_iterator_is_done (att_iter)) {
1663 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1664 if (!(TNY_IS_MIME_PART(part))) {
1665 g_warning ("strange data in attachment list");
1666 g_object_unref (part);
1667 tny_iterator_next (att_iter);
1670 data->attachments = g_list_append (data->attachments,
1672 tny_iterator_next (att_iter);
1674 g_object_unref (att_iter);
1676 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1677 att_iter = tny_list_create_iterator (priv->images);
1678 data->images = NULL;
1679 while (!tny_iterator_is_done (att_iter)) {
1680 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1682 if (!(TNY_IS_MIME_PART(part))) {
1683 g_warning ("strange data in attachment list");
1684 g_object_unref (part);
1685 tny_iterator_next (att_iter);
1688 cid = tny_mime_part_get_content_id (part);
1690 gchar *image_tag_id;
1691 GtkTextTag *image_tag;
1693 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1694 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1695 g_free (image_tag_id);
1697 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1699 ((gtk_text_iter_has_tag (&iter, image_tag))||
1700 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1701 data->images = g_list_append (data->images,
1702 g_object_ref (part));
1704 g_object_unref (part);
1705 tny_iterator_next (att_iter);
1707 g_object_unref (att_iter);
1709 data->priority_flags = priv->priority_flags;
1716 unref_gobject (GObject *obj, gpointer data)
1718 if (!G_IS_OBJECT(obj))
1720 g_object_unref (obj);
1724 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1727 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1735 g_free (data->from);
1736 g_free (data->subject);
1737 g_free (data->plain_body);
1738 g_free (data->html_body);
1739 g_free (data->account_name);
1741 if (data->draft_msg != NULL) {
1742 g_object_unref (data->draft_msg);
1743 data->draft_msg = NULL;
1746 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1747 g_list_free (data->attachments);
1748 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1749 g_list_free (data->images);
1751 g_slice_free (MsgData, data);
1755 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1757 guint64 *parts_size)
1759 ModestMsgEditWindowPrivate *priv;
1761 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1763 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1765 /* TODO: add images */
1766 *parts_size += priv->images_size;
1767 *parts_count += priv->images_count;
1772 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1775 ModestMsgEditWindowPrivate *priv = NULL;
1776 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1778 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1780 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1782 return MODEST_MSG_EDIT_FORMAT_HTML;
1784 return MODEST_MSG_EDIT_FORMAT_TEXT;
1788 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1789 ModestMsgEditFormat format)
1791 ModestMsgEditWindowPrivate *priv;
1793 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1794 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1797 case MODEST_MSG_EDIT_FORMAT_HTML:
1798 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1800 case MODEST_MSG_EDIT_FORMAT_TEXT:
1801 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1804 g_return_if_reached ();
1808 ModestMsgEditFormatState *
1809 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1811 ModestMsgEditFormatState *format_state = NULL;
1812 ModestMsgEditWindowPrivate *priv;
1813 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1815 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1816 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1818 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1820 format_state = g_new0 (ModestMsgEditFormatState, 1);
1821 format_state->bold = buffer_format->bold&0x1;
1822 format_state->italics = buffer_format->italic&0x1;
1823 format_state->bullet = buffer_format->bullet&0x1;
1824 format_state->color = buffer_format->color;
1825 format_state->font_size = buffer_format->font_size;
1826 format_state->font_family = wp_get_font_name (buffer_format->font);
1827 format_state->justification = buffer_format->justification;
1828 g_free (buffer_format);
1830 return format_state;
1835 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1836 const ModestMsgEditFormatState *format_state)
1838 ModestMsgEditWindowPrivate *priv;
1839 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1840 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1841 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1842 g_return_if_fail (format_state != NULL);
1844 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1845 gtk_widget_grab_focus (priv->msg_body);
1846 buffer_format->bold = (format_state->bold != FALSE);
1847 buffer_format->italic = (format_state->italics != FALSE);
1848 buffer_format->color = format_state->color;
1849 buffer_format->font_size = format_state->font_size;
1850 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1851 buffer_format->justification = format_state->justification;
1852 buffer_format->bullet = format_state->bullet;
1854 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1856 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1857 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1858 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1859 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1860 buffer_format->cs.font = (buffer_format->font != current_format->font);
1861 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1862 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1864 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1865 if (buffer_format->cs.bold) {
1866 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
1867 GINT_TO_POINTER (buffer_format->bold&0x1));
1869 if (buffer_format->cs.italic) {
1870 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
1871 GINT_TO_POINTER (buffer_format->italic&0x1));
1873 if (buffer_format->cs.color) {
1874 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1875 GINT_TO_POINTER (&(buffer_format->color)));
1877 if (buffer_format->cs.font_size) {
1878 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1879 GINT_TO_POINTER (buffer_format->font_size));
1881 if (buffer_format->cs.justification) {
1882 switch (buffer_format->justification) {
1883 case GTK_JUSTIFY_LEFT:
1884 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
1885 GINT_TO_POINTER(TRUE));
1887 case GTK_JUSTIFY_CENTER:
1888 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
1889 GINT_TO_POINTER(TRUE));
1891 case GTK_JUSTIFY_RIGHT:
1892 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
1893 GINT_TO_POINTER(TRUE));
1900 if (buffer_format->cs.font) {
1901 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1902 GINT_TO_POINTER (buffer_format->font));
1904 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1905 if (buffer_format->cs.bullet) {
1906 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
1907 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
1909 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1911 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
1913 g_free (buffer_format);
1914 g_free (current_format);
1916 /* Check dimming rules */
1917 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1918 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1922 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1924 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1926 ModestWindowPrivate *parent_priv;
1927 ModestMsgEditWindowPrivate *priv;
1928 GtkWidget *new_size_menuitem;
1929 GtkWidget *new_font_menuitem;
1931 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1932 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1934 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1935 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu");
1936 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1937 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1939 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatPlainTextMenu");
1940 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1941 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1944 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1946 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1947 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1949 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1950 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1952 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
1953 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
1956 switch (buffer_format->justification)
1958 case GTK_JUSTIFY_LEFT:
1959 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
1961 case GTK_JUSTIFY_CENTER:
1962 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
1964 case GTK_JUSTIFY_RIGHT:
1965 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
1972 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
1974 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1975 G_CALLBACK (modest_msg_edit_window_color_button_change),
1977 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1978 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1979 G_CALLBACK (modest_msg_edit_window_color_button_change),
1982 new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group,
1983 buffer_format->font_size))->data);
1984 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1988 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1989 markup = g_strconcat ("<span font_family='Sans'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1990 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1992 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1993 G_CALLBACK (modest_msg_edit_window_size_change),
1995 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
1996 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
1997 G_CALLBACK (modest_msg_edit_window_size_change),
2001 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
2002 buffer_format->font))->data);
2003 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
2007 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
2008 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2009 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2011 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
2012 G_CALLBACK (modest_msg_edit_window_font_change),
2014 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
2015 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
2016 G_CALLBACK (modest_msg_edit_window_font_change),
2020 g_free (buffer_format);
2024 #ifdef MODEST_HILDON_VERSION_0
2026 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2029 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2030 ModestMsgEditWindowPrivate *priv;
2031 GtkWidget *dialog = NULL;
2033 GdkColor *new_color = NULL;
2035 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2036 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2038 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2039 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
2040 g_free (buffer_format);
2042 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2043 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2044 if (new_color != NULL) {
2045 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2046 (gpointer) new_color);
2049 gtk_widget_destroy (dialog);
2054 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2057 ModestMsgEditWindowPrivate *priv;
2058 GtkWidget *dialog = NULL;
2060 GdkColor *old_color = NULL;
2061 const GdkColor *new_color = NULL;
2063 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2064 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2066 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2067 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2069 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2070 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2071 if (new_color != NULL)
2072 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2074 gtk_widget_destroy (dialog);
2080 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2083 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2084 ModestMsgEditWindowPrivate *priv;
2085 GtkWidget *dialog = NULL;
2087 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2088 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2090 dialog = hildon_color_chooser_new ();
2091 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2092 g_free (buffer_format);
2094 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2096 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2097 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2100 gtk_widget_destroy (dialog);
2105 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2108 ModestMsgEditWindowPrivate *priv;
2109 GtkWidget *dialog = NULL;
2110 GdkColor *old_color = NULL;
2112 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2113 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2115 dialog = hildon_color_chooser_new ();
2116 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2118 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2120 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2121 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2123 gtk_widget_destroy (dialog);
2126 #endif /*!MODEST_HILDON_VERSION_0*/
2131 create_stream_for_uri (const gchar* uri)
2136 TnyStream *result = NULL;
2138 GnomeVFSHandle *handle = NULL;
2139 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2140 if (test == GNOME_VFS_OK) {
2141 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2142 /* Streams over OBEX (Bluetooth) are not seekable but
2143 * we expect them to be (we might need to read them
2144 * several times). So if this is a Bluetooth URI just
2145 * read the whole file into memory (this is not a fast
2146 * protocol so we can assume that these files are not
2147 * going to be very big) */
2148 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2149 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2150 TnyStream *memstream = tny_camel_mem_stream_new ();
2151 tny_stream_write_to_stream (vfssstream, memstream);
2152 g_object_unref (vfssstream);
2155 result = vfssstream;
2163 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2166 ModestMsgEditWindowPrivate *priv;
2167 GtkWidget *dialog = NULL;
2169 GSList *uris = NULL;
2170 GSList *uri_node = NULL;
2172 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2174 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2175 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2176 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2178 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2180 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2181 GTK_WINDOW (dialog), GTK_WINDOW (window));
2183 response = gtk_dialog_run (GTK_DIALOG (dialog));
2185 case GTK_RESPONSE_OK:
2186 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2191 gtk_widget_destroy (dialog);
2193 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2195 GnomeVFSHandle *handle = NULL;
2196 GnomeVFSResult result;
2197 GtkTextIter position;
2198 GtkTextMark *insert_mark;
2200 uri = (const gchar *) uri_node->data;
2201 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2202 if (result == GNOME_VFS_OK) {
2204 GnomeVFSFileInfo *info;
2205 gchar *filename, *basename, *escaped_filename;
2206 TnyMimePart *mime_part;
2208 const gchar *mime_type = NULL;
2209 GnomeVFSURI *vfs_uri;
2210 guint64 stream_size;
2212 gnome_vfs_close (handle);
2213 vfs_uri = gnome_vfs_uri_new (uri);
2215 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2216 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2217 g_free (escaped_filename);
2218 gnome_vfs_uri_unref (vfs_uri);
2219 info = gnome_vfs_file_info_new ();
2221 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2222 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2224 mime_type = gnome_vfs_file_info_get_mime_type (info);
2226 mime_part = tny_platform_factory_new_mime_part
2227 (modest_runtime_get_platform_factory ());
2229 TnyStream *stream = create_stream_for_uri (uri);
2231 if (stream == NULL) {
2233 modest_platform_information_banner (NULL, NULL,
2234 _FM("sfil_ib_opening_not_allowed"));
2236 g_object_unref (mime_part);
2237 gnome_vfs_file_info_unref (info);
2241 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2243 content_id = g_strdup_printf ("%d", priv->next_cid);
2244 tny_mime_part_set_content_id (mime_part, content_id);
2245 g_free (content_id);
2248 basename = g_path_get_basename (filename);
2249 tny_mime_part_set_filename (mime_part, basename);
2252 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
2254 if (pixbuf != NULL) {
2255 priv->images_size += stream_size;
2256 priv->images_count ++;
2257 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2258 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2259 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
2260 g_object_unref (pixbuf);
2263 tny_list_prepend (priv->images, (GObject *) mime_part);
2264 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2266 g_object_unref (mime_part);
2267 gnome_vfs_file_info_unref (info);
2276 on_attach_file_response (GtkDialog *dialog,
2280 GSList *uris = NULL;
2282 GnomeVFSFileSize total_size, allowed_size;
2283 ModestMsgEditWindow *window;
2284 ModestMsgEditWindowPrivate *priv;
2289 case GTK_RESPONSE_OK:
2290 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2296 window = MODEST_MSG_EDIT_WINDOW (user_data);
2297 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2299 /* allowed size is the maximum size - what's already there */
2300 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2301 &att_num, &att_size);
2302 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2305 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2307 const gchar *uri = (const gchar *) uri_node->data;
2310 modest_msg_edit_window_attach_file_one (window, uri, allowed_size);
2312 if (total_size > allowed_size) {
2313 g_warning ("%s: total size: %u",
2314 __FUNCTION__, (unsigned int)total_size);
2317 allowed_size -= total_size;
2319 g_slist_foreach (uris, (GFunc) g_free, NULL);
2320 g_slist_free (uris);
2322 gtk_widget_destroy (GTK_WIDGET (dialog));
2326 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2328 GtkWidget *dialog = NULL;
2329 ModestMsgEditWindowPrivate *priv;
2331 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2333 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2335 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2338 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window),
2339 GTK_FILE_CHOOSER_ACTION_OPEN);
2340 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2341 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2342 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2343 GTK_WINDOW (dialog), GTK_WINDOW (window));
2345 /* Connect to response & show */
2346 g_signal_connect (dialog, "response",
2347 G_CALLBACK (on_attach_file_response), window);
2348 gtk_widget_show (dialog);
2353 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2355 GnomeVFSFileSize allowed_size)
2358 GnomeVFSHandle *handle = NULL;
2359 ModestMsgEditWindowPrivate *priv;
2360 GnomeVFSResult result;
2361 GnomeVFSFileSize size = 0;
2362 g_return_val_if_fail (window, 0);
2363 g_return_val_if_fail (uri, 0);
2365 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2367 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2368 if (result == GNOME_VFS_OK) {
2369 TnyMimePart *mime_part;
2371 const gchar *mime_type = NULL;
2373 gchar *escaped_filename;
2376 GnomeVFSFileInfo *info;
2377 GnomeVFSURI *vfs_uri;
2379 gnome_vfs_close (handle);
2380 vfs_uri = gnome_vfs_uri_new (uri);
2383 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2384 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2385 g_free (escaped_filename);
2386 gnome_vfs_uri_unref (vfs_uri);
2388 info = gnome_vfs_file_info_new ();
2390 if (gnome_vfs_get_file_info (uri,
2392 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2394 mime_type = gnome_vfs_file_info_get_mime_type (info);
2395 mime_part = tny_platform_factory_new_mime_part
2396 (modest_runtime_get_platform_factory ());
2398 /* try to get the attachment's size; this may fail for weird
2399 * file systems, like obex, upnp... */
2400 if (allowed_size != 0 &&
2401 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2403 if (size > allowed_size) {
2404 modest_platform_information_banner (NULL, NULL,
2405 _FM("sfil_ib_opening_not_allowed"));
2409 g_warning ("%s: could not get attachment size", __FUNCTION__);
2411 stream = create_stream_for_uri (uri);
2413 if (stream == NULL) {
2415 modest_platform_information_banner (NULL, NULL, _FM("sfil_ib_opening_not_allowed"));
2417 g_object_unref (mime_part);
2418 gnome_vfs_file_info_unref (info);
2422 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2423 g_object_unref (stream);
2425 content_id = g_strdup_printf ("%d", priv->next_cid);
2426 tny_mime_part_set_content_id (mime_part, content_id);
2427 g_free (content_id);
2430 basename = g_path_get_basename (filename);
2431 tny_mime_part_set_filename (mime_part, basename);
2434 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2435 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2437 info->size == 0, info->size);
2438 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2439 gtk_widget_show_all (priv->attachments_caption);
2440 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2442 g_object_unref (mime_part);
2443 gnome_vfs_file_info_unref (info);
2450 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2453 ModestMsgEditWindowPrivate *priv;
2456 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2457 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2459 if (att_list == NULL) {
2460 att_list = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2461 if (!modest_maemo_utils_select_attachments (GTK_WINDOW (window), att_list)) {
2462 g_object_unref (att_list);
2467 g_object_ref (att_list);
2470 if (tny_list_get_length (att_list) == 0) {
2471 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2473 gboolean dialog_response;
2474 gchar *message = NULL;
2475 gchar *filename = NULL;
2477 if (tny_list_get_length (att_list) == 1) {
2479 iter = tny_list_create_iterator (att_list);
2480 part = (TnyMimePart *) tny_iterator_get_current (iter);
2481 g_object_unref (iter);
2482 if (TNY_IS_MSG (part)) {
2483 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2485 filename = tny_header_dup_subject (header);
2486 g_object_unref (header);
2488 if (filename == NULL) {
2489 filename = g_strdup (_("mail_va_no_subject"));
2492 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2494 g_object_unref (part);
2496 filename = g_strdup ("");
2498 message = g_strdup_printf (ngettext("emev_nc_delete_attachment",
2499 "emev_nc_delete_attachments",
2500 tny_list_get_length (att_list)), filename);
2503 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
2507 if (dialog_response != GTK_RESPONSE_OK) {
2508 g_object_unref (att_list);
2512 for (iter = tny_list_create_iterator (att_list);
2513 !tny_iterator_is_done (iter);
2514 tny_iterator_next (iter)) {
2515 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2516 const gchar *att_id;
2517 tny_list_remove (priv->attachments, (GObject *) mime_part);
2519 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2521 if (tny_list_get_length (priv->attachments) == 0)
2522 gtk_widget_hide (priv->attachments_caption);
2523 att_id = tny_mime_part_get_content_id (mime_part);
2525 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2527 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2528 g_object_unref (mime_part);
2530 g_object_unref (iter);
2533 g_object_unref (att_list);
2535 /* if the last attachment has been removed, focus the Subject: field */
2536 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2537 gtk_widget_grab_focus (priv->subject_field);
2541 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2544 ModestMsgEditWindowPrivate *priv;
2545 GdkColor *new_color;
2546 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2548 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2549 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2552 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2554 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2556 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2558 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2563 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
2566 ModestMsgEditWindowPrivate *priv;
2567 gint new_size_index;
2568 ModestMsgEditWindow *window;
2571 window = MODEST_MSG_EDIT_WINDOW (userdata);
2572 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2573 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2575 if (gtk_check_menu_item_get_active (menu_item)) {
2577 WPTextBufferFormat format;
2579 memset (&format, 0, sizeof (format));
2580 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2582 label = gtk_bin_get_child (GTK_BIN (menu_item));
2584 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
2585 format.cs.font_size = TRUE;
2586 format.cs.text_position = TRUE;
2587 format.cs.font = TRUE;
2588 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
2589 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2591 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2592 GINT_TO_POINTER (wp_get_font_size_index (new_size_index, 12))))
2593 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2595 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2596 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
2597 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2603 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
2606 ModestMsgEditWindowPrivate *priv;
2607 gint new_font_index;
2608 ModestMsgEditWindow *window;
2611 window = MODEST_MSG_EDIT_WINDOW (userdata);
2612 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2613 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2615 if (gtk_check_menu_item_get_active (menu_item)) {
2618 label = gtk_bin_get_child (GTK_BIN (menu_item));
2620 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
2622 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2623 GINT_TO_POINTER(new_font_index)))
2624 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2626 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2627 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2628 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2634 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2637 ModestMsgEditWindowPrivate *priv = NULL;
2638 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2640 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2641 if (!priv->update_caption_visibility)
2644 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2646 gtk_widget_show (priv->cc_caption);
2648 gtk_widget_hide (priv->cc_caption);
2650 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2654 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2657 ModestMsgEditWindowPrivate *priv = NULL;
2658 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2660 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2661 if (!priv->update_caption_visibility)
2664 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2666 gtk_widget_show (priv->bcc_caption);
2668 gtk_widget_hide (priv->bcc_caption);
2670 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2674 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2675 ModestRecptEditor *editor)
2677 ModestMsgEditWindowPrivate *priv;
2679 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2680 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2682 /* we check for low-mem; in that case, show a warning, and don't allow
2683 * for the addressbook
2685 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2688 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2690 if (editor == NULL) {
2691 GtkWidget *view_focus;
2692 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2694 /* This code should be kept in sync with ModestRecptEditor. The
2695 textview inside the recpt editor is the one that really gets the
2696 focus. As it's inside a scrolled window, and this one inside the
2697 hbox recpt editor inherits from, we'll need to go up in the
2698 hierarchy to know if the text view is part of the recpt editor
2699 or if it's a different text entry */
2701 if (gtk_widget_get_parent (view_focus)) {
2702 GtkWidget *first_parent;
2704 first_parent = gtk_widget_get_parent (view_focus);
2705 if (gtk_widget_get_parent (first_parent) &&
2706 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2707 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2712 editor = MODEST_RECPT_EDITOR (priv->to_field);
2716 modest_address_book_select_addresses (editor);
2721 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2723 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2725 modest_msg_edit_window_open_addressbook (window, NULL);
2729 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2730 gboolean show_toolbar)
2732 ModestWindowPrivate *parent_priv;
2734 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2735 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2737 /* We can not just use the code of
2738 modest_msg_edit_window_setup_toolbar because it has a
2739 mixture of both initialization and creation code. */
2741 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2743 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2747 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2748 TnyHeaderFlags priority_flags)
2750 ModestMsgEditWindowPrivate *priv;
2751 ModestWindowPrivate *parent_priv;
2753 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2755 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2756 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2758 if (priv->priority_flags != priority_flags) {
2759 GtkAction *priority_action = NULL;
2761 priv->priority_flags = priority_flags;
2763 switch (priority_flags) {
2764 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2765 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2766 MODEST_HEADER_ICON_HIGH,
2767 HILDON_ICON_SIZE_XSMALL);
2768 gtk_widget_show (priv->priority_icon);
2769 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2770 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2772 case TNY_HEADER_FLAG_LOW_PRIORITY:
2773 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2774 MODEST_HEADER_ICON_LOW,
2775 HILDON_ICON_SIZE_XSMALL);
2776 gtk_widget_show (priv->priority_icon);
2777 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2778 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2781 gtk_widget_hide (priv->priority_icon);
2782 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2783 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2786 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2787 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2792 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2795 ModestMsgEditWindowPrivate *priv;
2796 ModestWindowPrivate *parent_priv;
2797 gint current_format;
2799 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2801 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2802 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2804 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2805 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2807 if (current_format != file_format) {
2808 switch (file_format) {
2809 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2810 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2811 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
2813 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2817 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2818 response = gtk_dialog_run (GTK_DIALOG (dialog));
2819 gtk_widget_destroy (dialog);
2820 if (response == GTK_RESPONSE_OK) {
2821 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2823 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
2824 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
2829 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2830 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2831 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2836 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2839 ModestMsgEditWindowPrivate *priv;
2840 WPTextBufferFormat oldfmt, fmt;
2841 gint old_position = 0;
2845 GdkColor *color = NULL;
2846 gboolean bold, bold_set, italic, italic_set;
2847 gboolean underline, underline_set;
2848 gboolean strikethrough, strikethrough_set;
2849 gboolean position_set;
2850 gboolean font_size_set, font_set, color_set;
2853 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2854 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2856 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2857 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
2858 GTK_WINDOW(dialog), GTK_WINDOW (window));
2860 /* First we get the currently selected font information */
2861 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2863 switch (oldfmt.text_position) {
2864 case TEXT_POSITION_NORMAL:
2867 case TEXT_POSITION_SUPERSCRIPT:
2875 g_object_set (G_OBJECT (dialog),
2876 "bold", oldfmt.bold != FALSE,
2877 "bold-set", !oldfmt.cs.bold,
2878 "underline", oldfmt.underline != FALSE,
2879 "underline-set", !oldfmt.cs.underline,
2880 "italic", oldfmt.italic != FALSE,
2881 "italic-set", !oldfmt.cs.italic,
2882 "strikethrough", oldfmt.strikethrough != FALSE,
2883 "strikethrough-set", !oldfmt.cs.strikethrough,
2884 "color", &oldfmt.color,
2885 "color-set", !oldfmt.cs.color,
2886 "size", wp_font_size[oldfmt.font_size],
2887 "size-set", !oldfmt.cs.font_size,
2888 "position", old_position,
2889 "position-set", !oldfmt.cs.text_position,
2890 "family", wp_get_font_name (oldfmt.font),
2891 "family-set", !oldfmt.cs.font,
2894 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2895 GTK_WINDOW (dialog), GTK_WINDOW (window));
2896 gtk_widget_show_all (dialog);
2897 priv->font_dialog = dialog;
2898 response = gtk_dialog_run (GTK_DIALOG (dialog));
2899 priv->font_dialog = NULL;
2900 if (response == GTK_RESPONSE_OK) {
2902 g_object_get( dialog,
2904 "bold-set", &bold_set,
2905 "underline", &underline,
2906 "underline-set", &underline_set,
2908 "italic-set", &italic_set,
2909 "strikethrough", &strikethrough,
2910 "strikethrough-set", &strikethrough_set,
2912 "color-set", &color_set,
2914 "size-set", &font_size_set,
2915 "family", &font_name,
2916 "family-set", &font_set,
2917 "position", &position,
2918 "position-set", &position_set,
2923 if (response == GTK_RESPONSE_OK) {
2924 memset(&fmt, 0, sizeof(fmt));
2930 fmt.italic = italic;
2931 fmt.cs.italic = TRUE;
2933 if (underline_set) {
2934 fmt.underline = underline;
2935 fmt.cs.underline = TRUE;
2937 if (strikethrough_set) {
2938 fmt.strikethrough = strikethrough;
2939 fmt.cs.strikethrough = TRUE;
2944 ? TEXT_POSITION_NORMAL
2945 : ( ( position == 1 )
2946 ? TEXT_POSITION_SUPERSCRIPT
2947 : TEXT_POSITION_SUBSCRIPT );
2948 fmt.cs.text_position = TRUE;
2949 fmt.font_size = oldfmt.font_size;
2953 fmt.cs.color = TRUE;
2956 fmt.font = wp_get_font_index(font_name,
2961 if (font_size_set) {
2962 fmt.cs.font_size = TRUE;
2963 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
2965 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2966 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2968 gtk_widget_destroy (dialog);
2970 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2974 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2976 ModestMsgEditWindowPrivate *priv;
2978 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2979 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2981 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2983 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2984 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2988 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
2990 ModestMsgEditWindowPrivate *priv;
2992 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2993 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2995 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
2997 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2998 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3003 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
3005 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3007 priv->can_undo = can_undo;
3011 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
3013 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3015 priv->can_redo = can_redo;
3019 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3021 ModestMsgEditWindowPrivate *priv;
3022 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3023 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3025 return priv->can_undo;
3029 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3031 ModestMsgEditWindowPrivate *priv;
3032 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3033 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3035 return priv->can_redo;
3040 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3043 GtkTextIter match_start, match_end;
3045 if (image_id == NULL)
3048 gtk_text_buffer_get_start_iter (buffer, &iter);
3050 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3051 GSList *tags = gtk_text_iter_get_tags (&match_start);
3053 for (node = tags; node != NULL; node = g_slist_next (node)) {
3054 GtkTextTag *tag = (GtkTextTag *) node->data;
3055 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3056 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3057 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3059 offset = gtk_text_iter_get_offset (&match_start);
3060 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3061 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3065 gtk_text_iter_forward_char (&iter);
3070 message_is_empty (ModestMsgEditWindow *window)
3072 ModestMsgEditWindowPrivate *priv = NULL;
3074 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3075 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3077 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3078 * so we can ignore markup.
3080 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3083 count = gtk_text_buffer_get_char_count (buf);
3089 msg_body_focus (GtkWidget *focus,
3090 GdkEventFocus *event,
3094 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3095 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3096 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3101 recpt_field_changed (GtkTextBuffer *buffer,
3102 ModestMsgEditWindow *editor)
3104 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3105 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3109 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3111 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3112 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3116 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3119 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3120 GtkTextBuffer *buffer;
3122 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3123 gtk_text_buffer_set_modified (buffer, modified);
3124 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3125 gtk_text_buffer_set_modified (buffer, modified);
3126 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3127 gtk_text_buffer_set_modified (buffer, modified);
3128 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3132 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3134 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3135 const char *account_name;
3136 GtkTextBuffer *buffer;
3138 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3139 if (gtk_text_buffer_get_modified (buffer))
3141 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3142 if (gtk_text_buffer_get_modified (buffer))
3144 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3145 if (gtk_text_buffer_get_modified (buffer))
3147 if (gtk_text_buffer_get_modified (priv->text_buffer))
3149 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3150 if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3161 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3163 ModestMsgEditWindowPrivate *priv = NULL;
3165 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3166 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3168 /* check if there's no recipient added */
3169 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3170 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3171 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3172 /* no recipient contents, then select contacts */
3173 modest_msg_edit_window_open_addressbook (window, NULL);
3177 g_object_ref (window);
3178 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3179 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3180 g_object_unref (window);
3183 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3184 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3185 g_object_unref (window);
3188 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3189 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3190 g_object_unref (window);
3194 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3195 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3196 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3197 g_object_unref (window);
3204 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3205 ModestMsgEditWindow *window)
3207 modest_msg_edit_window_offer_attach_file (window);
3211 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3213 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3215 return priv->clipboard_text;
3219 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3221 ModestMsgEditWindow *window)
3223 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3224 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3226 if (!GTK_WIDGET_VISIBLE (window))
3229 g_object_ref (window);
3230 text = gtk_clipboard_wait_for_text (selection_clipboard);
3232 if (priv->clipboard_text != NULL) {
3233 g_free (priv->clipboard_text);
3235 priv->clipboard_text = text;
3237 if (GTK_WIDGET_VISIBLE (window)) {
3238 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3240 g_object_unref (window);
3243 static gboolean clipboard_owner_change_idle (gpointer userdata)
3245 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3246 ModestMsgEditWindowPrivate *priv;
3248 gdk_threads_enter ();
3249 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3250 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3252 priv->clipboard_owner_idle = 0;
3253 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3254 gdk_threads_leave ();
3260 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3262 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3263 if (priv->clipboard_owner_idle == 0) {
3264 priv->clipboard_owner_idle = g_idle_add (clipboard_owner_change_idle, window);
3269 subject_field_move_cursor (GtkEntry *entry,
3270 GtkMovementStep step,
3275 if (!GTK_WIDGET_VISIBLE (window))
3278 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3282 update_window_title (ModestMsgEditWindow *window)
3284 ModestMsgEditWindowPrivate *priv = NULL;
3285 const gchar *subject;
3287 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3288 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3289 if (subject == NULL || subject[0] == '\0')
3290 subject = _("mail_va_new_email");
3292 gtk_window_set_title (GTK_WINDOW (window), subject);
3297 subject_field_changed (GtkEditable *editable,
3298 ModestMsgEditWindow *window)
3300 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3301 update_window_title (window);
3302 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3303 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3304 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3308 subject_field_insert_text (GtkEditable *editable,
3310 gint new_text_length,
3312 ModestMsgEditWindow *window)
3314 GString *result = g_string_new ("");
3316 gint result_len = 0;
3317 const gchar *entry_text = NULL;
3320 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3321 old_length = g_utf8_strlen (entry_text, -1);
3323 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3324 gunichar c = g_utf8_get_char_validated (current, 8);
3325 /* Invalid unichar, stop */
3331 result = g_string_append_unichar (result, c);
3335 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3336 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3339 /* Prevent endless recursion */
3340 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3341 g_signal_emit_by_name (editable, "insert-text",
3342 (gpointer) result->str, (gpointer) result->len,
3343 (gpointer) position, (gpointer) window);
3344 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3348 if (result_len + old_length > 1000) {
3349 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3350 _CS("ckdg_ib_maximum_characters_reached"));
3352 g_string_free (result, TRUE);
3356 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3359 ModestMsgEditWindowPrivate *priv = NULL;
3361 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3362 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3364 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3367 gtk_widget_show_all (priv->find_toolbar);
3368 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3370 gtk_widget_hide_all (priv->find_toolbar);
3371 gtk_widget_grab_focus (priv->msg_body);
3376 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3378 GtkTextIter *match_start,
3379 GtkTextIter *match_end)
3381 GtkTextIter end_iter;
3382 gchar *str_casefold;
3385 gchar *range_casefold;
3388 gboolean result = FALSE;
3395 gtk_text_iter_forward_to_end (&end_iter);
3397 str_casefold = g_utf8_casefold (str, -1);
3398 str_chars_n = strlen (str);
3400 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3401 range_casefold = g_utf8_casefold (range_text, -1);
3402 range_chars_n = strlen (range_casefold);
3404 if (range_chars_n < str_chars_n) {
3405 g_free (str_casefold);
3406 g_free (range_text);
3407 g_free (range_casefold);
3411 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3412 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3413 if (!g_utf8_collate (range_subtext, str_casefold)) {
3414 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3416 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3417 match_start, match_end, NULL);
3418 g_free (found_text);
3420 g_free (range_subtext);
3424 g_free (str_casefold);
3425 g_free (range_text);
3426 g_free (range_casefold);
3433 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3434 ModestMsgEditWindow *window)
3436 gchar *current_search = NULL;
3437 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3439 GtkTextIter selection_start, selection_end;
3440 GtkTextIter match_start, match_end;
3441 gboolean continue_search = FALSE;
3443 if (message_is_empty (window)) {
3444 g_free (priv->last_search);
3445 priv->last_search = NULL;
3446 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3450 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3451 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3452 g_free (current_search);
3453 g_free (priv->last_search);
3454 priv->last_search = NULL;
3455 /* Information banner about empty search */
3456 hildon_banner_show_information (NULL, NULL, _CS("ecdg_ib_find_rep_enter_text"));
3460 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3461 continue_search = TRUE;
3463 g_free (priv->last_search);
3464 priv->last_search = g_strdup (current_search);
3467 if (continue_search) {
3468 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3469 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3470 &match_start, &match_end);
3472 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_search_complete"));
3474 GtkTextIter buffer_start;
3475 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3476 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3477 &match_start, &match_end);
3479 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_no_matches"));
3482 /* Mark as selected the string found in search */
3484 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3485 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3486 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3488 g_free (priv->last_search);
3489 priv->last_search = NULL;
3491 g_free (current_search);
3495 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3497 ModestMsgEditWindowPrivate *priv;
3499 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3504 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3507 ModestMsgEditWindowPrivate *priv;
3509 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3514 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3515 ModestMsgEditWindow *window)
3517 modest_msg_edit_window_toggle_find_toolbar (window, FALSE);
3521 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3524 ModestMsgEditWindowPrivate *priv;
3525 TnyHeader *header = NULL;
3527 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3528 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3530 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3531 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3533 if (priv->draft_msg != NULL) {
3534 g_object_unref (priv->draft_msg);
3537 if (draft != NULL) {
3538 g_object_ref (draft);
3539 header = tny_msg_get_header (draft);
3540 if (priv->msg_uid) {
3541 g_free (priv->msg_uid);
3542 priv->msg_uid = NULL;
3544 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3545 if (GTK_WIDGET_REALIZED (window)) {
3546 if (!modest_window_mgr_register_window (mgr, MODEST_WINDOW (window), NULL)) {
3547 gtk_widget_destroy (GTK_WIDGET (window));
3553 priv->draft_msg = draft;
3557 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3558 GtkTextIter *start, GtkTextIter *end,
3561 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3562 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3565 if (tag == NULL) return;
3566 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3567 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3568 replace_with_images (window, priv->images);
3573 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3576 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3578 g_return_if_fail (TNY_IS_MIME_PART (part));
3579 tny_list_prepend (priv->attachments, (GObject *) part);
3580 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3581 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3582 gtk_widget_show_all (priv->attachments_caption);
3583 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3587 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3589 ModestMsgEditWindowPrivate *priv;
3591 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3592 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3594 return priv->msg_uid;
3598 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3599 ModestMsgEditWindowWidgetType widget_type)
3601 ModestMsgEditWindowPrivate *priv;
3603 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3604 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3606 switch (widget_type) {
3607 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3608 return priv->msg_body;
3610 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3611 return priv->to_field;
3613 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3614 return priv->cc_field;
3616 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3617 return priv->bcc_field;
3619 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3620 return priv->subject_field;
3622 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3623 return priv->attachments_view;
3631 remove_tags (WPTextBuffer *buffer)
3633 GtkTextIter start, end;
3635 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3636 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3638 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3642 on_account_removed (TnyAccountStore *account_store,
3643 TnyAccount *account,
3646 /* Do nothing if it's a store account, because we use the
3647 transport to send the messages */
3648 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3649 const gchar *parent_acc = NULL;
3650 const gchar *our_acc = NULL;
3652 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3653 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3654 /* Close this window if I'm showing a message of the removed account */
3655 if (strcmp (parent_acc, our_acc) == 0)
3656 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3661 from_field_changed (HildonPickerButton *button,
3662 ModestMsgEditWindow *self)
3664 ModestMsgEditWindowPrivate *priv;
3665 gboolean has_old_signature, has_new_signature;
3667 GtkTextIter match_start, match_end;
3668 ModestAccountMgr *mgr;
3670 gchar *full_signature;
3672 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3674 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
3675 mgr = modest_runtime_get_account_mgr ();
3676 signature = modest_account_mgr_get_signature (mgr, priv->last_from_account, &has_old_signature);
3677 if (has_old_signature) {
3678 full_signature = g_strconcat ("\n--\n", signature, NULL);
3679 if (gtk_text_iter_forward_search (&iter, full_signature, 0, &match_start, &match_end, NULL)) {
3680 gtk_text_buffer_delete (priv->text_buffer, &match_start, &match_end);
3682 } else if (gtk_text_iter_forward_search (&iter, _("mcen_ia_editor_original_message"), 0,
3683 &match_start, &match_end, NULL)) {
3686 g_free (full_signature);
3690 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3691 signature = modest_account_mgr_get_signature (mgr, priv->last_from_account, &has_new_signature);
3692 if (has_new_signature) {
3693 full_signature = g_strconcat ("\n--\n", signature, NULL);
3694 gtk_text_buffer_insert (priv->text_buffer, &iter, full_signature, -1);
3695 g_free (full_signature);
3700 typedef struct _MessageSettingsHelper {
3701 ModestMsgEditWindow *window;
3702 GSList *priority_group;
3703 GSList *format_group;
3704 GtkToggleButton *current_priority;
3705 GtkToggleButton *current_format;
3706 } MessageSettingsHelper;
3709 on_priority_toggle (GtkToggleButton *button,
3710 MessageSettingsHelper *helper)
3713 ModestMsgEditWindowPrivate *priv;
3715 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3716 if (gtk_toggle_button_get_active (button)) {
3718 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3719 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3720 if ((node_button != button) &&
3721 gtk_toggle_button_get_active (node_button)) {
3722 gtk_toggle_button_set_active (node_button, FALSE);
3725 helper->current_priority = button;
3727 gboolean found = FALSE;
3728 /* If no one is active, activate it again */
3729 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3730 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3731 if (gtk_toggle_button_get_active (node_button)) {
3737 gtk_toggle_button_set_active (button, TRUE);
3743 on_format_toggle (GtkToggleButton *button,
3744 MessageSettingsHelper *helper)
3747 ModestMsgEditWindowPrivate *priv;
3749 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3750 if (gtk_toggle_button_get_active (button)) {
3752 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
3753 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3754 if ((node_button != button) &&
3755 gtk_toggle_button_get_active (node_button)) {
3756 gtk_toggle_button_set_active (node_button, FALSE);
3759 helper->current_format = button;
3761 gboolean found = FALSE;
3762 /* If no one is active, activate it again */
3763 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
3764 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3765 if (gtk_toggle_button_get_active (node_button)) {
3771 gtk_toggle_button_set_active (button, TRUE);
3778 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
3782 GtkWidget *priority_hbox;
3783 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
3784 GtkWidget *captioned;
3785 GtkSizeGroup *title_sizegroup, *value_sizegroup;
3786 GtkWidget *format_hbox;
3787 GtkWidget *html_toggle, *text_toggle;
3788 ModestMsgEditWindowPrivate *priv;
3789 MessageSettingsHelper helper = {0,};
3791 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3792 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3793 helper.window = window;
3794 helper.priority_group = NULL;
3796 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3797 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3799 dialog = gtk_dialog_new_with_buttons (_("mcen_me_message_settings"), NULL,
3800 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
3801 _HL("wdgt_bd_done"), GTK_RESPONSE_ACCEPT, NULL);
3802 vbox = gtk_vbox_new (FALSE, 0);
3803 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), vbox);
3804 gtk_widget_show (vbox);
3806 /* Priority toggles */
3807 priority_hbox = gtk_hbox_new (TRUE, 0);
3808 high_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3809 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
3810 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
3811 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
3812 medium_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3813 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
3814 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
3815 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
3816 low_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3817 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
3818 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
3819 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
3820 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, TRUE, TRUE, 0);
3821 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, TRUE, TRUE, 0);
3822 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, TRUE, TRUE, 0);
3823 gtk_widget_show_all (priority_hbox);
3824 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
3825 _("mcen_me_editor_message_priority"), FALSE, priority_hbox);
3826 gtk_widget_show (captioned);
3827 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
3829 /* format toggles */
3830 format_hbox = gtk_hbox_new (TRUE, 0);
3831 html_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3832 gtk_button_set_label (GTK_BUTTON (html_toggle), _("mcen_me_editor_formatted_text"));
3833 helper.format_group = g_slist_prepend (helper.format_group, html_toggle);
3834 g_object_set_data (G_OBJECT (html_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_HTML));
3835 g_object_set_data (G_OBJECT (html_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_FORMATTED_TEXT));
3836 text_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3837 gtk_button_set_label (GTK_BUTTON (text_toggle), _("mcen_me_editor_plain_text"));
3838 helper.format_group = g_slist_prepend (helper.format_group, text_toggle);
3839 g_object_set_data (G_OBJECT (text_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_TEXT));
3840 g_object_set_data (G_OBJECT (text_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_PLAIN_TEXT));
3841 gtk_box_pack_start (GTK_BOX (format_hbox), html_toggle, TRUE, TRUE, 0);
3842 gtk_box_pack_start (GTK_BOX (format_hbox), text_toggle, TRUE, TRUE, 0);
3843 gtk_widget_show_all (format_hbox);
3844 gtk_widget_show (format_hbox);
3845 gtk_box_pack_start (GTK_BOX (vbox), format_hbox, FALSE, FALSE, 0);
3848 g_object_unref (title_sizegroup);
3849 g_object_unref (value_sizegroup);
3851 /* Set current values */
3852 switch (priv->priority_flags) {
3853 case TNY_HEADER_FLAG_HIGH_PRIORITY:
3854 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (high_toggle), TRUE);
3855 helper.current_priority = GTK_TOGGLE_BUTTON (high_toggle);
3857 case TNY_HEADER_FLAG_LOW_PRIORITY:
3858 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (low_toggle), TRUE);
3859 helper.current_priority = GTK_TOGGLE_BUTTON (low_toggle);
3862 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (medium_toggle), TRUE);
3863 helper.current_priority = GTK_TOGGLE_BUTTON (medium_toggle);
3867 switch (modest_msg_edit_window_get_format (window)) {
3868 case MODEST_MSG_EDIT_FORMAT_TEXT:
3869 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_toggle), TRUE);
3870 helper.current_format = GTK_TOGGLE_BUTTON (text_toggle);
3872 case MODEST_MSG_EDIT_FORMAT_HTML:
3874 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (html_toggle), TRUE);
3875 helper.current_format = GTK_TOGGLE_BUTTON (html_toggle);
3879 /* Signal connects */
3880 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3881 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3882 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3883 g_signal_connect (G_OBJECT (html_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
3884 g_signal_connect (G_OBJECT (text_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
3886 /* Save settings if the user clicked on done */
3887 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
3888 TnyHeaderFlags flags;
3889 ModestMsgEditFormat old_format, new_format;
3891 /* Set priority flags */
3892 flags = (TnyHeaderFlags) g_object_get_data (G_OBJECT (helper.current_priority), "priority");
3893 if (priv->priority_flags != flags)
3894 modest_msg_edit_window_set_priority_flags (window, flags);
3896 /* Set edit format */
3897 old_format = modest_msg_edit_window_get_format (window);
3898 new_format = (ModestMsgEditFormat) g_object_get_data (G_OBJECT (helper.current_format), "format");
3899 if (old_format != new_format) {
3900 gint file_format = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (helper.current_format), "file-format"));
3901 modest_msg_edit_window_set_file_format (window, file_format);
3905 gtk_widget_destroy (dialog);
3906 g_slist_free (helper.priority_group);
3910 on_message_settings (GtkAction *action,
3911 ModestMsgEditWindow *window)
3913 modest_msg_edit_window_show_msg_settings_dialog (window);
3917 on_cc_button_toggled (HildonCheckButton *button,
3918 ModestMsgEditWindow *window)
3920 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
3922 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
3923 hildon_check_button_get_active (button));
3927 on_bcc_button_toggled (HildonCheckButton *button,
3928 ModestMsgEditWindow *window)
3930 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
3932 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
3933 hildon_check_button_get_active (button));
3937 setup_menu (ModestMsgEditWindow *self)
3939 ModestMsgEditWindowPrivate *priv = NULL;
3941 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
3943 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3945 /* Settings menu buttons */
3946 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_checknames"), NULL,
3947 APP_MENU_CALLBACK (modest_ui_actions_on_check_names),
3949 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_undo"), "<Ctrl>z",
3950 APP_MENU_CALLBACK (modest_ui_actions_on_undo),
3951 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_undo));
3953 priv->cc_button = hildon_check_button_new (0);
3954 gtk_button_set_label (GTK_BUTTON (priv->cc_button), _("mcen_me_editor_showcc"));
3955 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button),
3957 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->cc_button),
3959 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
3960 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
3961 priv->bcc_button = hildon_check_button_new (0);
3962 gtk_button_set_label (GTK_BUTTON (priv->bcc_button), _("mcen_me_editor_showbcc"));
3963 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button),
3965 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->bcc_button),
3967 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
3968 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
3970 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_attach_inlineimage"), NULL,
3971 APP_MENU_CALLBACK (modest_ui_actions_on_insert_image),
3972 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_set_style));
3973 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_remove_attachments"), NULL,
3974 APP_MENU_CALLBACK (modest_ui_actions_on_remove_attachments),
3975 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
3976 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_message_settings"), NULL,
3977 APP_MENU_CALLBACK (on_message_settings),
3979 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_viewer_find"), "<Ctrl>f",
3980 APP_MENU_CALLBACK (modest_ui_actions_on_toggle_find_in_page),