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 insert = gtk_text_buffer_get_insert (priv->text_buffer);
516 gtk_text_buffer_get_iter_at_mark (priv->text_buffer, &iter, insert);
518 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &iter, &rectangle);
519 offset = priv->msg_body->allocation.y;
521 new_value = (offset + rectangle.y);
523 hildon_pannable_area_jump_to (HILDON_PANNABLE_AREA (priv->pannable), -1, new_value);
525 priv->correct_scroll_idle = 0;
530 correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused)
532 ModestMsgEditWindowPrivate *priv;
534 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
536 if (only_if_focused && !gtk_widget_is_focus (priv->msg_body))
539 if (priv->correct_scroll_idle > 0) {
543 priv->correct_scroll_idle = g_idle_add ((GSourceFunc) correct_scroll_without_drag_check_idle,
548 correct_scroll (ModestMsgEditWindow *w)
550 ModestMsgEditWindowPrivate *priv;
552 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
553 if (gtk_grab_get_current () == priv->msg_body) {
554 if (priv->scroll_drag_timeout_id == 0) {
555 priv->scroll_drag_timeout_id = g_timeout_add (500, (GSourceFunc) scroll_drag_timeout,
561 correct_scroll_without_drag_check (w, TRUE);
565 text_buffer_end_user_action (GtkTextBuffer *buffer,
566 ModestMsgEditWindow *userdata)
569 correct_scroll (userdata);
573 text_buffer_mark_set (GtkTextBuffer *buffer,
576 ModestMsgEditWindow *userdata)
578 gtk_text_buffer_begin_user_action (buffer);
579 gtk_text_buffer_end_user_action (buffer);
583 cut_clipboard_check (GtkTextView *text_view,
586 GtkTextBuffer *buffer;
588 buffer = gtk_text_view_get_buffer (text_view);
589 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
590 g_signal_stop_emission_by_name ((gpointer )text_view, "cut-clipboard");
595 copy_clipboard_check (GtkTextView *text_view,
598 GtkTextBuffer *buffer;
600 buffer = gtk_text_view_get_buffer (text_view);
601 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
602 g_signal_stop_emission_by_name ((gpointer )text_view, "copy-clipboard");
607 attachment_deleted (ModestAttachmentsView *attachments_view,
610 modest_msg_edit_window_remove_attachments (MODEST_MSG_EDIT_WINDOW (user_data),
615 connect_signals (ModestMsgEditWindow *obj)
617 ModestMsgEditWindowPrivate *priv;
619 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
621 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
622 G_CALLBACK (text_buffer_refresh_attributes), obj);
623 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
624 G_CALLBACK (text_buffer_can_undo), obj);
625 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
626 G_CALLBACK (text_buffer_can_redo), obj);
627 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
628 G_CALLBACK (body_changed), obj);
629 g_signal_connect (G_OBJECT (priv->text_buffer), "modified-changed",
630 G_CALLBACK (body_changed), obj);
631 g_signal_connect (G_OBJECT (priv->text_buffer), "end-user-action",
632 G_CALLBACK (text_buffer_end_user_action), obj);
633 g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
634 G_CALLBACK (text_buffer_mark_set), obj);
635 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
636 G_CALLBACK (text_buffer_apply_tag), obj);
637 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
638 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
639 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
640 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
641 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
642 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
644 g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
645 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
646 g_signal_connect (G_OBJECT (priv->from_field), "value-changed",
647 G_CALLBACK (from_field_changed), obj);
649 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
650 G_CALLBACK (msg_body_focus), obj);
651 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
652 G_CALLBACK (msg_body_focus), obj);
653 g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
654 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
655 "changed", G_CALLBACK (recpt_field_changed), obj);
656 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
657 "changed", G_CALLBACK (recpt_field_changed), obj);
658 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
659 "changed", G_CALLBACK (recpt_field_changed), obj);
660 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
661 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
662 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
664 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
665 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
667 priv->clipboard_change_handler_id =
668 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
669 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
670 priv->default_clipboard_change_handler_id =
671 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
672 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
674 g_signal_connect (G_OBJECT (priv->msg_body), "cut-clipboard", G_CALLBACK (cut_clipboard_check), NULL);
675 g_signal_connect (G_OBJECT (priv->msg_body), "copy-clipboard", G_CALLBACK (copy_clipboard_check), NULL);
676 g_signal_connect (G_OBJECT (priv->attachments_view), "delete", G_CALLBACK (attachment_deleted), obj);
680 init_wp_text_view_style ()
682 static gboolean initialized = FALSE;
685 gtk_rc_parse_string ("class \"WPTextView\" style \"fremantle-textview\"");
691 init_window (ModestMsgEditWindow *obj)
693 GtkWidget *to_caption, *subject_caption;
694 GtkWidget *main_vbox;
695 ModestMsgEditWindowPrivate *priv;
696 GtkActionGroup *action_group;
697 ModestWindowPrivate *parent_priv;
698 GdkPixbuf *window_icon = NULL;
699 GError *error = NULL;
701 GtkSizeGroup *title_size_group;
702 GtkSizeGroup *value_size_group;
703 GtkWidget *subject_box;
704 GtkWidget *attachment_icon;
705 GtkWidget *window_box;
706 #if (GTK_MINOR_VERSION >= 10)
707 GdkAtom deserialize_type;
710 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
711 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
713 parent_priv->ui_manager = gtk_ui_manager_new();
714 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
715 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
717 /* Add common actions */
718 gtk_action_group_add_actions (action_group,
719 modest_msg_edit_action_entries,
720 G_N_ELEMENTS (modest_msg_edit_action_entries),
722 gtk_action_group_add_actions (action_group,
723 hildon2_msg_edit_action_entries,
724 G_N_ELEMENTS (hildon2_msg_edit_action_entries),
726 gtk_action_group_add_toggle_actions (action_group,
727 modest_msg_edit_toggle_action_entries,
728 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
730 gtk_action_group_add_radio_actions (action_group,
731 modest_msg_edit_alignment_radio_action_entries,
732 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
734 G_CALLBACK (modest_ui_actions_on_change_justify),
736 gtk_action_group_add_radio_actions (action_group,
737 modest_msg_edit_priority_action_entries,
738 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
740 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
742 gtk_action_group_add_radio_actions (action_group,
743 modest_msg_edit_file_format_action_entries,
744 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
745 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
746 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
748 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
749 g_object_unref (action_group);
751 /* Load the UI definition */
752 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
755 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
756 g_clear_error (&error);
759 /* Add accelerators */
760 gtk_window_add_accel_group (GTK_WINDOW (obj),
761 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
763 parent_priv->menubar = NULL;
765 title_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
766 value_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
768 /* Note: This ModestPairList* must exist for as long as the picker
769 * that uses it, because the ModestSelectorPicker uses the ID opaquely,
770 * so it can't know how to manage its memory. */
771 priv->from_field = modest_selector_picker_new (MODEST_EDITABLE_SIZE,
772 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL,
774 modest_maemo_utils_set_hbutton_layout (title_size_group, value_size_group,
775 _("mail_va_from"), priv->from_field);
777 priv->to_field = modest_recpt_editor_new ();
778 priv->cc_field = modest_recpt_editor_new ();
779 priv->bcc_field = modest_recpt_editor_new ();
780 subject_box = gtk_hbox_new (FALSE, 0);
781 priv->priority_icon = gtk_image_new ();
782 gtk_box_pack_start (GTK_BOX (subject_box), priv->priority_icon, FALSE, FALSE, 0);
783 priv->subject_field = hildon_entry_new (MODEST_EDITABLE_SIZE);
784 gtk_entry_set_max_length (GTK_ENTRY (priv->subject_field) ,SUBJECT_MAX_LENGTH);
785 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
786 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
787 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
788 gtk_box_pack_start (GTK_BOX (subject_box), priv->subject_field, TRUE, TRUE, 0);
789 priv->add_attachment_button = hildon_button_new (MODEST_EDITABLE_SIZE, HILDON_BUTTON_ARRANGEMENT_VERTICAL);
790 gtk_widget_set_size_request (priv->add_attachment_button, ATTACHMENT_BUTTON_WIDTH, -1);
791 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
792 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
793 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, HILDON_ICON_SIZE_FINGER);
794 hildon_button_set_image (HILDON_BUTTON (priv->add_attachment_button), attachment_icon);
795 gtk_box_pack_start (GTK_BOX (subject_box), priv->add_attachment_button, FALSE, FALSE, 0);
796 priv->attachments_view = modest_attachments_view_new (NULL);
797 modest_attachments_view_set_style (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
798 MODEST_ATTACHMENTS_VIEW_STYLE_NO_FOCUS);
800 priv->header_box = gtk_vbox_new (FALSE, 0);
802 to_caption = modest_maemo_utils_create_captioned_with_size_type
803 (title_size_group, value_size_group,
804 _("mail_va_to"), FALSE, priv->to_field,
805 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
806 priv->cc_caption = modest_maemo_utils_create_captioned_with_size_type
807 (title_size_group, value_size_group,
808 _("mail_va_cc"), FALSE, priv->cc_field,
809 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
810 priv->bcc_caption = modest_maemo_utils_create_captioned_with_size_type
811 (title_size_group, value_size_group,
812 _("mail_va_hotfix1"), FALSE, priv->bcc_field,
813 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
814 subject_caption = modest_maemo_utils_create_captioned (title_size_group, value_size_group,
815 _("mail_va_subject"), FALSE, subject_box);
816 priv->attachments_caption = modest_maemo_utils_create_captioned_with_size_type (title_size_group, value_size_group,
817 _("mail_va_attachment"),
819 priv->attachments_view,
820 HILDON_SIZE_AUTO_WIDTH |
821 HILDON_SIZE_AUTO_HEIGHT);
822 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), value_size_group); */
823 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), value_size_group); */
824 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), value_size_group); */
825 g_object_unref (title_size_group);
826 g_object_unref (value_size_group);
828 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->from_field, FALSE, FALSE, 0);
829 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
830 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
831 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
832 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
833 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
834 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
836 init_wp_text_view_style ();
838 priv->msg_body = wp_text_view_new ();
841 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
842 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
843 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
844 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
845 #if (GTK_MINOR_VERSION >= 10)
846 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
847 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
849 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
850 deserialize_type, TRUE);
852 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
854 priv->find_toolbar = hildon_find_toolbar_new (NULL);
855 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
857 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
859 priv->pannable = hildon_pannable_area_new ();
861 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
863 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
864 priv->frame = gtk_frame_new (NULL);
865 gtk_box_pack_start (GTK_BOX(main_vbox), priv->frame, TRUE, TRUE, 0);
867 hildon_pannable_area_add_with_viewport (HILDON_PANNABLE_AREA (priv->pannable), main_vbox);
868 gtk_container_set_focus_vadjustment (GTK_CONTAINER (main_vbox),
869 hildon_pannable_area_get_vadjustment (HILDON_PANNABLE_AREA (priv->pannable)));
870 gtk_widget_show_all (GTK_WIDGET(priv->pannable));
872 window_box = gtk_vbox_new (FALSE, 0);
873 gtk_container_add (GTK_CONTAINER(obj), window_box);
875 gtk_box_pack_start (GTK_BOX (window_box), priv->pannable, TRUE, TRUE, 0);
877 gtk_container_add (GTK_CONTAINER (priv->frame), priv->msg_body);
879 /* Set window icon */
880 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
882 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
883 g_object_unref (window_icon);
888 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
890 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
892 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
893 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
894 priv->clipboard_change_handler_id))
895 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
896 priv->clipboard_change_handler_id);
897 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
898 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
899 priv->default_clipboard_change_handler_id))
900 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
901 priv->default_clipboard_change_handler_id);
903 if (priv->account_removed_handler_id &&
904 g_signal_handler_is_connected (modest_runtime_get_account_store (),
905 priv->account_removed_handler_id))
906 g_signal_handler_disconnect(modest_runtime_get_account_store (),
907 priv->account_removed_handler_id);
911 modest_msg_edit_window_finalize (GObject *obj)
913 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
915 /* Sanity check: shouldn't be needed, the window mgr should
916 call this function before */
917 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
919 if (priv->font_dialog != NULL) {
920 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
923 if (priv->clipboard_text != NULL) {
924 g_free (priv->clipboard_text);
925 priv->clipboard_text = NULL;
928 if (priv->draft_msg != NULL) {
929 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
930 if (TNY_IS_HEADER (header)) {
931 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
932 modest_window_mgr_unregister_header (mgr, header);
934 g_object_unref (priv->draft_msg);
935 priv->draft_msg = NULL;
937 if (priv->outbox_msg != NULL) {
938 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
939 if (TNY_IS_HEADER (header)) {
940 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
941 modest_window_mgr_unregister_header (mgr, header);
943 g_object_unref (priv->outbox_msg);
944 priv->outbox_msg = NULL;
946 if (priv->correct_scroll_idle > 0) {
947 g_source_remove (priv->correct_scroll_idle);
948 priv->correct_scroll_idle = 0;
950 if (priv->scroll_drag_timeout_id > 0) {
951 g_source_remove (priv->scroll_drag_timeout_id);
952 priv->scroll_drag_timeout_id = 0;
954 if (priv->clipboard_owner_idle > 0) {
955 g_source_remove (priv->clipboard_owner_idle);
956 priv->clipboard_owner_idle = 0;
958 if (priv->original_account_name)
959 g_free (priv->original_account_name);
960 g_free (priv->msg_uid);
961 g_free (priv->last_search);
962 g_slist_free (priv->font_items_group);
963 g_slist_free (priv->size_items_group);
964 g_object_unref (priv->attachments);
965 g_object_unref (priv->images);
967 /* This had to stay alive for as long as the picker that used it: */
968 modest_pair_list_free (priv->from_field_protos);
970 G_OBJECT_CLASS(parent_class)->finalize (obj);
974 pixbuf_from_stream (TnyStream *stream, const gchar *mime_type, guint64 *stream_size)
976 GdkPixbufLoader *loader;
982 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
984 if (loader == NULL) {
990 tny_stream_reset (TNY_STREAM (stream));
991 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
992 GError *error = NULL;
993 unsigned char read_buffer[128];
995 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
997 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
999 g_error_free (error);
1004 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1006 g_object_ref (pixbuf);
1007 gdk_pixbuf_loader_close (loader, NULL);
1008 g_object_unref (loader);
1013 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1014 GdkPixbuf *new_pixbuf;
1016 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1017 gdk_pixbuf_get_width (pixbuf);
1018 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1019 g_object_unref (pixbuf);
1020 pixbuf = new_pixbuf;
1024 *stream_size = size;
1030 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1032 ModestMsgEditWindowPrivate *priv;
1035 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1037 for (iter = tny_list_create_iterator (attachments);
1038 !tny_iterator_is_done (iter);
1039 tny_iterator_next (iter)) {
1040 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1041 const gchar *cid = tny_mime_part_get_content_id (part);
1042 const gchar *mime_type = tny_mime_part_get_content_type (part);
1043 if ((cid != NULL)&&(mime_type != NULL)) {
1044 guint64 stream_size;
1045 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1046 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
1049 g_object_unref (stream);
1051 if (pixbuf != NULL) {
1052 priv->images_count ++;
1053 priv->images_size += stream_size;
1054 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1055 g_object_unref (pixbuf);
1058 g_object_unref (part);
1060 g_object_unref (iter);
1064 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1066 TnyMimePart *parent = NULL;
1067 const gchar *content_type = NULL;
1068 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1070 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1072 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1073 parent = g_object_ref (msg);
1074 } else if (content_type && !g_strcasecmp (content_type, "multipart/mixed")) {
1075 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1078 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1079 iter = tny_list_create_iterator (parts);
1080 while (!tny_iterator_is_done (iter)) {
1082 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1083 content_type = tny_mime_part_get_content_type (part);
1084 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1088 g_object_unref (part);
1090 tny_iterator_next (iter);
1092 g_object_unref (iter);
1093 g_object_unref (parts);
1096 if (parent != NULL) {
1097 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1100 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1101 iter = tny_list_create_iterator (parts);
1102 while (!tny_iterator_is_done (iter)) {
1104 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1105 content_type = tny_mime_part_get_content_type (part);
1106 if (content_type && g_str_has_prefix (content_type, "image/")) {
1107 tny_list_prepend (priv->images, (GObject *) part);
1109 g_object_unref (part);
1110 tny_iterator_next (iter);
1112 g_object_unref (iter);
1113 g_object_unref (parts);
1114 g_object_unref (parent);
1119 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1122 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1124 for (iter = tny_list_create_iterator (attachments) ;
1125 !tny_iterator_is_done (iter);
1126 tny_iterator_next (iter)) {
1127 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1128 const gchar *cid = tny_mime_part_get_content_id (part);
1130 char *invalid = NULL;
1131 gint int_cid = strtol (cid, &invalid, 10);
1132 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1133 priv->next_cid = int_cid + 1;
1136 g_object_unref (part);
1138 g_object_unref (iter);
1142 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1145 gchar *to, *cc, *bcc, *subject;
1147 ModestMsgEditWindowPrivate *priv;
1148 ModestWindowPrivate *parent_priv;
1150 TnyHeaderFlags priority_flags;
1151 TnyFolder *msg_folder;
1152 gboolean is_html = FALSE;
1153 gboolean field_view_set;
1155 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1156 g_return_if_fail (TNY_IS_MSG (msg));
1158 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1159 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1161 header = tny_msg_get_header (msg);
1162 to = tny_header_dup_to (header);
1163 cc = tny_header_dup_cc (header);
1164 bcc = tny_header_dup_bcc (header);
1165 subject = tny_header_dup_subject (header);
1166 priority_flags = tny_header_get_priority (header);
1169 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
1171 field_view_set = TRUE;
1173 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
1174 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1175 gtk_widget_show (priv->cc_caption);
1176 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1177 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1178 gtk_widget_hide (priv->cc_caption);
1179 field_view_set = FALSE;
1181 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button), field_view_set);
1183 field_view_set = TRUE;
1185 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
1186 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1187 gtk_widget_show (priv->bcc_caption);
1188 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1189 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1190 gtk_widget_hide (priv->bcc_caption);
1191 field_view_set = FALSE;
1193 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button), field_view_set);
1197 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1198 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1201 update_window_title (self);
1203 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1204 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1206 if ((body == NULL)||(body[0] == '\0')) {
1208 body = modest_text_utils_convert_to_html ("");
1211 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1212 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1215 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1218 /* Add attachments to the view */
1219 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1220 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1221 if (tny_list_get_length (priv->attachments) == 0) {
1222 gtk_widget_hide (priv->attachments_caption);
1224 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1225 gtk_widget_show_all (priv->attachments_caption);
1227 get_related_images (self, msg);
1228 update_next_cid (self, priv->attachments);
1229 update_next_cid (self, priv->images);
1230 replace_with_images (self, priv->images);
1232 if (preserve_is_rich && !is_html) {
1233 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1234 /* Get the default format required from configuration */
1235 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1236 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1239 /* Set the default focus depending on having already a To: field or not */
1240 if ((!to)||(*to == '\0')) {
1241 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1243 gtk_widget_grab_focus (priv->msg_body);
1246 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1248 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1249 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1251 modest_msg_edit_window_set_modified (self, FALSE);
1253 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1254 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1255 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1256 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1258 if (priv->msg_uid) {
1259 g_free (priv->msg_uid);
1260 priv->msg_uid = NULL;
1263 /* we should set a reference to the incoming message if it is a draft */
1264 msg_folder = tny_msg_get_folder (msg);
1266 if (modest_tny_folder_is_local_folder (msg_folder)) {
1267 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1268 if (type == TNY_FOLDER_TYPE_INVALID)
1269 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1271 if (type == TNY_FOLDER_TYPE_DRAFTS)
1272 priv->draft_msg = g_object_ref(msg);
1273 if (type == TNY_FOLDER_TYPE_OUTBOX)
1274 priv->outbox_msg = g_object_ref(msg);
1275 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1277 g_object_unref (msg_folder);
1287 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
1290 GList *item_children, *node;
1291 GtkWidget *bin_child;
1293 bin_child = gtk_bin_get_child (GTK_BIN(item));
1295 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
1297 for (node = item_children; node != NULL; node = g_list_next (node)) {
1298 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
1299 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
1302 g_list_free (item_children);
1306 menu_tool_button_dont_expand (GtkMenuToolButton *item)
1309 GList *item_children, *node;
1311 box = gtk_bin_get_child (GTK_BIN (item));
1312 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
1313 item_children = gtk_container_get_children (GTK_CONTAINER (box));
1315 for (node = item_children; node != NULL; node = g_list_next (node)) {
1316 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
1317 if (GTK_IS_TOGGLE_BUTTON (node->data))
1318 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
1319 else if (GTK_IS_BUTTON (node->data))
1320 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
1322 g_list_free (item_children);
1327 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1329 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1330 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1331 GtkWidget *placeholder;
1332 GtkWidget *tool_item;
1337 GtkWidget *sizes_menu;
1338 GtkWidget *fonts_menu;
1339 GSList *radio_group = NULL;
1340 GSList *node = NULL;
1344 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1345 gtk_toolbar_set_show_arrow (GTK_TOOLBAR (parent_priv->toolbar), FALSE);
1346 gtk_toolbar_set_icon_size (GTK_TOOLBAR (parent_priv->toolbar), HILDON_ICON_SIZE_FINGER);
1347 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1349 /* Font color placeholder */
1350 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1351 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1354 priv->font_color_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1355 priv->font_color_button = hildon_color_button_new ();
1356 gtk_widget_set_size_request (priv->font_color_button, -1, 48);
1357 GTK_WIDGET_UNSET_FLAGS (priv->font_color_toolitem, GTK_CAN_FOCUS);
1358 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1359 gtk_container_add (GTK_CONTAINER (priv->font_color_toolitem), priv->font_color_button);
1360 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1361 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1362 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->font_color_toolitem), insert_index);
1363 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1365 G_CALLBACK (modest_msg_edit_window_color_button_change),
1368 /* Font size and face placeholder */
1369 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1370 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1372 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1373 priv->size_tool_button_label = gtk_label_new (NULL);
1374 hildon_helper_set_logical_color (GTK_WIDGET (priv->size_tool_button_label), GTK_RC_TEXT,
1375 GTK_STATE_INSENSITIVE, "SecondaryTextColor");
1376 hildon_helper_set_logical_color (GTK_WIDGET (priv->size_tool_button_label), GTK_RC_FG,
1377 GTK_STATE_INSENSITIVE, "SecondaryTextColor");
1378 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1379 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1380 size_text,"</span>", NULL);
1381 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1383 hildon_helper_set_logical_font (priv->size_tool_button_label, "LargeSystemFont");
1384 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
1385 sizes_menu = gtk_menu_new ();
1386 priv->size_items_group = NULL;
1388 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1389 GtkWidget *size_menu_item;
1391 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1392 size_menu_item = gtk_radio_menu_item_new_with_label (radio_group, size_text);
1393 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (size_menu_item));
1394 gtk_menu_shell_append (GTK_MENU_SHELL (sizes_menu), size_menu_item);
1395 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (size_menu_item), (wp_font_size[size_index] == 12));
1396 gtk_widget_show (size_menu_item);
1398 priv->size_items_group = g_slist_prepend (priv->size_items_group, size_menu_item);
1402 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1403 GtkWidget *item = (GtkWidget *) node->data;
1404 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_size_change),
1408 priv->size_items_group = g_slist_reverse (priv->size_items_group);
1409 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), sizes_menu);
1410 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1411 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1412 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), FALSE);
1413 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), FALSE);
1414 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1415 priv->font_size_toolitem = tool_item;
1418 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1419 priv->font_tool_button_label = gtk_label_new (NULL);
1420 hildon_helper_set_logical_color (GTK_WIDGET (priv->font_tool_button_label), GTK_RC_TEXT,
1421 GTK_STATE_INSENSITIVE, "SecondaryTextColor");
1422 hildon_helper_set_logical_color (GTK_WIDGET (priv->font_tool_button_label), GTK_RC_FG,
1423 GTK_STATE_INSENSITIVE, "SecondaryTextColor");
1424 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1425 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1427 hildon_helper_set_logical_font (priv->font_tool_button_label, "LargeSystemFont");
1428 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
1429 fonts_menu = gtk_menu_new ();
1430 priv->font_items_group = NULL;
1432 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1433 GtkWidget *font_menu_item;
1434 GtkWidget *child_label;
1436 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
1437 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
1438 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
1439 wp_get_font_name (font_index), "</span>", NULL);
1440 gtk_label_set_markup (GTK_LABEL (child_label), markup);
1443 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
1444 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
1445 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
1446 gtk_widget_show (font_menu_item);
1448 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
1451 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1452 GtkWidget *item = (GtkWidget *) node->data;
1453 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
1456 priv->font_items_group = g_slist_reverse (priv->font_items_group);
1457 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
1458 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1459 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1460 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), FALSE);
1461 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), FALSE);
1462 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1463 priv->font_face_toolitem = tool_item;
1465 /* Set expand and homogeneous for remaining items */
1466 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
1467 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1468 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1469 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
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/ActionsItalics");
1473 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1474 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1476 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1477 will not show the tool items added to the placeholders) */
1478 gtk_widget_show_all (parent_priv->toolbar);
1480 /* Set the no show all *after* showing all items. We do not
1481 want the toolbar to be shown with a show all because it
1482 could go agains the gconf setting regarding showing or not
1483 the toolbar of the editor window */
1484 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1490 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, gboolean preserve_is_rich)
1493 ModestWindowPrivate *parent_priv;
1494 ModestMsgEditWindowPrivate *priv;
1495 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1496 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1497 ModestWindowMgr *mgr = NULL;
1499 g_return_val_if_fail (msg, NULL);
1500 g_return_val_if_fail (account_name, NULL);
1502 mgr = modest_runtime_get_window_mgr ();
1504 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1506 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1507 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1509 /* Menubar. Update the state of some toggles */
1510 priv->from_field_protos = get_transports ();
1511 modest_selector_picker_set_pair_list (MODEST_SELECTOR_PICKER (priv->from_field), priv->from_field_protos);
1512 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1513 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1514 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1516 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1517 hildon_touch_selector_get_current_text
1518 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1519 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1520 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1523 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1525 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1527 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1529 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1531 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1532 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1533 /* Add common dimming rules */
1534 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1535 modest_msg_edit_window_toolbar_dimming_entries,
1536 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1537 MODEST_WINDOW (obj));
1538 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_toolitem,
1539 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1540 MODEST_WINDOW (obj));
1541 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_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_face_toolitem,
1545 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1546 MODEST_WINDOW (obj));
1547 /* Insert dimming rules group for this window */
1548 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1549 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1551 /* Setup app menu */
1552 setup_menu (MODEST_MSG_EDIT_WINDOW (obj));
1554 /* Checks the dimming rules */
1555 g_object_unref (toolbar_rules_group);
1556 g_object_unref (clipboard_rules_group);
1557 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1559 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1561 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1562 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1563 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1564 priv->update_caption_visibility = TRUE;
1566 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1568 /* Track account-removed signal, this window should be closed
1569 in the case we're creating a mail associated to the account
1571 priv->account_removed_handler_id =
1572 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1574 G_CALLBACK(on_account_removed),
1577 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1579 return (ModestWindow*) obj;
1583 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1585 GString **string_buffer = (GString **) user_data;
1587 *string_buffer = g_string_append (*string_buffer, buffer);
1593 * @result: A new string which should be freed with g_free().
1596 get_formatted_data (ModestMsgEditWindow *edit_window)
1598 ModestMsgEditWindowPrivate *priv;
1599 GString *string_buffer = g_string_new ("");
1601 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1603 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1605 modest_text_utils_hyperlinkify (string_buffer);
1607 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1609 return g_string_free (string_buffer, FALSE);
1614 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1617 const gchar *account_name;
1618 ModestMsgEditWindowPrivate *priv;
1619 TnyIterator *att_iter;
1621 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1623 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1625 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1626 g_return_val_if_fail (account_name, NULL);
1629 /* don't free these (except from) */
1630 data = g_slice_new0 (MsgData);
1631 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1633 data->account_name = g_strdup (account_name);
1634 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1635 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1636 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1637 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1638 if (priv->draft_msg) {
1639 data->draft_msg = g_object_ref (priv->draft_msg);
1640 } else if (priv->outbox_msg) {
1641 data->draft_msg = g_object_ref (priv->outbox_msg);
1643 data->draft_msg = NULL;
1646 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1648 gtk_text_buffer_get_bounds (buf, &b, &e);
1649 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1651 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1652 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1654 data->html_body = NULL;
1656 /* deep-copy the data */
1657 att_iter = tny_list_create_iterator (priv->attachments);
1658 data->attachments = NULL;
1659 while (!tny_iterator_is_done (att_iter)) {
1660 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1661 if (!(TNY_IS_MIME_PART(part))) {
1662 g_warning ("strange data in attachment list");
1663 g_object_unref (part);
1664 tny_iterator_next (att_iter);
1667 data->attachments = g_list_append (data->attachments,
1669 tny_iterator_next (att_iter);
1671 g_object_unref (att_iter);
1673 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1674 att_iter = tny_list_create_iterator (priv->images);
1675 data->images = NULL;
1676 while (!tny_iterator_is_done (att_iter)) {
1677 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1679 if (!(TNY_IS_MIME_PART(part))) {
1680 g_warning ("strange data in attachment list");
1681 g_object_unref (part);
1682 tny_iterator_next (att_iter);
1685 cid = tny_mime_part_get_content_id (part);
1687 gchar *image_tag_id;
1688 GtkTextTag *image_tag;
1690 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1691 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1692 g_free (image_tag_id);
1694 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1696 ((gtk_text_iter_has_tag (&iter, image_tag))||
1697 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1698 data->images = g_list_append (data->images,
1699 g_object_ref (part));
1701 g_object_unref (part);
1702 tny_iterator_next (att_iter);
1704 g_object_unref (att_iter);
1706 data->priority_flags = priv->priority_flags;
1713 unref_gobject (GObject *obj, gpointer data)
1715 if (!G_IS_OBJECT(obj))
1717 g_object_unref (obj);
1721 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1724 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1732 g_free (data->from);
1733 g_free (data->subject);
1734 g_free (data->plain_body);
1735 g_free (data->html_body);
1736 g_free (data->account_name);
1738 if (data->draft_msg != NULL) {
1739 g_object_unref (data->draft_msg);
1740 data->draft_msg = NULL;
1743 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1744 g_list_free (data->attachments);
1745 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1746 g_list_free (data->images);
1748 g_slice_free (MsgData, data);
1752 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1754 guint64 *parts_size)
1756 ModestMsgEditWindowPrivate *priv;
1758 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1760 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1762 /* TODO: add images */
1763 *parts_size += priv->images_size;
1764 *parts_count += priv->images_count;
1769 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1772 ModestMsgEditWindowPrivate *priv = NULL;
1773 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1775 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1777 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1779 return MODEST_MSG_EDIT_FORMAT_HTML;
1781 return MODEST_MSG_EDIT_FORMAT_TEXT;
1785 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1786 ModestMsgEditFormat format)
1788 ModestMsgEditWindowPrivate *priv;
1790 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1791 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1794 case MODEST_MSG_EDIT_FORMAT_HTML:
1795 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1797 case MODEST_MSG_EDIT_FORMAT_TEXT:
1798 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1801 g_return_if_reached ();
1805 ModestMsgEditFormatState *
1806 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1808 ModestMsgEditFormatState *format_state = NULL;
1809 ModestMsgEditWindowPrivate *priv;
1810 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1812 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1813 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1815 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1817 format_state = g_new0 (ModestMsgEditFormatState, 1);
1818 format_state->bold = buffer_format->bold&0x1;
1819 format_state->italics = buffer_format->italic&0x1;
1820 format_state->bullet = buffer_format->bullet&0x1;
1821 format_state->color = buffer_format->color;
1822 format_state->font_size = buffer_format->font_size;
1823 format_state->font_family = wp_get_font_name (buffer_format->font);
1824 format_state->justification = buffer_format->justification;
1825 g_free (buffer_format);
1827 return format_state;
1832 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1833 const ModestMsgEditFormatState *format_state)
1835 ModestMsgEditWindowPrivate *priv;
1836 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1837 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1838 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1839 g_return_if_fail (format_state != NULL);
1841 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1842 gtk_widget_grab_focus (priv->msg_body);
1843 buffer_format->bold = (format_state->bold != FALSE);
1844 buffer_format->italic = (format_state->italics != FALSE);
1845 buffer_format->color = format_state->color;
1846 buffer_format->font_size = format_state->font_size;
1847 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1848 buffer_format->justification = format_state->justification;
1849 buffer_format->bullet = format_state->bullet;
1851 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1853 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1854 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1855 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1856 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1857 buffer_format->cs.font = (buffer_format->font != current_format->font);
1858 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1859 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1861 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1862 if (buffer_format->cs.bold) {
1863 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
1864 GINT_TO_POINTER (buffer_format->bold&0x1));
1866 if (buffer_format->cs.italic) {
1867 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
1868 GINT_TO_POINTER (buffer_format->italic&0x1));
1870 if (buffer_format->cs.color) {
1871 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1872 GINT_TO_POINTER (&(buffer_format->color)));
1874 if (buffer_format->cs.font_size) {
1875 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1876 GINT_TO_POINTER (buffer_format->font_size));
1878 if (buffer_format->cs.justification) {
1879 switch (buffer_format->justification) {
1880 case GTK_JUSTIFY_LEFT:
1881 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
1882 GINT_TO_POINTER(TRUE));
1884 case GTK_JUSTIFY_CENTER:
1885 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
1886 GINT_TO_POINTER(TRUE));
1888 case GTK_JUSTIFY_RIGHT:
1889 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
1890 GINT_TO_POINTER(TRUE));
1897 if (buffer_format->cs.font) {
1898 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1899 GINT_TO_POINTER (buffer_format->font));
1901 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1902 if (buffer_format->cs.bullet) {
1903 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
1904 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
1906 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1908 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
1910 g_free (buffer_format);
1911 g_free (current_format);
1913 /* Check dimming rules */
1914 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1915 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1919 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1921 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1923 ModestWindowPrivate *parent_priv;
1924 ModestMsgEditWindowPrivate *priv;
1925 GtkWidget *new_size_menuitem;
1926 GtkWidget *new_font_menuitem;
1928 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1929 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1931 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1932 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu");
1933 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1934 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1936 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatPlainTextMenu");
1937 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1938 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1941 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1943 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1944 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1946 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1947 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1949 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
1950 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
1953 switch (buffer_format->justification)
1955 case GTK_JUSTIFY_LEFT:
1956 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
1958 case GTK_JUSTIFY_CENTER:
1959 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
1961 case GTK_JUSTIFY_RIGHT:
1962 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
1969 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
1971 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1972 G_CALLBACK (modest_msg_edit_window_color_button_change),
1974 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1975 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1976 G_CALLBACK (modest_msg_edit_window_color_button_change),
1979 new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group,
1980 buffer_format->font_size))->data);
1981 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1985 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1986 markup = g_strconcat ("<span font_family='Sans'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1987 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1989 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1990 G_CALLBACK (modest_msg_edit_window_size_change),
1992 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
1993 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
1994 G_CALLBACK (modest_msg_edit_window_size_change),
1998 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
1999 buffer_format->font))->data);
2000 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
2004 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
2005 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2006 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2008 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
2009 G_CALLBACK (modest_msg_edit_window_font_change),
2011 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
2012 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
2013 G_CALLBACK (modest_msg_edit_window_font_change),
2017 g_free (buffer_format);
2021 #ifdef MODEST_HILDON_VERSION_0
2023 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2026 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2027 ModestMsgEditWindowPrivate *priv;
2028 GtkWidget *dialog = NULL;
2030 GdkColor *new_color = NULL;
2032 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2033 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2035 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2036 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
2037 g_free (buffer_format);
2039 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2040 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2041 if (new_color != NULL) {
2042 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2043 (gpointer) new_color);
2046 gtk_widget_destroy (dialog);
2051 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2054 ModestMsgEditWindowPrivate *priv;
2055 GtkWidget *dialog = NULL;
2057 GdkColor *old_color = NULL;
2058 const GdkColor *new_color = NULL;
2060 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2061 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2063 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2064 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2066 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2067 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2068 if (new_color != NULL)
2069 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2071 gtk_widget_destroy (dialog);
2077 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2080 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2081 ModestMsgEditWindowPrivate *priv;
2082 GtkWidget *dialog = NULL;
2084 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2085 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2087 dialog = hildon_color_chooser_new ();
2088 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2089 g_free (buffer_format);
2091 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2093 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2094 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2097 gtk_widget_destroy (dialog);
2102 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2105 ModestMsgEditWindowPrivate *priv;
2106 GtkWidget *dialog = NULL;
2107 GdkColor *old_color = NULL;
2109 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2110 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2112 dialog = hildon_color_chooser_new ();
2113 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2115 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2117 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2118 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2120 gtk_widget_destroy (dialog);
2123 #endif /*!MODEST_HILDON_VERSION_0*/
2128 create_stream_for_uri (const gchar* uri)
2133 TnyStream *result = NULL;
2135 GnomeVFSHandle *handle = NULL;
2136 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2137 if (test == GNOME_VFS_OK) {
2138 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2139 /* Streams over OBEX (Bluetooth) are not seekable but
2140 * we expect them to be (we might need to read them
2141 * several times). So if this is a Bluetooth URI just
2142 * read the whole file into memory (this is not a fast
2143 * protocol so we can assume that these files are not
2144 * going to be very big) */
2145 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2146 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2147 TnyStream *memstream = tny_camel_mem_stream_new ();
2148 tny_stream_write_to_stream (vfssstream, memstream);
2149 g_object_unref (vfssstream);
2152 result = vfssstream;
2160 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2163 ModestMsgEditWindowPrivate *priv;
2164 GtkWidget *dialog = NULL;
2166 GSList *uris = NULL;
2167 GSList *uri_node = NULL;
2169 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2171 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2172 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2173 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2175 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2177 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2178 GTK_WINDOW (dialog), GTK_WINDOW (window));
2180 response = gtk_dialog_run (GTK_DIALOG (dialog));
2182 case GTK_RESPONSE_OK:
2183 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2188 gtk_widget_destroy (dialog);
2190 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2192 GnomeVFSHandle *handle = NULL;
2193 GnomeVFSResult result;
2194 GtkTextIter position;
2195 GtkTextMark *insert_mark;
2197 uri = (const gchar *) uri_node->data;
2198 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2199 if (result == GNOME_VFS_OK) {
2201 GnomeVFSFileInfo *info;
2202 gchar *filename, *basename, *escaped_filename;
2203 TnyMimePart *mime_part;
2205 const gchar *mime_type = NULL;
2206 GnomeVFSURI *vfs_uri;
2207 guint64 stream_size;
2209 gnome_vfs_close (handle);
2210 vfs_uri = gnome_vfs_uri_new (uri);
2212 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2213 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2214 g_free (escaped_filename);
2215 gnome_vfs_uri_unref (vfs_uri);
2216 info = gnome_vfs_file_info_new ();
2218 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2219 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2221 mime_type = gnome_vfs_file_info_get_mime_type (info);
2223 mime_part = tny_platform_factory_new_mime_part
2224 (modest_runtime_get_platform_factory ());
2226 TnyStream *stream = create_stream_for_uri (uri);
2228 if (stream == NULL) {
2230 modest_platform_information_banner (NULL, NULL,
2231 _FM("sfil_ib_opening_not_allowed"));
2233 g_object_unref (mime_part);
2234 gnome_vfs_file_info_unref (info);
2238 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2240 content_id = g_strdup_printf ("%d", priv->next_cid);
2241 tny_mime_part_set_content_id (mime_part, content_id);
2242 g_free (content_id);
2245 basename = g_path_get_basename (filename);
2246 tny_mime_part_set_filename (mime_part, basename);
2249 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
2251 if (pixbuf != NULL) {
2252 priv->images_size += stream_size;
2253 priv->images_count ++;
2254 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2255 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2256 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
2257 g_object_unref (pixbuf);
2260 tny_list_prepend (priv->images, (GObject *) mime_part);
2261 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2263 g_object_unref (mime_part);
2264 gnome_vfs_file_info_unref (info);
2273 on_attach_file_response (GtkDialog *dialog,
2277 GSList *uris = NULL;
2279 GnomeVFSFileSize total_size, allowed_size;
2280 ModestMsgEditWindow *window;
2281 ModestMsgEditWindowPrivate *priv;
2286 case GTK_RESPONSE_OK:
2287 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2293 window = MODEST_MSG_EDIT_WINDOW (user_data);
2294 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2296 /* allowed size is the maximum size - what's already there */
2297 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2298 &att_num, &att_size);
2299 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2302 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2304 const gchar *uri = (const gchar *) uri_node->data;
2307 modest_msg_edit_window_attach_file_one (window, uri, allowed_size);
2309 if (total_size > allowed_size) {
2310 g_warning ("%s: total size: %u",
2311 __FUNCTION__, (unsigned int)total_size);
2314 allowed_size -= total_size;
2316 g_slist_foreach (uris, (GFunc) g_free, NULL);
2317 g_slist_free (uris);
2319 gtk_widget_destroy (GTK_WIDGET (dialog));
2323 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2325 GtkWidget *dialog = NULL;
2326 ModestMsgEditWindowPrivate *priv;
2328 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2330 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2332 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2335 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window),
2336 GTK_FILE_CHOOSER_ACTION_OPEN);
2337 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2338 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2339 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2340 GTK_WINDOW (dialog), GTK_WINDOW (window));
2342 /* Connect to response & show */
2343 g_signal_connect (dialog, "response",
2344 G_CALLBACK (on_attach_file_response), window);
2345 gtk_widget_show (dialog);
2350 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2352 GnomeVFSFileSize allowed_size)
2355 GnomeVFSHandle *handle = NULL;
2356 ModestMsgEditWindowPrivate *priv;
2357 GnomeVFSResult result;
2358 GnomeVFSFileSize size = 0;
2359 g_return_val_if_fail (window, 0);
2360 g_return_val_if_fail (uri, 0);
2362 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2364 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2365 if (result == GNOME_VFS_OK) {
2366 TnyMimePart *mime_part;
2368 const gchar *mime_type = NULL;
2370 gchar *escaped_filename;
2373 GnomeVFSFileInfo *info;
2374 GnomeVFSURI *vfs_uri;
2376 gnome_vfs_close (handle);
2377 vfs_uri = gnome_vfs_uri_new (uri);
2380 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2381 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2382 g_free (escaped_filename);
2383 gnome_vfs_uri_unref (vfs_uri);
2385 info = gnome_vfs_file_info_new ();
2387 if (gnome_vfs_get_file_info (uri,
2389 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2391 mime_type = gnome_vfs_file_info_get_mime_type (info);
2392 mime_part = tny_platform_factory_new_mime_part
2393 (modest_runtime_get_platform_factory ());
2395 /* try to get the attachment's size; this may fail for weird
2396 * file systems, like obex, upnp... */
2397 if (allowed_size != 0 &&
2398 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2400 if (size > allowed_size) {
2401 modest_platform_information_banner (NULL, NULL,
2402 _FM("sfil_ib_opening_not_allowed"));
2406 g_warning ("%s: could not get attachment size", __FUNCTION__);
2408 stream = create_stream_for_uri (uri);
2410 if (stream == NULL) {
2412 modest_platform_information_banner (NULL, NULL, _FM("sfil_ib_opening_not_allowed"));
2414 g_object_unref (mime_part);
2415 gnome_vfs_file_info_unref (info);
2419 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2420 g_object_unref (stream);
2422 content_id = g_strdup_printf ("%d", priv->next_cid);
2423 tny_mime_part_set_content_id (mime_part, content_id);
2424 g_free (content_id);
2427 basename = g_path_get_basename (filename);
2428 tny_mime_part_set_filename (mime_part, basename);
2431 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2432 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2434 info->size == 0, info->size);
2435 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2436 gtk_widget_show_all (priv->attachments_caption);
2437 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2439 g_object_unref (mime_part);
2440 gnome_vfs_file_info_unref (info);
2447 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2450 ModestMsgEditWindowPrivate *priv;
2453 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2454 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2456 if (att_list == NULL) {
2457 att_list = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2458 if (!modest_maemo_utils_select_attachments (GTK_WINDOW (window), att_list)) {
2459 g_object_unref (att_list);
2464 g_object_ref (att_list);
2467 if (tny_list_get_length (att_list) == 0) {
2468 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2470 gboolean dialog_response;
2471 gchar *message = NULL;
2472 gchar *filename = NULL;
2474 if (tny_list_get_length (att_list) == 1) {
2476 iter = tny_list_create_iterator (att_list);
2477 part = (TnyMimePart *) tny_iterator_get_current (iter);
2478 g_object_unref (iter);
2479 if (TNY_IS_MSG (part)) {
2480 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2482 filename = tny_header_dup_subject (header);
2483 g_object_unref (header);
2485 if (filename == NULL) {
2486 filename = g_strdup (_("mail_va_no_subject"));
2489 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2491 g_object_unref (part);
2493 filename = g_strdup ("");
2495 message = g_strdup_printf (ngettext("emev_nc_delete_attachment",
2496 "emev_nc_delete_attachments",
2497 tny_list_get_length (att_list)), filename);
2500 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
2504 if (dialog_response != GTK_RESPONSE_OK) {
2505 g_object_unref (att_list);
2509 for (iter = tny_list_create_iterator (att_list);
2510 !tny_iterator_is_done (iter);
2511 tny_iterator_next (iter)) {
2512 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2513 const gchar *att_id;
2514 tny_list_remove (priv->attachments, (GObject *) mime_part);
2516 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2518 if (tny_list_get_length (priv->attachments) == 0)
2519 gtk_widget_hide (priv->attachments_caption);
2520 att_id = tny_mime_part_get_content_id (mime_part);
2522 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2524 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2525 g_object_unref (mime_part);
2527 g_object_unref (iter);
2530 g_object_unref (att_list);
2532 /* if the last attachment has been removed, focus the Subject: field */
2533 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2534 gtk_widget_grab_focus (priv->subject_field);
2538 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2541 ModestMsgEditWindowPrivate *priv;
2542 GdkColor *new_color;
2543 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2545 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2546 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2549 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2551 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2553 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2555 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2560 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
2563 ModestMsgEditWindowPrivate *priv;
2564 gint new_size_index;
2565 ModestMsgEditWindow *window;
2568 window = MODEST_MSG_EDIT_WINDOW (userdata);
2569 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2570 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2572 if (gtk_check_menu_item_get_active (menu_item)) {
2574 WPTextBufferFormat format;
2576 memset (&format, 0, sizeof (format));
2577 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2579 label = gtk_bin_get_child (GTK_BIN (menu_item));
2581 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
2582 format.cs.font_size = TRUE;
2583 format.cs.text_position = TRUE;
2584 format.cs.font = TRUE;
2585 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
2586 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2588 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2589 GINT_TO_POINTER (wp_get_font_size_index (new_size_index, 12))))
2590 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2592 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2593 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
2594 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2600 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
2603 ModestMsgEditWindowPrivate *priv;
2604 gint new_font_index;
2605 ModestMsgEditWindow *window;
2608 window = MODEST_MSG_EDIT_WINDOW (userdata);
2609 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2610 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2612 if (gtk_check_menu_item_get_active (menu_item)) {
2615 label = gtk_bin_get_child (GTK_BIN (menu_item));
2617 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
2619 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2620 GINT_TO_POINTER(new_font_index)))
2621 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2623 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2624 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2625 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2631 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2634 ModestMsgEditWindowPrivate *priv = NULL;
2635 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2637 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2638 if (!priv->update_caption_visibility)
2641 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2643 gtk_widget_show (priv->cc_caption);
2645 gtk_widget_hide (priv->cc_caption);
2647 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2651 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2654 ModestMsgEditWindowPrivate *priv = NULL;
2655 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2657 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2658 if (!priv->update_caption_visibility)
2661 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2663 gtk_widget_show (priv->bcc_caption);
2665 gtk_widget_hide (priv->bcc_caption);
2667 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2671 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2672 ModestRecptEditor *editor)
2674 ModestMsgEditWindowPrivate *priv;
2676 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2677 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2679 /* we check for low-mem; in that case, show a warning, and don't allow
2680 * for the addressbook
2682 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2685 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2687 if (editor == NULL) {
2688 GtkWidget *view_focus;
2689 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2691 /* This code should be kept in sync with ModestRecptEditor. The
2692 textview inside the recpt editor is the one that really gets the
2693 focus. As it's inside a scrolled window, and this one inside the
2694 hbox recpt editor inherits from, we'll need to go up in the
2695 hierarchy to know if the text view is part of the recpt editor
2696 or if it's a different text entry */
2698 if (gtk_widget_get_parent (view_focus)) {
2699 GtkWidget *first_parent;
2701 first_parent = gtk_widget_get_parent (view_focus);
2702 if (gtk_widget_get_parent (first_parent) &&
2703 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2704 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2709 editor = MODEST_RECPT_EDITOR (priv->to_field);
2713 modest_address_book_select_addresses (editor);
2718 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2720 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2722 modest_msg_edit_window_open_addressbook (window, NULL);
2726 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2727 gboolean show_toolbar)
2729 ModestWindowPrivate *parent_priv;
2731 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2732 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2734 /* We can not just use the code of
2735 modest_msg_edit_window_setup_toolbar because it has a
2736 mixture of both initialization and creation code. */
2738 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2740 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2744 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2745 TnyHeaderFlags priority_flags)
2747 ModestMsgEditWindowPrivate *priv;
2748 ModestWindowPrivate *parent_priv;
2750 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2752 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2753 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2755 if (priv->priority_flags != priority_flags) {
2756 GtkAction *priority_action = NULL;
2758 priv->priority_flags = priority_flags;
2760 switch (priority_flags) {
2761 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2762 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2763 MODEST_HEADER_ICON_HIGH,
2764 HILDON_ICON_SIZE_XSMALL);
2765 gtk_widget_show (priv->priority_icon);
2766 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2767 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2769 case TNY_HEADER_FLAG_LOW_PRIORITY:
2770 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2771 MODEST_HEADER_ICON_LOW,
2772 HILDON_ICON_SIZE_XSMALL);
2773 gtk_widget_show (priv->priority_icon);
2774 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2775 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2778 gtk_widget_hide (priv->priority_icon);
2779 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2780 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2783 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2784 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2789 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2792 ModestMsgEditWindowPrivate *priv;
2793 ModestWindowPrivate *parent_priv;
2794 gint current_format;
2796 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2798 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2799 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2801 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2802 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2804 if (current_format != file_format) {
2805 switch (file_format) {
2806 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2807 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2808 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
2810 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2814 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2815 response = gtk_dialog_run (GTK_DIALOG (dialog));
2816 gtk_widget_destroy (dialog);
2817 if (response == GTK_RESPONSE_OK) {
2818 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2820 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
2821 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
2826 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2827 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2828 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2833 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2836 ModestMsgEditWindowPrivate *priv;
2837 WPTextBufferFormat oldfmt, fmt;
2838 gint old_position = 0;
2842 GdkColor *color = NULL;
2843 gboolean bold, bold_set, italic, italic_set;
2844 gboolean underline, underline_set;
2845 gboolean strikethrough, strikethrough_set;
2846 gboolean position_set;
2847 gboolean font_size_set, font_set, color_set;
2850 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2851 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2853 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2854 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
2855 GTK_WINDOW(dialog), GTK_WINDOW (window));
2857 /* First we get the currently selected font information */
2858 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2860 switch (oldfmt.text_position) {
2861 case TEXT_POSITION_NORMAL:
2864 case TEXT_POSITION_SUPERSCRIPT:
2872 g_object_set (G_OBJECT (dialog),
2873 "bold", oldfmt.bold != FALSE,
2874 "bold-set", !oldfmt.cs.bold,
2875 "underline", oldfmt.underline != FALSE,
2876 "underline-set", !oldfmt.cs.underline,
2877 "italic", oldfmt.italic != FALSE,
2878 "italic-set", !oldfmt.cs.italic,
2879 "strikethrough", oldfmt.strikethrough != FALSE,
2880 "strikethrough-set", !oldfmt.cs.strikethrough,
2881 "color", &oldfmt.color,
2882 "color-set", !oldfmt.cs.color,
2883 "size", wp_font_size[oldfmt.font_size],
2884 "size-set", !oldfmt.cs.font_size,
2885 "position", old_position,
2886 "position-set", !oldfmt.cs.text_position,
2887 "family", wp_get_font_name (oldfmt.font),
2888 "family-set", !oldfmt.cs.font,
2891 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2892 GTK_WINDOW (dialog), GTK_WINDOW (window));
2893 gtk_widget_show_all (dialog);
2894 priv->font_dialog = dialog;
2895 response = gtk_dialog_run (GTK_DIALOG (dialog));
2896 priv->font_dialog = NULL;
2897 if (response == GTK_RESPONSE_OK) {
2899 g_object_get( dialog,
2901 "bold-set", &bold_set,
2902 "underline", &underline,
2903 "underline-set", &underline_set,
2905 "italic-set", &italic_set,
2906 "strikethrough", &strikethrough,
2907 "strikethrough-set", &strikethrough_set,
2909 "color-set", &color_set,
2911 "size-set", &font_size_set,
2912 "family", &font_name,
2913 "family-set", &font_set,
2914 "position", &position,
2915 "position-set", &position_set,
2920 if (response == GTK_RESPONSE_OK) {
2921 memset(&fmt, 0, sizeof(fmt));
2927 fmt.italic = italic;
2928 fmt.cs.italic = TRUE;
2930 if (underline_set) {
2931 fmt.underline = underline;
2932 fmt.cs.underline = TRUE;
2934 if (strikethrough_set) {
2935 fmt.strikethrough = strikethrough;
2936 fmt.cs.strikethrough = TRUE;
2941 ? TEXT_POSITION_NORMAL
2942 : ( ( position == 1 )
2943 ? TEXT_POSITION_SUPERSCRIPT
2944 : TEXT_POSITION_SUBSCRIPT );
2945 fmt.cs.text_position = TRUE;
2946 fmt.font_size = oldfmt.font_size;
2950 fmt.cs.color = TRUE;
2953 fmt.font = wp_get_font_index(font_name,
2958 if (font_size_set) {
2959 fmt.cs.font_size = TRUE;
2960 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
2962 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2963 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2965 gtk_widget_destroy (dialog);
2967 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2971 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2973 ModestMsgEditWindowPrivate *priv;
2975 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2976 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2978 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2980 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2981 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2985 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
2987 ModestMsgEditWindowPrivate *priv;
2989 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2990 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2992 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
2994 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2995 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3000 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
3002 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3004 priv->can_undo = can_undo;
3008 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
3010 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3012 priv->can_redo = can_redo;
3016 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3018 ModestMsgEditWindowPrivate *priv;
3019 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3020 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3022 return priv->can_undo;
3026 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3028 ModestMsgEditWindowPrivate *priv;
3029 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3030 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3032 return priv->can_redo;
3037 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3040 GtkTextIter match_start, match_end;
3042 if (image_id == NULL)
3045 gtk_text_buffer_get_start_iter (buffer, &iter);
3047 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3048 GSList *tags = gtk_text_iter_get_tags (&match_start);
3050 for (node = tags; node != NULL; node = g_slist_next (node)) {
3051 GtkTextTag *tag = (GtkTextTag *) node->data;
3052 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3053 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3054 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3056 offset = gtk_text_iter_get_offset (&match_start);
3057 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3058 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3062 gtk_text_iter_forward_char (&iter);
3067 message_is_empty (ModestMsgEditWindow *window)
3069 ModestMsgEditWindowPrivate *priv = NULL;
3071 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3072 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3074 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3075 * so we can ignore markup.
3077 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3080 count = gtk_text_buffer_get_char_count (buf);
3086 msg_body_focus (GtkWidget *focus,
3087 GdkEventFocus *event,
3091 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3092 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3093 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3098 recpt_field_changed (GtkTextBuffer *buffer,
3099 ModestMsgEditWindow *editor)
3101 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3102 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3106 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3108 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3109 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3113 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3116 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3117 GtkTextBuffer *buffer;
3119 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3120 gtk_text_buffer_set_modified (buffer, modified);
3121 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3122 gtk_text_buffer_set_modified (buffer, modified);
3123 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3124 gtk_text_buffer_set_modified (buffer, modified);
3125 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3129 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3131 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3132 const char *account_name;
3133 GtkTextBuffer *buffer;
3135 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3136 if (gtk_text_buffer_get_modified (buffer))
3138 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3139 if (gtk_text_buffer_get_modified (buffer))
3141 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3142 if (gtk_text_buffer_get_modified (buffer))
3144 if (gtk_text_buffer_get_modified (priv->text_buffer))
3146 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3147 if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3158 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3160 ModestMsgEditWindowPrivate *priv = NULL;
3162 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3163 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3165 /* check if there's no recipient added */
3166 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3167 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3168 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3169 /* no recipient contents, then select contacts */
3170 modest_msg_edit_window_open_addressbook (window, NULL);
3174 g_object_ref (window);
3175 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3176 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3177 g_object_unref (window);
3180 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3181 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3182 g_object_unref (window);
3185 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3186 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3187 g_object_unref (window);
3191 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3192 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3193 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3194 g_object_unref (window);
3201 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3202 ModestMsgEditWindow *window)
3204 modest_msg_edit_window_offer_attach_file (window);
3208 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3210 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3212 return priv->clipboard_text;
3216 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3218 ModestMsgEditWindow *window)
3220 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3221 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3223 if (!GTK_WIDGET_VISIBLE (window))
3226 g_object_ref (window);
3227 text = gtk_clipboard_wait_for_text (selection_clipboard);
3229 if (priv->clipboard_text != NULL) {
3230 g_free (priv->clipboard_text);
3232 priv->clipboard_text = text;
3234 if (GTK_WIDGET_VISIBLE (window)) {
3235 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3237 g_object_unref (window);
3240 static gboolean clipboard_owner_change_idle (gpointer userdata)
3242 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3243 ModestMsgEditWindowPrivate *priv;
3245 gdk_threads_enter ();
3246 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3247 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3249 priv->clipboard_owner_idle = 0;
3250 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3251 gdk_threads_leave ();
3257 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3259 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3260 if (priv->clipboard_owner_idle == 0) {
3261 priv->clipboard_owner_idle = g_idle_add (clipboard_owner_change_idle, window);
3266 subject_field_move_cursor (GtkEntry *entry,
3267 GtkMovementStep step,
3272 if (!GTK_WIDGET_VISIBLE (window))
3275 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3279 update_window_title (ModestMsgEditWindow *window)
3281 ModestMsgEditWindowPrivate *priv = NULL;
3282 const gchar *subject;
3284 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3285 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3286 if (subject == NULL || subject[0] == '\0')
3287 subject = _("mail_va_new_email");
3289 gtk_window_set_title (GTK_WINDOW (window), subject);
3294 subject_field_changed (GtkEditable *editable,
3295 ModestMsgEditWindow *window)
3297 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3298 update_window_title (window);
3299 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3300 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3301 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3305 subject_field_insert_text (GtkEditable *editable,
3307 gint new_text_length,
3309 ModestMsgEditWindow *window)
3311 GString *result = g_string_new ("");
3313 gint result_len = 0;
3314 const gchar *entry_text = NULL;
3317 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3318 old_length = g_utf8_strlen (entry_text, -1);
3320 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3321 gunichar c = g_utf8_get_char_validated (current, 8);
3322 /* Invalid unichar, stop */
3328 result = g_string_append_unichar (result, c);
3332 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3333 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3336 /* Prevent endless recursion */
3337 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3338 g_signal_emit_by_name (editable, "insert-text",
3339 (gpointer) result->str, (gpointer) result->len,
3340 (gpointer) position, (gpointer) window);
3341 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3345 if (result_len + old_length > 1000) {
3346 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3347 _CS("ckdg_ib_maximum_characters_reached"));
3349 g_string_free (result, TRUE);
3353 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3356 ModestMsgEditWindowPrivate *priv = NULL;
3358 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3359 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3361 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3364 gtk_widget_show_all (priv->find_toolbar);
3365 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3367 gtk_widget_hide_all (priv->find_toolbar);
3368 gtk_widget_grab_focus (priv->msg_body);
3373 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3375 GtkTextIter *match_start,
3376 GtkTextIter *match_end)
3378 GtkTextIter end_iter;
3379 gchar *str_casefold;
3382 gchar *range_casefold;
3385 gboolean result = FALSE;
3392 gtk_text_iter_forward_to_end (&end_iter);
3394 str_casefold = g_utf8_casefold (str, -1);
3395 str_chars_n = strlen (str);
3397 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3398 range_casefold = g_utf8_casefold (range_text, -1);
3399 range_chars_n = strlen (range_casefold);
3401 if (range_chars_n < str_chars_n) {
3402 g_free (str_casefold);
3403 g_free (range_text);
3404 g_free (range_casefold);
3408 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3409 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3410 if (!g_utf8_collate (range_subtext, str_casefold)) {
3411 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3413 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3414 match_start, match_end, NULL);
3415 g_free (found_text);
3417 g_free (range_subtext);
3421 g_free (str_casefold);
3422 g_free (range_text);
3423 g_free (range_casefold);
3430 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3431 ModestMsgEditWindow *window)
3433 gchar *current_search = NULL;
3434 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3436 GtkTextIter selection_start, selection_end;
3437 GtkTextIter match_start, match_end;
3438 gboolean continue_search = FALSE;
3440 if (message_is_empty (window)) {
3441 g_free (priv->last_search);
3442 priv->last_search = NULL;
3443 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3447 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3448 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3449 g_free (current_search);
3450 g_free (priv->last_search);
3451 priv->last_search = NULL;
3452 /* Information banner about empty search */
3453 hildon_banner_show_information (NULL, NULL, _CS("ecdg_ib_find_rep_enter_text"));
3457 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3458 continue_search = TRUE;
3460 g_free (priv->last_search);
3461 priv->last_search = g_strdup (current_search);
3464 if (continue_search) {
3465 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3466 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3467 &match_start, &match_end);
3469 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_search_complete"));
3471 GtkTextIter buffer_start;
3472 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3473 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3474 &match_start, &match_end);
3476 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_no_matches"));
3479 /* Mark as selected the string found in search */
3481 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3482 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3483 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3485 g_free (priv->last_search);
3486 priv->last_search = NULL;
3488 g_free (current_search);
3492 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3494 ModestMsgEditWindowPrivate *priv;
3496 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3501 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3504 ModestMsgEditWindowPrivate *priv;
3506 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3511 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3512 ModestMsgEditWindow *window)
3514 modest_msg_edit_window_toggle_find_toolbar (window, FALSE);
3518 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3521 ModestMsgEditWindowPrivate *priv;
3522 TnyHeader *header = NULL;
3524 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3525 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3527 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3528 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3530 if (priv->draft_msg != NULL) {
3531 g_object_unref (priv->draft_msg);
3534 if (draft != NULL) {
3535 g_object_ref (draft);
3536 header = tny_msg_get_header (draft);
3537 if (priv->msg_uid) {
3538 g_free (priv->msg_uid);
3539 priv->msg_uid = NULL;
3541 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3542 if (GTK_WIDGET_REALIZED (window)) {
3543 if (!modest_window_mgr_register_window (mgr, MODEST_WINDOW (window), NULL)) {
3544 gtk_widget_destroy (GTK_WIDGET (window));
3550 priv->draft_msg = draft;
3554 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3555 GtkTextIter *start, GtkTextIter *end,
3558 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3559 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3562 if (tag == NULL) return;
3563 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3564 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3565 replace_with_images (window, priv->images);
3570 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3573 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3575 g_return_if_fail (TNY_IS_MIME_PART (part));
3576 tny_list_prepend (priv->attachments, (GObject *) part);
3577 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3578 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3579 gtk_widget_show_all (priv->attachments_caption);
3580 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3584 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3586 ModestMsgEditWindowPrivate *priv;
3588 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3589 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3591 return priv->msg_uid;
3595 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3596 ModestMsgEditWindowWidgetType widget_type)
3598 ModestMsgEditWindowPrivate *priv;
3600 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3601 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3603 switch (widget_type) {
3604 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3605 return priv->msg_body;
3607 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3608 return priv->to_field;
3610 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3611 return priv->cc_field;
3613 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3614 return priv->bcc_field;
3616 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3617 return priv->subject_field;
3619 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3620 return priv->attachments_view;
3628 remove_tags (WPTextBuffer *buffer)
3630 GtkTextIter start, end;
3632 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3633 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3635 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3639 on_account_removed (TnyAccountStore *account_store,
3640 TnyAccount *account,
3643 /* Do nothing if it's a store account, because we use the
3644 transport to send the messages */
3645 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3646 const gchar *parent_acc = NULL;
3647 const gchar *our_acc = NULL;
3649 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3650 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3651 /* Close this window if I'm showing a message of the removed account */
3652 if (strcmp (parent_acc, our_acc) == 0)
3653 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3658 from_field_changed (HildonPickerButton *button,
3659 ModestMsgEditWindow *self)
3661 ModestMsgEditWindowPrivate *priv;
3662 gboolean has_old_signature, has_new_signature;
3664 GtkTextIter match_start, match_end;
3665 ModestAccountMgr *mgr;
3667 gchar *full_signature;
3669 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3671 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
3672 mgr = modest_runtime_get_account_mgr ();
3673 signature = modest_account_mgr_get_signature (mgr, priv->last_from_account, &has_old_signature);
3674 if (has_old_signature) {
3675 full_signature = g_strconcat ("\n--\n", signature, NULL);
3676 if (gtk_text_iter_forward_search (&iter, full_signature, 0, &match_start, &match_end, NULL)) {
3677 gtk_text_buffer_delete (priv->text_buffer, &match_start, &match_end);
3679 } else if (gtk_text_iter_forward_search (&iter, _("mcen_ia_editor_original_message"), 0,
3680 &match_start, &match_end, NULL)) {
3683 g_free (full_signature);
3687 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3688 signature = modest_account_mgr_get_signature (mgr, priv->last_from_account, &has_new_signature);
3689 if (has_new_signature) {
3690 full_signature = g_strconcat ("\n--\n", signature, NULL);
3691 gtk_text_buffer_insert (priv->text_buffer, &iter, full_signature, -1);
3692 g_free (full_signature);
3697 typedef struct _MessageSettingsHelper {
3698 ModestMsgEditWindow *window;
3699 GSList *priority_group;
3700 GSList *format_group;
3701 GtkToggleButton *current_priority;
3702 GtkToggleButton *current_format;
3703 } MessageSettingsHelper;
3706 on_priority_toggle (GtkToggleButton *button,
3707 MessageSettingsHelper *helper)
3710 ModestMsgEditWindowPrivate *priv;
3712 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3713 if (gtk_toggle_button_get_active (button)) {
3715 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3716 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3717 if ((node_button != button) &&
3718 gtk_toggle_button_get_active (node_button)) {
3719 gtk_toggle_button_set_active (node_button, FALSE);
3722 helper->current_priority = button;
3724 gboolean found = FALSE;
3725 /* If no one is active, activate it again */
3726 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3727 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3728 if (gtk_toggle_button_get_active (node_button)) {
3734 gtk_toggle_button_set_active (button, TRUE);
3740 on_format_toggle (GtkToggleButton *button,
3741 MessageSettingsHelper *helper)
3744 ModestMsgEditWindowPrivate *priv;
3746 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3747 if (gtk_toggle_button_get_active (button)) {
3749 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
3750 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3751 if ((node_button != button) &&
3752 gtk_toggle_button_get_active (node_button)) {
3753 gtk_toggle_button_set_active (node_button, FALSE);
3756 helper->current_format = button;
3758 gboolean found = FALSE;
3759 /* If no one is active, activate it again */
3760 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
3761 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3762 if (gtk_toggle_button_get_active (node_button)) {
3768 gtk_toggle_button_set_active (button, TRUE);
3775 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
3779 GtkWidget *priority_hbox;
3780 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
3781 GtkWidget *captioned;
3782 GtkSizeGroup *title_sizegroup, *value_sizegroup;
3783 GtkWidget *format_hbox;
3784 GtkWidget *html_toggle, *text_toggle;
3785 ModestMsgEditWindowPrivate *priv;
3786 MessageSettingsHelper helper = {0,};
3788 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3789 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3790 helper.window = window;
3791 helper.priority_group = NULL;
3793 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3794 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3796 dialog = gtk_dialog_new_with_buttons (_("mcen_me_message_settings"), NULL,
3797 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
3798 _HL("wdgt_bd_done"), GTK_RESPONSE_ACCEPT, NULL);
3799 vbox = gtk_vbox_new (FALSE, 0);
3800 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), vbox);
3801 gtk_widget_show (vbox);
3803 /* Priority toggles */
3804 priority_hbox = gtk_hbox_new (TRUE, 0);
3805 high_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3806 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
3807 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
3808 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
3809 medium_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3810 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
3811 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
3812 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
3813 low_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3814 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
3815 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
3816 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
3817 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, TRUE, TRUE, 0);
3818 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, TRUE, TRUE, 0);
3819 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, TRUE, TRUE, 0);
3820 gtk_widget_show_all (priority_hbox);
3821 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
3822 _("mcen_me_editor_message_priority"), FALSE, priority_hbox);
3823 gtk_widget_show (captioned);
3824 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
3826 /* format toggles */
3827 format_hbox = gtk_hbox_new (TRUE, 0);
3828 html_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3829 gtk_button_set_label (GTK_BUTTON (html_toggle), _("mcen_me_editor_formatted_text"));
3830 helper.format_group = g_slist_prepend (helper.format_group, html_toggle);
3831 g_object_set_data (G_OBJECT (html_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_HTML));
3832 g_object_set_data (G_OBJECT (html_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_FORMATTED_TEXT));
3833 text_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3834 gtk_button_set_label (GTK_BUTTON (text_toggle), _("mcen_me_editor_plain_text"));
3835 helper.format_group = g_slist_prepend (helper.format_group, text_toggle);
3836 g_object_set_data (G_OBJECT (text_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_TEXT));
3837 g_object_set_data (G_OBJECT (text_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_PLAIN_TEXT));
3838 gtk_box_pack_start (GTK_BOX (format_hbox), html_toggle, TRUE, TRUE, 0);
3839 gtk_box_pack_start (GTK_BOX (format_hbox), text_toggle, TRUE, TRUE, 0);
3840 gtk_widget_show_all (format_hbox);
3841 gtk_widget_show (format_hbox);
3842 gtk_box_pack_start (GTK_BOX (vbox), format_hbox, FALSE, FALSE, 0);
3845 g_object_unref (title_sizegroup);
3846 g_object_unref (value_sizegroup);
3848 /* Set current values */
3849 switch (priv->priority_flags) {
3850 case TNY_HEADER_FLAG_HIGH_PRIORITY:
3851 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (high_toggle), TRUE);
3852 helper.current_priority = GTK_TOGGLE_BUTTON (high_toggle);
3854 case TNY_HEADER_FLAG_LOW_PRIORITY:
3855 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (low_toggle), TRUE);
3856 helper.current_priority = GTK_TOGGLE_BUTTON (low_toggle);
3859 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (medium_toggle), TRUE);
3860 helper.current_priority = GTK_TOGGLE_BUTTON (medium_toggle);
3864 switch (modest_msg_edit_window_get_format (window)) {
3865 case MODEST_MSG_EDIT_FORMAT_TEXT:
3866 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_toggle), TRUE);
3867 helper.current_format = GTK_TOGGLE_BUTTON (text_toggle);
3869 case MODEST_MSG_EDIT_FORMAT_HTML:
3871 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (html_toggle), TRUE);
3872 helper.current_format = GTK_TOGGLE_BUTTON (html_toggle);
3876 /* Signal connects */
3877 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3878 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3879 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3880 g_signal_connect (G_OBJECT (html_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
3881 g_signal_connect (G_OBJECT (text_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
3883 /* Save settings if the user clicked on done */
3884 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
3885 TnyHeaderFlags flags;
3886 ModestMsgEditFormat old_format, new_format;
3888 /* Set priority flags */
3889 flags = (TnyHeaderFlags) g_object_get_data (G_OBJECT (helper.current_priority), "priority");
3890 if (priv->priority_flags != flags)
3891 modest_msg_edit_window_set_priority_flags (window, flags);
3893 /* Set edit format */
3894 old_format = modest_msg_edit_window_get_format (window);
3895 new_format = (ModestMsgEditFormat) g_object_get_data (G_OBJECT (helper.current_format), "format");
3896 if (old_format != new_format) {
3897 gint file_format = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (helper.current_format), "file-format"));
3898 modest_msg_edit_window_set_file_format (window, file_format);
3902 gtk_widget_destroy (dialog);
3903 g_slist_free (helper.priority_group);
3907 on_message_settings (GtkAction *action,
3908 ModestMsgEditWindow *window)
3910 modest_msg_edit_window_show_msg_settings_dialog (window);
3914 on_cc_button_toggled (HildonCheckButton *button,
3915 ModestMsgEditWindow *window)
3917 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
3919 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
3920 hildon_check_button_get_active (button));
3924 on_bcc_button_toggled (HildonCheckButton *button,
3925 ModestMsgEditWindow *window)
3927 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
3929 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
3930 hildon_check_button_get_active (button));
3934 setup_menu (ModestMsgEditWindow *self)
3936 ModestMsgEditWindowPrivate *priv = NULL;
3938 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
3940 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3942 /* Settings menu buttons */
3943 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_checknames"), NULL,
3944 APP_MENU_CALLBACK (modest_ui_actions_on_check_names),
3946 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_undo"), "<Ctrl>z",
3947 APP_MENU_CALLBACK (modest_ui_actions_on_undo),
3948 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_undo));
3950 priv->cc_button = hildon_check_button_new (0);
3951 gtk_button_set_label (GTK_BUTTON (priv->cc_button), _("mcen_me_editor_showcc"));
3952 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button),
3954 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->cc_button),
3956 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
3957 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
3958 priv->bcc_button = hildon_check_button_new (0);
3959 gtk_button_set_label (GTK_BUTTON (priv->bcc_button), _("mcen_me_editor_showbcc"));
3960 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button),
3962 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->bcc_button),
3964 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
3965 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
3967 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_attach_inlineimage"), NULL,
3968 APP_MENU_CALLBACK (modest_ui_actions_on_insert_image),
3969 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_set_style));
3970 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_remove_attachments"), NULL,
3971 APP_MENU_CALLBACK (modest_ui_actions_on_remove_attachments),
3972 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
3973 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_message_settings"), NULL,
3974 APP_MENU_CALLBACK (on_message_settings),
3976 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_viewer_find"), "<Ctrl>f",
3977 APP_MENU_CALLBACK (modest_ui_actions_on_toggle_find_in_page),