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
92 static gboolean is_wp_text_buffer_started = FALSE;
94 static void modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass);
95 static void modest_msg_edit_window_init (ModestMsgEditWindow *obj);
96 static void modest_msg_edit_window_finalize (GObject *obj);
98 static gboolean msg_body_focus (GtkWidget *focus, GdkEventFocus *event, gpointer userdata);
99 static void body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
100 static void recpt_field_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
102 static void text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window);
103 static void text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window);
104 static void text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window);
105 static void text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
106 GtkTextIter *start, GtkTextIter *end,
108 static void text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id);
109 static void subject_field_changed (GtkEditable *editable, ModestMsgEditWindow *window);
110 static void subject_field_insert_text (GtkEditable *editable,
112 gint new_text_length,
114 ModestMsgEditWindow *window);
115 static void modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
117 static void modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
119 static void modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
121 static void modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
123 static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
124 ModestRecptEditor *editor);
125 static void modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
126 ModestMsgEditWindow *window);
128 /* ModestWindow methods implementation */
129 static void modest_msg_edit_window_disconnect_signals (ModestWindow *window);
130 static void modest_msg_edit_window_show_toolbar (ModestWindow *window,
131 gboolean show_toolbar);
132 static void modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
134 ModestMsgEditWindow *window);
135 static void modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window);
136 static void subject_field_move_cursor (GtkEntry *entry,
137 GtkMovementStep step,
141 static void update_window_title (ModestMsgEditWindow *window);
144 static void modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
145 ModestMsgEditWindow *window);
146 static void modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
147 ModestMsgEditWindow *window);
148 static gboolean gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
150 GtkTextIter *match_start,
151 GtkTextIter *match_end);
153 static void remove_tags (WPTextBuffer *buffer);
155 static void on_account_removed (TnyAccountStore *account_store,
159 static void init_window (ModestMsgEditWindow *obj);
161 gboolean scroll_drag_timeout (gpointer userdata);
162 static void correct_scroll (ModestMsgEditWindow *w);
163 static void correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused);
164 static void text_buffer_end_user_action (GtkTextBuffer *buffer,
165 ModestMsgEditWindow *userdata);
166 static void text_buffer_mark_set (GtkTextBuffer *buffer,
169 ModestMsgEditWindow *userdata);
170 static void on_message_settings (GtkAction *action,
171 ModestMsgEditWindow *window);
172 static void setup_menu (ModestMsgEditWindow *self);
174 static void DEBUG_BUFFER (WPTextBuffer *buffer)
178 g_message ("BEGIN BUFFER OF SIZE %d", gtk_text_buffer_get_char_count (GTK_TEXT_BUFFER (buffer)));
180 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &iter);
181 while (!gtk_text_iter_is_end (&iter)) {
182 GString *output = g_string_new ("");
183 GSList *toggled_tags;
186 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
187 g_string_append_printf (output, "%d: CLOSED [ ", gtk_text_iter_get_offset (&iter));
188 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
189 GtkTextTag *tag = (GtkTextTag *) node->data;
191 g_object_get (G_OBJECT (tag), "name", &name, NULL);
192 output = g_string_append (output, name);
193 g_string_append (output, " ");
195 output = g_string_append (output, "] OPENED [ ");
196 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
197 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
198 GtkTextTag *tag = (GtkTextTag *) node->data;
200 g_object_get (G_OBJECT (tag), "name", &name, NULL);
201 output = g_string_append (output, name);
202 g_string_append (output, " ");
204 output = g_string_append (output, "]\n");
205 g_message ("%s", output->str);
206 g_string_free (output, TRUE);
207 gtk_text_iter_forward_to_tag_toggle (&iter, NULL);
209 g_message ("END BUFFER");
213 static const GtkActionEntry hildon2_msg_edit_action_entries [] = {
214 { "MessageSettings", NULL, N_("mcen_me_message_settings"), NULL, NULL, G_CALLBACK (on_message_settings)},
218 /* static gboolean */
219 /* on_key_pressed (GtkWidget *self, */
220 /* GdkEventKey *event, */
221 /* gpointer user_data); */
223 /* list my signals */
230 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
231 struct _ModestMsgEditWindowPrivate {
234 GtkWidget *header_box;
236 ModestPairList *from_field_protos;
237 GtkWidget *from_field;
238 gchar *original_account_name;
242 GtkWidget *bcc_field;
243 GtkWidget *subject_field;
244 GtkWidget *attachments_view;
245 GtkWidget *priority_icon;
246 GtkWidget *add_attachment_button;
248 GtkWidget *cc_caption;
249 GtkWidget *bcc_caption;
250 gboolean update_caption_visibility;
251 GtkWidget *attachments_caption;
253 GtkTextBuffer *text_buffer;
255 GtkWidget *font_size_toolitem;
256 GtkWidget *font_face_toolitem;
257 GtkWidget *font_color_button;
258 GtkWidget *font_color_toolitem;
259 GSList *font_items_group;
260 GtkWidget *font_tool_button_label;
261 GSList *size_items_group;
262 GtkWidget *size_tool_button_label;
264 GtkWidget *find_toolbar;
267 GtkWidget *font_dialog;
270 guint correct_scroll_idle;
271 guint scroll_drag_timeout_id;
275 TnyList *attachments;
280 TnyHeaderFlags priority_flags;
282 gboolean can_undo, can_redo;
283 gulong clipboard_change_handler_id;
284 gulong default_clipboard_change_handler_id;
285 gulong account_removed_handler_id;
286 guint clipboard_owner_idle;
287 gchar *clipboard_text;
296 GtkWidget *cc_button;
297 GtkWidget *bcc_button;
300 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
301 MODEST_TYPE_MSG_EDIT_WINDOW, \
302 ModestMsgEditWindowPrivate))
304 static GtkWindowClass *parent_class = NULL;
306 /* uncomment the following if you have defined any signals */
307 /* static guint signals[LAST_SIGNAL] = {0}; */
310 modest_msg_edit_window_get_type (void)
312 static GType my_type = 0;
314 static const GTypeInfo my_info = {
315 sizeof(ModestMsgEditWindowClass),
316 NULL, /* base init */
317 NULL, /* base finalize */
318 (GClassInitFunc) modest_msg_edit_window_class_init,
319 NULL, /* class finalize */
320 NULL, /* class data */
321 sizeof(ModestMsgEditWindow),
323 (GInstanceInitFunc) modest_msg_edit_window_init,
326 my_type = g_type_register_static (MODEST_TYPE_HILDON2_WINDOW,
327 "ModestMsgEditWindow",
335 save_state (ModestWindow *self)
337 modest_widget_memory_save (modest_runtime_get_conf(),
338 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
343 restore_settings (ModestMsgEditWindow *self)
345 ModestConf *conf = NULL;
347 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
349 conf = modest_runtime_get_conf ();
351 /* Dim at start clipboard actions */
352 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
353 gtk_action_set_sensitive (action, FALSE);
354 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
355 gtk_action_set_sensitive (action, FALSE);
356 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
357 gtk_action_set_sensitive (action, FALSE);
359 modest_widget_memory_restore (conf, G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
364 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
366 GObjectClass *gobject_class;
367 ModestWindowClass *modest_window_class;
368 gobject_class = (GObjectClass*) klass;
369 modest_window_class = (ModestWindowClass*) klass;
371 parent_class = g_type_class_peek_parent (klass);
372 gobject_class->finalize = modest_msg_edit_window_finalize;
374 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
375 modest_window_class->save_state_func = save_state;
376 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
378 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
382 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
384 ModestMsgEditWindowPrivate *priv;
385 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
387 priv->msg_body = NULL;
389 priv->from_field = NULL;
390 priv->to_field = NULL;
391 priv->cc_field = NULL;
392 priv->bcc_field = NULL;
393 priv->subject_field = NULL;
394 priv->attachments = TNY_LIST (tny_simple_list_new ());
395 priv->images = TNY_LIST (tny_simple_list_new ());
396 priv->images_size = 0;
397 priv->images_count = 0;
400 priv->cc_caption = NULL;
401 priv->bcc_caption = NULL;
402 priv->update_caption_visibility = FALSE;
404 priv->priority_flags = 0;
406 priv->find_toolbar = NULL;
407 priv->last_search = NULL;
409 priv->draft_msg = NULL;
410 priv->outbox_msg = NULL;
411 priv->msg_uid = NULL;
413 priv->can_undo = FALSE;
414 priv->can_redo = FALSE;
415 priv->clipboard_change_handler_id = 0;
416 priv->default_clipboard_change_handler_id = 0;
417 priv->account_removed_handler_id = 0;
418 priv->clipboard_owner_idle = 0;
419 priv->clipboard_text = NULL;
422 priv->scroll_drag_timeout_id = 0;
423 priv->correct_scroll_idle = 0;
424 priv->last_upper = 0.0;
426 priv->font_dialog = NULL;
427 priv->app_menu = NULL;
429 if (!is_wp_text_buffer_started) {
430 is_wp_text_buffer_started = TRUE;
431 wp_text_buffer_library_init ();
436 hildon_program_add_window (hildon_program_get_instance(),
442 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
444 static ModestPairList*
445 get_transports (void)
447 GSList *transports = NULL;
449 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
450 GSList *accounts = modest_account_mgr_account_names (account_mgr,
451 TRUE /* only enabled accounts. */);
453 GSList *cursor = accounts;
455 gchar *account_name = cursor->data;
456 gchar *from_string = NULL;
458 from_string = modest_account_mgr_get_from_string (account_mgr,
462 if (from_string && account_name) {
463 gchar *name = account_name;
464 ModestPair *pair = modest_pair_new ((gpointer) name,
465 (gpointer) from_string , TRUE);
466 transports = g_slist_prepend (transports, pair);
469 cursor = cursor->next;
471 g_slist_free (accounts); /* only free the accounts, not the elements,
472 * because they are used in the pairlist */
476 static void window_focus (GtkWindow *window,
480 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
484 scroll_drag_timeout (gpointer userdata)
486 ModestMsgEditWindow *win = (ModestMsgEditWindow *) userdata;
487 ModestMsgEditWindowPrivate *priv;
489 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(win);
491 correct_scroll_without_drag_check (win, TRUE);
493 priv->scroll_drag_timeout_id = 0;
499 correct_scroll_without_drag_check_idle (gpointer userdata)
501 ModestMsgEditWindow *w = (ModestMsgEditWindow *) userdata;
502 ModestMsgEditWindowPrivate *priv;
504 GdkRectangle rectangle;
509 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
511 insert = gtk_text_buffer_get_insert (priv->text_buffer);
512 gtk_text_buffer_get_iter_at_mark (priv->text_buffer, &iter, insert);
514 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &iter, &rectangle);
515 offset = priv->msg_body->allocation.y;
517 new_value = (offset + rectangle.y);
519 hildon_pannable_area_jump_to (HILDON_PANNABLE_AREA (priv->pannable), -1, new_value);
521 priv->correct_scroll_idle = 0;
526 correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused)
528 ModestMsgEditWindowPrivate *priv;
530 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
532 if (only_if_focused && !gtk_widget_is_focus (priv->msg_body))
535 if (priv->correct_scroll_idle > 0) {
539 priv->correct_scroll_idle = g_idle_add ((GSourceFunc) correct_scroll_without_drag_check_idle,
544 correct_scroll (ModestMsgEditWindow *w)
546 ModestMsgEditWindowPrivate *priv;
548 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
549 if (gtk_grab_get_current () == priv->msg_body) {
550 if (priv->scroll_drag_timeout_id == 0) {
551 priv->scroll_drag_timeout_id = g_timeout_add (500, (GSourceFunc) scroll_drag_timeout,
557 correct_scroll_without_drag_check (w, TRUE);
561 text_buffer_end_user_action (GtkTextBuffer *buffer,
562 ModestMsgEditWindow *userdata)
565 correct_scroll (userdata);
569 text_buffer_mark_set (GtkTextBuffer *buffer,
572 ModestMsgEditWindow *userdata)
574 gtk_text_buffer_begin_user_action (buffer);
575 gtk_text_buffer_end_user_action (buffer);
579 cut_clipboard_check (GtkTextView *text_view,
582 GtkTextBuffer *buffer;
584 buffer = gtk_text_view_get_buffer (text_view);
585 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
586 g_signal_stop_emission_by_name ((gpointer )text_view, "cut-clipboard");
591 copy_clipboard_check (GtkTextView *text_view,
594 GtkTextBuffer *buffer;
596 buffer = gtk_text_view_get_buffer (text_view);
597 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
598 g_signal_stop_emission_by_name ((gpointer )text_view, "copy-clipboard");
603 attachment_deleted (ModestAttachmentsView *attachments_view,
606 modest_msg_edit_window_remove_attachments (MODEST_MSG_EDIT_WINDOW (user_data),
611 connect_signals (ModestMsgEditWindow *obj)
613 ModestMsgEditWindowPrivate *priv;
615 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
617 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
618 G_CALLBACK (text_buffer_refresh_attributes), obj);
619 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
620 G_CALLBACK (text_buffer_can_undo), obj);
621 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
622 G_CALLBACK (text_buffer_can_redo), obj);
623 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
624 G_CALLBACK (body_changed), obj);
625 g_signal_connect (G_OBJECT (priv->text_buffer), "modified-changed",
626 G_CALLBACK (body_changed), obj);
627 g_signal_connect (G_OBJECT (priv->text_buffer), "end-user-action",
628 G_CALLBACK (text_buffer_end_user_action), obj);
629 g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
630 G_CALLBACK (text_buffer_mark_set), obj);
631 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
632 G_CALLBACK (text_buffer_apply_tag), obj);
633 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
634 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
635 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
636 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
637 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
638 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
640 g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
641 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
643 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
644 G_CALLBACK (msg_body_focus), obj);
645 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
646 G_CALLBACK (msg_body_focus), obj);
647 g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
648 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
649 "changed", G_CALLBACK (recpt_field_changed), obj);
650 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
651 "changed", G_CALLBACK (recpt_field_changed), obj);
652 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
653 "changed", G_CALLBACK (recpt_field_changed), obj);
654 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
655 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
656 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
658 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
659 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
661 priv->clipboard_change_handler_id =
662 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
663 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
664 priv->default_clipboard_change_handler_id =
665 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
666 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
668 g_signal_connect (G_OBJECT (priv->msg_body), "cut-clipboard", G_CALLBACK (cut_clipboard_check), NULL);
669 g_signal_connect (G_OBJECT (priv->msg_body), "copy-clipboard", G_CALLBACK (copy_clipboard_check), NULL);
670 g_signal_connect (G_OBJECT (priv->attachments_view), "delete", G_CALLBACK (attachment_deleted), obj);
674 init_wp_text_view_style ()
676 static gboolean initialized = FALSE;
679 gtk_rc_parse_string ("class \"WPTextView\" style \"fremantle-textview\"");
685 init_window (ModestMsgEditWindow *obj)
687 GtkWidget *to_caption, *subject_caption;
688 GtkWidget *main_vbox;
689 ModestMsgEditWindowPrivate *priv;
690 GtkActionGroup *action_group;
691 ModestWindowPrivate *parent_priv;
692 GdkPixbuf *window_icon = NULL;
693 GError *error = NULL;
695 GtkSizeGroup *title_size_group;
696 GtkSizeGroup *value_size_group;
697 GtkWidget *subject_box;
698 GtkWidget *attachment_icon;
699 GtkWidget *window_box;
700 #if (GTK_MINOR_VERSION >= 10)
701 GdkAtom deserialize_type;
704 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
705 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
707 parent_priv->ui_manager = gtk_ui_manager_new();
708 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
709 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
711 /* Add common actions */
712 gtk_action_group_add_actions (action_group,
713 modest_msg_edit_action_entries,
714 G_N_ELEMENTS (modest_msg_edit_action_entries),
716 gtk_action_group_add_actions (action_group,
717 hildon2_msg_edit_action_entries,
718 G_N_ELEMENTS (hildon2_msg_edit_action_entries),
720 gtk_action_group_add_toggle_actions (action_group,
721 modest_msg_edit_toggle_action_entries,
722 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
724 gtk_action_group_add_radio_actions (action_group,
725 modest_msg_edit_alignment_radio_action_entries,
726 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
728 G_CALLBACK (modest_ui_actions_on_change_justify),
730 gtk_action_group_add_radio_actions (action_group,
731 modest_msg_edit_priority_action_entries,
732 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
734 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
736 gtk_action_group_add_radio_actions (action_group,
737 modest_msg_edit_file_format_action_entries,
738 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
739 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
740 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
742 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
743 g_object_unref (action_group);
745 /* Load the UI definition */
746 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
749 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
750 g_clear_error (&error);
753 /* Add accelerators */
754 gtk_window_add_accel_group (GTK_WINDOW (obj),
755 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
757 parent_priv->menubar = NULL;
759 title_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
760 value_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
762 /* Note: This ModestPairList* must exist for as long as the picker
763 * that uses it, because the ModestSelectorPicker uses the ID opaquely,
764 * so it can't know how to manage its memory. */
765 priv->from_field = modest_selector_picker_new (MODEST_EDITABLE_SIZE,
766 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL,
768 modest_maemo_utils_set_hbutton_layout (title_size_group, value_size_group,
769 _("mail_va_from"), priv->from_field);
771 priv->to_field = modest_recpt_editor_new ();
772 priv->cc_field = modest_recpt_editor_new ();
773 priv->bcc_field = modest_recpt_editor_new ();
774 subject_box = gtk_hbox_new (FALSE, 0);
775 priv->priority_icon = gtk_image_new ();
776 gtk_box_pack_start (GTK_BOX (subject_box), priv->priority_icon, FALSE, FALSE, 0);
777 priv->subject_field = hildon_entry_new (MODEST_EDITABLE_SIZE);
778 gtk_entry_set_max_length (GTK_ENTRY (priv->subject_field) ,SUBJECT_MAX_LENGTH);
779 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
780 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
781 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
782 gtk_box_pack_start (GTK_BOX (subject_box), priv->subject_field, TRUE, TRUE, 0);
783 priv->add_attachment_button = gtk_button_new ();
784 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
785 gtk_button_set_relief (GTK_BUTTON (priv->add_attachment_button), GTK_RELIEF_NONE);
786 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
787 gtk_button_set_alignment (GTK_BUTTON (priv->add_attachment_button), 1.0, 0.5);
788 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, HILDON_ICON_SIZE_FINGER);
789 gtk_container_add (GTK_CONTAINER (priv->add_attachment_button), attachment_icon);
790 gtk_box_pack_start (GTK_BOX (subject_box), priv->add_attachment_button, FALSE, FALSE, 0);
791 priv->attachments_view = modest_attachments_view_new (NULL);
793 priv->header_box = gtk_vbox_new (FALSE, 0);
795 to_caption = modest_maemo_utils_create_captioned_with_size_type
796 (title_size_group, value_size_group,
797 _("mail_va_to"), FALSE, priv->to_field,
798 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
799 priv->cc_caption = modest_maemo_utils_create_captioned_with_size_type
800 (title_size_group, value_size_group,
801 _("mail_va_cc"), FALSE, priv->cc_field,
802 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
803 priv->bcc_caption = modest_maemo_utils_create_captioned_with_size_type
804 (title_size_group, value_size_group,
805 _("mail_va_hotfix1"), FALSE, priv->bcc_field,
806 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
807 subject_caption = modest_maemo_utils_create_captioned (title_size_group, value_size_group,
808 _("mail_va_subject"), FALSE, subject_box);
809 priv->attachments_caption = modest_maemo_utils_create_captioned_with_size_type (title_size_group, value_size_group,
810 _("mail_va_attachment"),
812 priv->attachments_view,
813 HILDON_SIZE_AUTO_WIDTH |
814 HILDON_SIZE_AUTO_HEIGHT);
815 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), value_size_group); */
816 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), value_size_group); */
817 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), value_size_group); */
818 g_object_unref (title_size_group);
819 g_object_unref (value_size_group);
821 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->from_field, FALSE, FALSE, 0);
822 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
823 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
824 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
825 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
826 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
827 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
829 init_wp_text_view_style ();
831 priv->msg_body = wp_text_view_new ();
834 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
835 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
836 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
837 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
838 #if (GTK_MINOR_VERSION >= 10)
839 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
840 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
842 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
843 deserialize_type, TRUE);
845 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
847 priv->find_toolbar = hildon_find_toolbar_new (NULL);
848 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
850 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
852 priv->pannable = hildon_pannable_area_new ();
854 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
856 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
857 priv->frame = gtk_frame_new (NULL);
858 gtk_box_pack_start (GTK_BOX(main_vbox), priv->frame, TRUE, TRUE, 0);
860 hildon_pannable_area_add_with_viewport (HILDON_PANNABLE_AREA (priv->pannable), main_vbox);
861 gtk_container_set_focus_vadjustment (GTK_CONTAINER (main_vbox),
862 hildon_pannable_area_get_vadjustment (HILDON_PANNABLE_AREA (priv->pannable)));
863 gtk_widget_show_all (GTK_WIDGET(priv->pannable));
865 window_box = gtk_vbox_new (FALSE, 0);
866 gtk_container_add (GTK_CONTAINER(obj), window_box);
868 gtk_box_pack_start (GTK_BOX (window_box), priv->pannable, TRUE, TRUE, 0);
870 gtk_container_add (GTK_CONTAINER (priv->frame), priv->msg_body);
872 /* Set window icon */
873 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
875 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
876 g_object_unref (window_icon);
881 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
883 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
885 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
886 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
887 priv->clipboard_change_handler_id))
888 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
889 priv->clipboard_change_handler_id);
890 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
891 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
892 priv->default_clipboard_change_handler_id))
893 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
894 priv->default_clipboard_change_handler_id);
896 if (priv->account_removed_handler_id &&
897 g_signal_handler_is_connected (modest_runtime_get_account_store (),
898 priv->account_removed_handler_id))
899 g_signal_handler_disconnect(modest_runtime_get_account_store (),
900 priv->account_removed_handler_id);
904 modest_msg_edit_window_finalize (GObject *obj)
906 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
908 /* Sanity check: shouldn't be needed, the window mgr should
909 call this function before */
910 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
912 if (priv->font_dialog != NULL) {
913 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
916 if (priv->clipboard_text != NULL) {
917 g_free (priv->clipboard_text);
918 priv->clipboard_text = NULL;
921 if (priv->draft_msg != NULL) {
922 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
923 if (TNY_IS_HEADER (header)) {
924 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
925 modest_window_mgr_unregister_header (mgr, header);
927 g_object_unref (priv->draft_msg);
928 priv->draft_msg = NULL;
930 if (priv->outbox_msg != NULL) {
931 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
932 if (TNY_IS_HEADER (header)) {
933 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
934 modest_window_mgr_unregister_header (mgr, header);
936 g_object_unref (priv->outbox_msg);
937 priv->outbox_msg = NULL;
939 if (priv->correct_scroll_idle > 0) {
940 g_source_remove (priv->correct_scroll_idle);
941 priv->correct_scroll_idle = 0;
943 if (priv->scroll_drag_timeout_id > 0) {
944 g_source_remove (priv->scroll_drag_timeout_id);
945 priv->scroll_drag_timeout_id = 0;
947 if (priv->clipboard_owner_idle > 0) {
948 g_source_remove (priv->clipboard_owner_idle);
949 priv->clipboard_owner_idle = 0;
951 if (priv->original_account_name)
952 g_free (priv->original_account_name);
953 g_free (priv->msg_uid);
954 g_free (priv->last_search);
955 g_slist_free (priv->font_items_group);
956 g_slist_free (priv->size_items_group);
957 g_object_unref (priv->attachments);
958 g_object_unref (priv->images);
960 /* This had to stay alive for as long as the picker that used it: */
961 modest_pair_list_free (priv->from_field_protos);
963 G_OBJECT_CLASS(parent_class)->finalize (obj);
967 pixbuf_from_stream (TnyStream *stream, const gchar *mime_type, guint64 *stream_size)
969 GdkPixbufLoader *loader;
975 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
977 if (loader == NULL) {
983 tny_stream_reset (TNY_STREAM (stream));
984 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
985 GError *error = NULL;
986 unsigned char read_buffer[128];
988 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
990 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
992 g_error_free (error);
997 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
999 g_object_ref (pixbuf);
1000 gdk_pixbuf_loader_close (loader, NULL);
1001 g_object_unref (loader);
1006 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1007 GdkPixbuf *new_pixbuf;
1009 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1010 gdk_pixbuf_get_width (pixbuf);
1011 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1012 g_object_unref (pixbuf);
1013 pixbuf = new_pixbuf;
1017 *stream_size = size;
1023 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1025 ModestMsgEditWindowPrivate *priv;
1028 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1030 for (iter = tny_list_create_iterator (attachments);
1031 !tny_iterator_is_done (iter);
1032 tny_iterator_next (iter)) {
1033 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1034 const gchar *cid = tny_mime_part_get_content_id (part);
1035 const gchar *mime_type = tny_mime_part_get_content_type (part);
1036 if ((cid != NULL)&&(mime_type != NULL)) {
1037 guint64 stream_size;
1038 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1039 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
1042 g_object_unref (stream);
1044 if (pixbuf != NULL) {
1045 priv->images_count ++;
1046 priv->images_size += stream_size;
1047 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1048 g_object_unref (pixbuf);
1051 g_object_unref (part);
1053 g_object_unref (iter);
1057 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1059 TnyMimePart *parent = NULL;
1060 const gchar *content_type = NULL;
1061 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1063 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1065 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1066 parent = g_object_ref (msg);
1067 } else if (content_type && !g_strcasecmp (content_type, "multipart/mixed")) {
1068 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1071 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1072 iter = tny_list_create_iterator (parts);
1073 while (!tny_iterator_is_done (iter)) {
1075 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1076 content_type = tny_mime_part_get_content_type (part);
1077 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1081 g_object_unref (part);
1083 tny_iterator_next (iter);
1085 g_object_unref (iter);
1086 g_object_unref (parts);
1089 if (parent != NULL) {
1090 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1093 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1094 iter = tny_list_create_iterator (parts);
1095 while (!tny_iterator_is_done (iter)) {
1097 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1098 content_type = tny_mime_part_get_content_type (part);
1099 if (content_type && g_str_has_prefix (content_type, "image/")) {
1100 tny_list_prepend (priv->images, (GObject *) part);
1102 g_object_unref (part);
1103 tny_iterator_next (iter);
1105 g_object_unref (iter);
1106 g_object_unref (parts);
1107 g_object_unref (parent);
1112 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1115 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1117 for (iter = tny_list_create_iterator (attachments) ;
1118 !tny_iterator_is_done (iter);
1119 tny_iterator_next (iter)) {
1120 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1121 const gchar *cid = tny_mime_part_get_content_id (part);
1123 char *invalid = NULL;
1124 gint int_cid = strtol (cid, &invalid, 10);
1125 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1126 priv->next_cid = int_cid + 1;
1129 g_object_unref (part);
1131 g_object_unref (iter);
1135 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1138 gchar *to, *cc, *bcc, *subject;
1140 ModestMsgEditWindowPrivate *priv;
1141 ModestWindowPrivate *parent_priv;
1143 TnyHeaderFlags priority_flags;
1144 TnyFolder *msg_folder;
1145 gboolean is_html = FALSE;
1146 gboolean field_view_set;
1148 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1149 g_return_if_fail (TNY_IS_MSG (msg));
1151 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1152 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1154 header = tny_msg_get_header (msg);
1155 to = tny_header_dup_to (header);
1156 cc = tny_header_dup_cc (header);
1157 bcc = tny_header_dup_bcc (header);
1158 subject = tny_header_dup_subject (header);
1159 priority_flags = tny_header_get_priority (header);
1162 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
1164 field_view_set = TRUE;
1166 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
1167 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1168 gtk_widget_show (priv->cc_caption);
1169 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1170 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1171 gtk_widget_hide (priv->cc_caption);
1172 field_view_set = FALSE;
1174 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button), field_view_set);
1176 field_view_set = TRUE;
1178 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
1179 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1180 gtk_widget_show (priv->bcc_caption);
1181 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1182 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1183 gtk_widget_hide (priv->bcc_caption);
1184 field_view_set = FALSE;
1186 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button), field_view_set);
1190 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1191 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1194 update_window_title (self);
1196 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1197 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1199 if ((body == NULL)||(body[0] == '\0')) {
1201 body = modest_text_utils_convert_to_html ("");
1204 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1205 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1208 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1211 /* Add attachments to the view */
1212 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1213 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1214 if (tny_list_get_length (priv->attachments) == 0) {
1215 gtk_widget_hide (priv->attachments_caption);
1217 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1218 gtk_widget_show_all (priv->attachments_caption);
1220 get_related_images (self, msg);
1221 update_next_cid (self, priv->attachments);
1222 update_next_cid (self, priv->images);
1223 replace_with_images (self, priv->images);
1225 if (preserve_is_rich && !is_html) {
1226 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1227 /* Get the default format required from configuration */
1228 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1229 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1232 /* Set the default focus depending on having already a To: field or not */
1233 if ((!to)||(*to == '\0')) {
1234 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1236 gtk_widget_grab_focus (priv->msg_body);
1239 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1241 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1242 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1244 modest_msg_edit_window_set_modified (self, FALSE);
1246 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1247 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1248 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1249 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1251 if (priv->msg_uid) {
1252 g_free (priv->msg_uid);
1253 priv->msg_uid = NULL;
1256 /* we should set a reference to the incoming message if it is a draft */
1257 msg_folder = tny_msg_get_folder (msg);
1259 if (modest_tny_folder_is_local_folder (msg_folder)) {
1260 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1261 if (type == TNY_FOLDER_TYPE_INVALID)
1262 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1264 if (type == TNY_FOLDER_TYPE_DRAFTS)
1265 priv->draft_msg = g_object_ref(msg);
1266 if (type == TNY_FOLDER_TYPE_OUTBOX)
1267 priv->outbox_msg = g_object_ref(msg);
1268 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1270 g_object_unref (msg_folder);
1280 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
1283 GList *item_children, *node;
1284 GtkWidget *bin_child;
1286 bin_child = gtk_bin_get_child (GTK_BIN(item));
1288 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
1290 for (node = item_children; node != NULL; node = g_list_next (node)) {
1291 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
1292 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
1295 g_list_free (item_children);
1299 menu_tool_button_dont_expand (GtkMenuToolButton *item)
1302 GList *item_children, *node;
1304 box = gtk_bin_get_child (GTK_BIN (item));
1305 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
1306 item_children = gtk_container_get_children (GTK_CONTAINER (box));
1308 for (node = item_children; node != NULL; node = g_list_next (node)) {
1309 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
1310 if (GTK_IS_TOGGLE_BUTTON (node->data))
1311 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
1312 else if (GTK_IS_BUTTON (node->data))
1313 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
1315 g_list_free (item_children);
1320 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1322 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1323 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1324 GtkWidget *placeholder;
1325 GtkWidget *tool_item;
1330 GtkWidget *sizes_menu;
1331 GtkWidget *fonts_menu;
1332 GSList *radio_group = NULL;
1333 GSList *node = NULL;
1337 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1338 gtk_toolbar_set_icon_size (GTK_TOOLBAR (parent_priv->toolbar), HILDON_ICON_SIZE_FINGER);
1339 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1341 /* Font color placeholder */
1342 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1343 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1346 priv->font_color_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1347 priv->font_color_button = hildon_color_button_new ();
1348 GTK_WIDGET_UNSET_FLAGS (priv->font_color_toolitem, GTK_CAN_FOCUS);
1349 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1350 gtk_container_add (GTK_CONTAINER (priv->font_color_toolitem), priv->font_color_button);
1351 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1352 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1353 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->font_color_toolitem), insert_index);
1354 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1356 G_CALLBACK (modest_msg_edit_window_color_button_change),
1359 /* Font size and face placeholder */
1360 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1361 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1363 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1364 priv->size_tool_button_label = gtk_label_new (NULL);
1365 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1366 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1367 size_text,"</span>", NULL);
1368 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1370 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
1371 sizes_menu = gtk_menu_new ();
1372 priv->size_items_group = NULL;
1374 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1375 GtkWidget *size_menu_item;
1377 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1378 size_menu_item = gtk_radio_menu_item_new_with_label (radio_group, size_text);
1379 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (size_menu_item));
1380 gtk_menu_shell_append (GTK_MENU_SHELL (sizes_menu), size_menu_item);
1381 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (size_menu_item), (wp_font_size[size_index] == 12));
1382 gtk_widget_show (size_menu_item);
1384 priv->size_items_group = g_slist_prepend (priv->size_items_group, size_menu_item);
1388 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1389 GtkWidget *item = (GtkWidget *) node->data;
1390 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_size_change),
1394 priv->size_items_group = g_slist_reverse (priv->size_items_group);
1395 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), sizes_menu);
1396 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1397 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1398 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1399 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1400 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1401 priv->font_size_toolitem = tool_item;
1404 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1405 priv->font_tool_button_label = gtk_label_new (NULL);
1406 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1407 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1409 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
1410 fonts_menu = gtk_menu_new ();
1411 priv->font_items_group = NULL;
1413 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1414 GtkWidget *font_menu_item;
1415 GtkWidget *child_label;
1417 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
1418 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
1419 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
1420 wp_get_font_name (font_index), "</span>", NULL);
1421 gtk_label_set_markup (GTK_LABEL (child_label), markup);
1424 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
1425 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
1426 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
1427 gtk_widget_show (font_menu_item);
1429 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
1432 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1433 GtkWidget *item = (GtkWidget *) node->data;
1434 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
1437 priv->font_items_group = g_slist_reverse (priv->font_items_group);
1438 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
1439 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1440 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1441 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1442 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1443 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1444 priv->font_face_toolitem = tool_item;
1446 /* Set expand and homogeneous for remaining items */
1447 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
1448 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1449 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1450 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1451 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1452 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1453 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1454 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1455 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1457 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1458 will not show the tool items added to the placeholders) */
1459 gtk_widget_show_all (parent_priv->toolbar);
1461 /* Set the no show all *after* showing all items. We do not
1462 want the toolbar to be shown with a show all because it
1463 could go agains the gconf setting regarding showing or not
1464 the toolbar of the editor window */
1465 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1471 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, gboolean preserve_is_rich)
1474 ModestWindowPrivate *parent_priv;
1475 ModestMsgEditWindowPrivate *priv;
1476 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1477 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1478 ModestWindowMgr *mgr = NULL;
1480 g_return_val_if_fail (msg, NULL);
1481 g_return_val_if_fail (account_name, NULL);
1483 mgr = modest_runtime_get_window_mgr ();
1485 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1487 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1488 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1490 /* Menubar. Update the state of some toggles */
1491 priv->from_field_protos = get_transports ();
1492 modest_selector_picker_set_pair_list (MODEST_SELECTOR_PICKER (priv->from_field), priv->from_field_protos);
1493 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1494 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1496 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1497 hildon_touch_selector_get_current_text
1498 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1499 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1500 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1503 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1505 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1507 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1509 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1511 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1512 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1513 /* Add common dimming rules */
1514 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1515 modest_msg_edit_window_toolbar_dimming_entries,
1516 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1517 MODEST_WINDOW (obj));
1518 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_toolitem,
1519 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1520 MODEST_WINDOW (obj));
1521 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1522 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1523 MODEST_WINDOW (obj));
1524 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1525 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1526 MODEST_WINDOW (obj));
1527 /* Insert dimming rules group for this window */
1528 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1529 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1531 /* Setup app menu */
1532 setup_menu (MODEST_MSG_EDIT_WINDOW (obj));
1534 /* Checks the dimming rules */
1535 g_object_unref (toolbar_rules_group);
1536 g_object_unref (clipboard_rules_group);
1537 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1539 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1541 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1542 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1543 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1544 priv->update_caption_visibility = TRUE;
1546 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1548 /* Track account-removed signal, this window should be closed
1549 in the case we're creating a mail associated to the account
1551 priv->account_removed_handler_id =
1552 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1554 G_CALLBACK(on_account_removed),
1557 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1559 return (ModestWindow*) obj;
1563 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1565 GString **string_buffer = (GString **) user_data;
1567 *string_buffer = g_string_append (*string_buffer, buffer);
1573 * @result: A new string which should be freed with g_free().
1576 get_formatted_data (ModestMsgEditWindow *edit_window)
1578 ModestMsgEditWindowPrivate *priv;
1579 GString *string_buffer = g_string_new ("");
1581 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1583 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1585 modest_text_utils_hyperlinkify (string_buffer);
1587 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1589 return g_string_free (string_buffer, FALSE);
1594 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1597 const gchar *account_name;
1598 ModestMsgEditWindowPrivate *priv;
1599 TnyIterator *att_iter;
1601 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1603 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1605 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1606 g_return_val_if_fail (account_name, NULL);
1609 /* don't free these (except from) */
1610 data = g_slice_new0 (MsgData);
1611 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1613 data->account_name = g_strdup (account_name);
1614 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1615 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1616 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1617 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1618 if (priv->draft_msg) {
1619 data->draft_msg = g_object_ref (priv->draft_msg);
1620 } else if (priv->outbox_msg) {
1621 data->draft_msg = g_object_ref (priv->outbox_msg);
1623 data->draft_msg = NULL;
1626 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1628 gtk_text_buffer_get_bounds (buf, &b, &e);
1629 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1631 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1632 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1634 data->html_body = NULL;
1636 /* deep-copy the data */
1637 att_iter = tny_list_create_iterator (priv->attachments);
1638 data->attachments = NULL;
1639 while (!tny_iterator_is_done (att_iter)) {
1640 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1641 if (!(TNY_IS_MIME_PART(part))) {
1642 g_warning ("strange data in attachment list");
1643 g_object_unref (part);
1644 tny_iterator_next (att_iter);
1647 data->attachments = g_list_append (data->attachments,
1649 tny_iterator_next (att_iter);
1651 g_object_unref (att_iter);
1653 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1654 att_iter = tny_list_create_iterator (priv->images);
1655 data->images = NULL;
1656 while (!tny_iterator_is_done (att_iter)) {
1657 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1659 if (!(TNY_IS_MIME_PART(part))) {
1660 g_warning ("strange data in attachment list");
1661 g_object_unref (part);
1662 tny_iterator_next (att_iter);
1665 cid = tny_mime_part_get_content_id (part);
1667 gchar *image_tag_id;
1668 GtkTextTag *image_tag;
1670 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1671 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1672 g_free (image_tag_id);
1674 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1676 ((gtk_text_iter_has_tag (&iter, image_tag))||
1677 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1678 data->images = g_list_append (data->images,
1679 g_object_ref (part));
1681 g_object_unref (part);
1682 tny_iterator_next (att_iter);
1684 g_object_unref (att_iter);
1686 data->priority_flags = priv->priority_flags;
1693 unref_gobject (GObject *obj, gpointer data)
1695 if (!G_IS_OBJECT(obj))
1697 g_object_unref (obj);
1701 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1704 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1712 g_free (data->from);
1713 g_free (data->subject);
1714 g_free (data->plain_body);
1715 g_free (data->html_body);
1716 g_free (data->account_name);
1718 if (data->draft_msg != NULL) {
1719 g_object_unref (data->draft_msg);
1720 data->draft_msg = NULL;
1723 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1724 g_list_free (data->attachments);
1725 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1726 g_list_free (data->images);
1728 g_slice_free (MsgData, data);
1732 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1734 guint64 *parts_size)
1736 ModestMsgEditWindowPrivate *priv;
1738 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1740 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1742 /* TODO: add images */
1743 *parts_size += priv->images_size;
1744 *parts_count += priv->images_count;
1749 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1752 ModestMsgEditWindowPrivate *priv = NULL;
1753 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1755 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1757 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1759 return MODEST_MSG_EDIT_FORMAT_HTML;
1761 return MODEST_MSG_EDIT_FORMAT_TEXT;
1765 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1766 ModestMsgEditFormat format)
1768 ModestMsgEditWindowPrivate *priv;
1770 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1771 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1774 case MODEST_MSG_EDIT_FORMAT_HTML:
1775 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1777 case MODEST_MSG_EDIT_FORMAT_TEXT:
1778 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1781 g_return_if_reached ();
1785 ModestMsgEditFormatState *
1786 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1788 ModestMsgEditFormatState *format_state = NULL;
1789 ModestMsgEditWindowPrivate *priv;
1790 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1792 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1793 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1795 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1797 format_state = g_new0 (ModestMsgEditFormatState, 1);
1798 format_state->bold = buffer_format->bold&0x1;
1799 format_state->italics = buffer_format->italic&0x1;
1800 format_state->bullet = buffer_format->bullet&0x1;
1801 format_state->color = buffer_format->color;
1802 format_state->font_size = buffer_format->font_size;
1803 format_state->font_family = wp_get_font_name (buffer_format->font);
1804 format_state->justification = buffer_format->justification;
1805 g_free (buffer_format);
1807 return format_state;
1812 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1813 const ModestMsgEditFormatState *format_state)
1815 ModestMsgEditWindowPrivate *priv;
1816 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1817 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1818 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1819 g_return_if_fail (format_state != NULL);
1821 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1822 gtk_widget_grab_focus (priv->msg_body);
1823 buffer_format->bold = (format_state->bold != FALSE);
1824 buffer_format->italic = (format_state->italics != FALSE);
1825 buffer_format->color = format_state->color;
1826 buffer_format->font_size = format_state->font_size;
1827 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1828 buffer_format->justification = format_state->justification;
1829 buffer_format->bullet = format_state->bullet;
1831 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1833 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1834 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1835 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1836 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1837 buffer_format->cs.font = (buffer_format->font != current_format->font);
1838 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1839 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1841 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1842 if (buffer_format->cs.bold) {
1843 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
1844 GINT_TO_POINTER (buffer_format->bold&0x1));
1846 if (buffer_format->cs.italic) {
1847 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
1848 GINT_TO_POINTER (buffer_format->italic&0x1));
1850 if (buffer_format->cs.color) {
1851 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1852 GINT_TO_POINTER (&(buffer_format->color)));
1854 if (buffer_format->cs.font_size) {
1855 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1856 GINT_TO_POINTER (buffer_format->font_size));
1858 if (buffer_format->cs.justification) {
1859 switch (buffer_format->justification) {
1860 case GTK_JUSTIFY_LEFT:
1861 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
1862 GINT_TO_POINTER(TRUE));
1864 case GTK_JUSTIFY_CENTER:
1865 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
1866 GINT_TO_POINTER(TRUE));
1868 case GTK_JUSTIFY_RIGHT:
1869 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
1870 GINT_TO_POINTER(TRUE));
1877 if (buffer_format->cs.font) {
1878 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1879 GINT_TO_POINTER (buffer_format->font));
1881 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1882 if (buffer_format->cs.bullet) {
1883 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
1884 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
1886 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1888 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
1890 g_free (buffer_format);
1891 g_free (current_format);
1893 /* Check dimming rules */
1894 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1895 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1899 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1901 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1903 ModestWindowPrivate *parent_priv;
1904 ModestMsgEditWindowPrivate *priv;
1905 GtkWidget *new_size_menuitem;
1906 GtkWidget *new_font_menuitem;
1908 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1909 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1911 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1912 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu");
1913 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1914 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1916 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatPlainTextMenu");
1917 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1918 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1921 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1923 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1924 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1926 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1927 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1929 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
1930 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
1933 switch (buffer_format->justification)
1935 case GTK_JUSTIFY_LEFT:
1936 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
1938 case GTK_JUSTIFY_CENTER:
1939 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
1941 case GTK_JUSTIFY_RIGHT:
1942 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
1949 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
1951 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1952 G_CALLBACK (modest_msg_edit_window_color_button_change),
1954 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1955 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1956 G_CALLBACK (modest_msg_edit_window_color_button_change),
1959 new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group,
1960 buffer_format->font_size))->data);
1961 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1965 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1966 markup = g_strconcat ("<span font_family='Sans'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1967 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1969 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1970 G_CALLBACK (modest_msg_edit_window_size_change),
1972 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
1973 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
1974 G_CALLBACK (modest_msg_edit_window_size_change),
1978 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
1979 buffer_format->font))->data);
1980 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
1984 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
1985 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1986 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1988 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
1989 G_CALLBACK (modest_msg_edit_window_font_change),
1991 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
1992 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
1993 G_CALLBACK (modest_msg_edit_window_font_change),
1997 g_free (buffer_format);
2001 #ifdef MODEST_HILDON_VERSION_0
2003 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2006 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2007 ModestMsgEditWindowPrivate *priv;
2008 GtkWidget *dialog = NULL;
2010 GdkColor *new_color = NULL;
2012 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2013 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2015 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2016 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
2017 g_free (buffer_format);
2019 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2020 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2021 if (new_color != NULL) {
2022 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2023 (gpointer) new_color);
2026 gtk_widget_destroy (dialog);
2031 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2034 ModestMsgEditWindowPrivate *priv;
2035 GtkWidget *dialog = NULL;
2037 GdkColor *old_color = NULL;
2038 const GdkColor *new_color = NULL;
2040 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2041 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2043 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2044 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2046 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2047 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2048 if (new_color != NULL)
2049 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2051 gtk_widget_destroy (dialog);
2057 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2060 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2061 ModestMsgEditWindowPrivate *priv;
2062 GtkWidget *dialog = NULL;
2064 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2065 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2067 dialog = hildon_color_chooser_new ();
2068 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2069 g_free (buffer_format);
2071 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2073 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2074 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2077 gtk_widget_destroy (dialog);
2082 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2085 ModestMsgEditWindowPrivate *priv;
2086 GtkWidget *dialog = NULL;
2087 GdkColor *old_color = NULL;
2089 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2090 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2092 dialog = hildon_color_chooser_new ();
2093 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2095 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2097 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2098 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2100 gtk_widget_destroy (dialog);
2103 #endif /*!MODEST_HILDON_VERSION_0*/
2108 create_stream_for_uri (const gchar* uri)
2113 TnyStream *result = NULL;
2115 GnomeVFSHandle *handle = NULL;
2116 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2117 if (test == GNOME_VFS_OK) {
2118 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2119 /* Streams over OBEX (Bluetooth) are not seekable but
2120 * we expect them to be (we might need to read them
2121 * several times). So if this is a Bluetooth URI just
2122 * read the whole file into memory (this is not a fast
2123 * protocol so we can assume that these files are not
2124 * going to be very big) */
2125 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2126 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2127 TnyStream *memstream = tny_camel_mem_stream_new ();
2128 tny_stream_write_to_stream (vfssstream, memstream);
2129 g_object_unref (vfssstream);
2132 result = vfssstream;
2140 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2143 ModestMsgEditWindowPrivate *priv;
2144 GtkWidget *dialog = NULL;
2146 GSList *uris = NULL;
2147 GSList *uri_node = NULL;
2149 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2151 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2152 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2153 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2155 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2157 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2158 GTK_WINDOW (dialog), GTK_WINDOW (window));
2160 response = gtk_dialog_run (GTK_DIALOG (dialog));
2162 case GTK_RESPONSE_OK:
2163 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2168 gtk_widget_destroy (dialog);
2170 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2172 GnomeVFSHandle *handle = NULL;
2173 GnomeVFSResult result;
2174 GtkTextIter position;
2175 GtkTextMark *insert_mark;
2177 uri = (const gchar *) uri_node->data;
2178 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2179 if (result == GNOME_VFS_OK) {
2181 GnomeVFSFileInfo *info;
2182 gchar *filename, *basename, *escaped_filename;
2183 TnyMimePart *mime_part;
2185 const gchar *mime_type = NULL;
2186 GnomeVFSURI *vfs_uri;
2187 guint64 stream_size;
2189 gnome_vfs_close (handle);
2190 vfs_uri = gnome_vfs_uri_new (uri);
2192 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2193 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2194 g_free (escaped_filename);
2195 gnome_vfs_uri_unref (vfs_uri);
2196 info = gnome_vfs_file_info_new ();
2198 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2199 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2201 mime_type = gnome_vfs_file_info_get_mime_type (info);
2203 mime_part = tny_platform_factory_new_mime_part
2204 (modest_runtime_get_platform_factory ());
2206 TnyStream *stream = create_stream_for_uri (uri);
2208 if (stream == NULL) {
2210 modest_platform_information_banner (NULL, NULL,
2211 _FM("sfil_ib_opening_not_allowed"));
2213 g_object_unref (mime_part);
2214 gnome_vfs_file_info_unref (info);
2218 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2220 content_id = g_strdup_printf ("%d", priv->next_cid);
2221 tny_mime_part_set_content_id (mime_part, content_id);
2222 g_free (content_id);
2225 basename = g_path_get_basename (filename);
2226 tny_mime_part_set_filename (mime_part, basename);
2229 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
2231 if (pixbuf != NULL) {
2232 priv->images_size += stream_size;
2233 priv->images_count ++;
2234 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2235 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2236 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
2237 g_object_unref (pixbuf);
2240 tny_list_prepend (priv->images, (GObject *) mime_part);
2241 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2243 g_object_unref (mime_part);
2244 gnome_vfs_file_info_unref (info);
2253 on_attach_file_response (GtkDialog *dialog,
2257 GSList *uris = NULL;
2259 GnomeVFSFileSize total_size, allowed_size;
2260 ModestMsgEditWindow *window;
2261 ModestMsgEditWindowPrivate *priv;
2266 case GTK_RESPONSE_OK:
2267 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2273 window = MODEST_MSG_EDIT_WINDOW (user_data);
2274 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2276 /* allowed size is the maximum size - what's already there */
2277 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2278 &att_num, &att_size);
2279 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2282 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2284 const gchar *uri = (const gchar *) uri_node->data;
2287 modest_msg_edit_window_attach_file_one (window, uri, allowed_size);
2289 if (total_size > allowed_size) {
2290 g_warning ("%s: total size: %u",
2291 __FUNCTION__, (unsigned int)total_size);
2294 allowed_size -= total_size;
2296 g_slist_foreach (uris, (GFunc) g_free, NULL);
2297 g_slist_free (uris);
2299 gtk_widget_destroy (GTK_WIDGET (dialog));
2303 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2305 GtkWidget *dialog = NULL;
2306 ModestMsgEditWindowPrivate *priv;
2308 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2310 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2312 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2315 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window),
2316 GTK_FILE_CHOOSER_ACTION_OPEN);
2317 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2318 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2319 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2320 GTK_WINDOW (dialog), GTK_WINDOW (window));
2322 /* Connect to response & show */
2323 g_signal_connect (dialog, "response",
2324 G_CALLBACK (on_attach_file_response), window);
2325 gtk_widget_show (dialog);
2330 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2332 GnomeVFSFileSize allowed_size)
2335 GnomeVFSHandle *handle = NULL;
2336 ModestMsgEditWindowPrivate *priv;
2337 GnomeVFSResult result;
2338 GnomeVFSFileSize size = 0;
2339 g_return_val_if_fail (window, 0);
2340 g_return_val_if_fail (uri, 0);
2342 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2344 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2345 if (result == GNOME_VFS_OK) {
2346 TnyMimePart *mime_part;
2348 const gchar *mime_type = NULL;
2350 gchar *escaped_filename;
2353 GnomeVFSFileInfo *info;
2354 GnomeVFSURI *vfs_uri;
2356 gnome_vfs_close (handle);
2357 vfs_uri = gnome_vfs_uri_new (uri);
2360 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2361 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2362 g_free (escaped_filename);
2363 gnome_vfs_uri_unref (vfs_uri);
2365 info = gnome_vfs_file_info_new ();
2367 if (gnome_vfs_get_file_info (uri,
2369 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2371 mime_type = gnome_vfs_file_info_get_mime_type (info);
2372 mime_part = tny_platform_factory_new_mime_part
2373 (modest_runtime_get_platform_factory ());
2375 /* try to get the attachment's size; this may fail for weird
2376 * file systems, like obex, upnp... */
2377 if (allowed_size != 0 &&
2378 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2380 if (size > allowed_size) {
2381 modest_platform_information_banner (NULL, NULL,
2382 _FM("sfil_ib_opening_not_allowed"));
2386 g_warning ("%s: could not get attachment size", __FUNCTION__);
2388 stream = create_stream_for_uri (uri);
2390 if (stream == NULL) {
2392 modest_platform_information_banner (NULL, NULL, _FM("sfil_ib_opening_not_allowed"));
2394 g_object_unref (mime_part);
2395 gnome_vfs_file_info_unref (info);
2399 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2400 g_object_unref (stream);
2402 content_id = g_strdup_printf ("%d", priv->next_cid);
2403 tny_mime_part_set_content_id (mime_part, content_id);
2404 g_free (content_id);
2407 basename = g_path_get_basename (filename);
2408 tny_mime_part_set_filename (mime_part, basename);
2411 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2412 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2414 info->size == 0, info->size);
2415 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2416 gtk_widget_show_all (priv->attachments_caption);
2417 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2419 g_object_unref (mime_part);
2420 gnome_vfs_file_info_unref (info);
2427 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2430 ModestMsgEditWindowPrivate *priv;
2433 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2434 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2436 if (att_list == NULL) {
2437 att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2439 g_object_ref (att_list);
2442 if (tny_list_get_length (att_list) == 0) {
2443 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2445 gboolean dialog_response;
2446 gchar *message = NULL;
2447 gchar *filename = NULL;
2449 if (tny_list_get_length (att_list) == 1) {
2451 iter = tny_list_create_iterator (att_list);
2452 part = (TnyMimePart *) tny_iterator_get_current (iter);
2453 g_object_unref (iter);
2454 if (TNY_IS_MSG (part)) {
2455 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2457 filename = tny_header_dup_subject (header);
2458 g_object_unref (header);
2460 if (filename == NULL) {
2461 filename = g_strdup (_("mail_va_no_subject"));
2464 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2466 g_object_unref (part);
2468 filename = g_strdup ("");
2470 message = g_strdup_printf (ngettext("emev_nc_delete_attachment",
2471 "emev_nc_delete_attachments",
2472 tny_list_get_length (att_list)), filename);
2475 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
2479 if (dialog_response != GTK_RESPONSE_OK) {
2480 g_object_unref (att_list);
2484 for (iter = tny_list_create_iterator (att_list);
2485 !tny_iterator_is_done (iter);
2486 tny_iterator_next (iter)) {
2487 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2488 const gchar *att_id;
2489 tny_list_remove (priv->attachments, (GObject *) mime_part);
2491 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2493 if (tny_list_get_length (priv->attachments) == 0)
2494 gtk_widget_hide (priv->attachments_caption);
2495 att_id = tny_mime_part_get_content_id (mime_part);
2497 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2499 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2500 g_object_unref (mime_part);
2502 g_object_unref (iter);
2505 g_object_unref (att_list);
2507 /* if the last attachment has been removed, focus the Subject: field */
2508 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2509 gtk_widget_grab_focus (priv->subject_field);
2513 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2516 ModestMsgEditWindowPrivate *priv;
2517 GdkColor *new_color;
2518 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2520 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2521 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2524 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2526 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2528 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2530 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2535 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
2538 ModestMsgEditWindowPrivate *priv;
2539 gint new_size_index;
2540 ModestMsgEditWindow *window;
2543 window = MODEST_MSG_EDIT_WINDOW (userdata);
2544 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2545 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2547 if (gtk_check_menu_item_get_active (menu_item)) {
2549 WPTextBufferFormat format;
2551 memset (&format, 0, sizeof (format));
2552 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2554 label = gtk_bin_get_child (GTK_BIN (menu_item));
2556 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
2557 format.cs.font_size = TRUE;
2558 format.cs.text_position = TRUE;
2559 format.cs.font = TRUE;
2560 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
2561 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2563 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2564 GINT_TO_POINTER (wp_get_font_size_index (new_size_index, 12))))
2565 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2567 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2568 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
2569 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2575 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
2578 ModestMsgEditWindowPrivate *priv;
2579 gint new_font_index;
2580 ModestMsgEditWindow *window;
2583 window = MODEST_MSG_EDIT_WINDOW (userdata);
2584 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2585 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2587 if (gtk_check_menu_item_get_active (menu_item)) {
2590 label = gtk_bin_get_child (GTK_BIN (menu_item));
2592 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
2594 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2595 GINT_TO_POINTER(new_font_index)))
2596 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2598 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2599 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2600 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2606 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2609 ModestMsgEditWindowPrivate *priv = NULL;
2610 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2612 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2613 if (!priv->update_caption_visibility)
2616 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2618 gtk_widget_show (priv->cc_caption);
2620 gtk_widget_hide (priv->cc_caption);
2622 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2626 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2629 ModestMsgEditWindowPrivate *priv = NULL;
2630 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2632 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2633 if (!priv->update_caption_visibility)
2636 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2638 gtk_widget_show (priv->bcc_caption);
2640 gtk_widget_hide (priv->bcc_caption);
2642 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2646 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2647 ModestRecptEditor *editor)
2649 ModestMsgEditWindowPrivate *priv;
2651 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2652 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2654 /* we check for low-mem; in that case, show a warning, and don't allow
2655 * for the addressbook
2657 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2660 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2662 if (editor == NULL) {
2663 GtkWidget *view_focus;
2664 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2666 /* This code should be kept in sync with ModestRecptEditor. The
2667 textview inside the recpt editor is the one that really gets the
2668 focus. As it's inside a scrolled window, and this one inside the
2669 hbox recpt editor inherits from, we'll need to go up in the
2670 hierarchy to know if the text view is part of the recpt editor
2671 or if it's a different text entry */
2673 if (gtk_widget_get_parent (view_focus)) {
2674 GtkWidget *first_parent;
2676 first_parent = gtk_widget_get_parent (view_focus);
2677 if (gtk_widget_get_parent (first_parent) &&
2678 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2679 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2684 editor = MODEST_RECPT_EDITOR (priv->to_field);
2688 modest_address_book_select_addresses (editor);
2693 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2695 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2697 modest_msg_edit_window_open_addressbook (window, NULL);
2701 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2702 gboolean show_toolbar)
2704 ModestWindowPrivate *parent_priv;
2706 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2707 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2709 /* We can not just use the code of
2710 modest_msg_edit_window_setup_toolbar because it has a
2711 mixture of both initialization and creation code. */
2713 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2715 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2719 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2720 TnyHeaderFlags priority_flags)
2722 ModestMsgEditWindowPrivate *priv;
2723 ModestWindowPrivate *parent_priv;
2725 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2727 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2728 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2730 if (priv->priority_flags != priority_flags) {
2731 GtkAction *priority_action = NULL;
2733 priv->priority_flags = priority_flags;
2735 switch (priority_flags) {
2736 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2737 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2738 MODEST_HEADER_ICON_HIGH,
2739 HILDON_ICON_SIZE_XSMALL);
2740 gtk_widget_show (priv->priority_icon);
2741 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2742 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2744 case TNY_HEADER_FLAG_LOW_PRIORITY:
2745 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2746 MODEST_HEADER_ICON_LOW,
2747 HILDON_ICON_SIZE_XSMALL);
2748 gtk_widget_show (priv->priority_icon);
2749 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2750 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2753 gtk_widget_hide (priv->priority_icon);
2754 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2755 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2758 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2759 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2764 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2767 ModestMsgEditWindowPrivate *priv;
2768 ModestWindowPrivate *parent_priv;
2769 gint current_format;
2771 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2773 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2774 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2776 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2777 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2779 if (current_format != file_format) {
2780 switch (file_format) {
2781 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2782 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2783 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
2785 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2789 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2790 response = gtk_dialog_run (GTK_DIALOG (dialog));
2791 gtk_widget_destroy (dialog);
2792 if (response == GTK_RESPONSE_OK) {
2793 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2795 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
2796 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
2801 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2802 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2803 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2808 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2811 ModestMsgEditWindowPrivate *priv;
2812 WPTextBufferFormat oldfmt, fmt;
2813 gint old_position = 0;
2817 GdkColor *color = NULL;
2818 gboolean bold, bold_set, italic, italic_set;
2819 gboolean underline, underline_set;
2820 gboolean strikethrough, strikethrough_set;
2821 gboolean position_set;
2822 gboolean font_size_set, font_set, color_set;
2825 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2826 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2828 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2829 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
2830 GTK_WINDOW(dialog), GTK_WINDOW (window));
2832 /* First we get the currently selected font information */
2833 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2835 switch (oldfmt.text_position) {
2836 case TEXT_POSITION_NORMAL:
2839 case TEXT_POSITION_SUPERSCRIPT:
2847 g_object_set (G_OBJECT (dialog),
2848 "bold", oldfmt.bold != FALSE,
2849 "bold-set", !oldfmt.cs.bold,
2850 "underline", oldfmt.underline != FALSE,
2851 "underline-set", !oldfmt.cs.underline,
2852 "italic", oldfmt.italic != FALSE,
2853 "italic-set", !oldfmt.cs.italic,
2854 "strikethrough", oldfmt.strikethrough != FALSE,
2855 "strikethrough-set", !oldfmt.cs.strikethrough,
2856 "color", &oldfmt.color,
2857 "color-set", !oldfmt.cs.color,
2858 "size", wp_font_size[oldfmt.font_size],
2859 "size-set", !oldfmt.cs.font_size,
2860 "position", old_position,
2861 "position-set", !oldfmt.cs.text_position,
2862 "family", wp_get_font_name (oldfmt.font),
2863 "family-set", !oldfmt.cs.font,
2866 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2867 GTK_WINDOW (dialog), GTK_WINDOW (window));
2868 gtk_widget_show_all (dialog);
2869 priv->font_dialog = dialog;
2870 response = gtk_dialog_run (GTK_DIALOG (dialog));
2871 priv->font_dialog = NULL;
2872 if (response == GTK_RESPONSE_OK) {
2874 g_object_get( dialog,
2876 "bold-set", &bold_set,
2877 "underline", &underline,
2878 "underline-set", &underline_set,
2880 "italic-set", &italic_set,
2881 "strikethrough", &strikethrough,
2882 "strikethrough-set", &strikethrough_set,
2884 "color-set", &color_set,
2886 "size-set", &font_size_set,
2887 "family", &font_name,
2888 "family-set", &font_set,
2889 "position", &position,
2890 "position-set", &position_set,
2895 if (response == GTK_RESPONSE_OK) {
2896 memset(&fmt, 0, sizeof(fmt));
2902 fmt.italic = italic;
2903 fmt.cs.italic = TRUE;
2905 if (underline_set) {
2906 fmt.underline = underline;
2907 fmt.cs.underline = TRUE;
2909 if (strikethrough_set) {
2910 fmt.strikethrough = strikethrough;
2911 fmt.cs.strikethrough = TRUE;
2916 ? TEXT_POSITION_NORMAL
2917 : ( ( position == 1 )
2918 ? TEXT_POSITION_SUPERSCRIPT
2919 : TEXT_POSITION_SUBSCRIPT );
2920 fmt.cs.text_position = TRUE;
2921 fmt.font_size = oldfmt.font_size;
2925 fmt.cs.color = TRUE;
2928 fmt.font = wp_get_font_index(font_name,
2933 if (font_size_set) {
2934 fmt.cs.font_size = TRUE;
2935 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
2937 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2938 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2940 gtk_widget_destroy (dialog);
2942 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2946 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2948 ModestMsgEditWindowPrivate *priv;
2950 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2951 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2953 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2955 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2956 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2960 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
2962 ModestMsgEditWindowPrivate *priv;
2964 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2965 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2967 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
2969 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2970 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2975 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
2977 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2979 priv->can_undo = can_undo;
2983 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
2985 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2987 priv->can_redo = can_redo;
2991 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
2993 ModestMsgEditWindowPrivate *priv;
2994 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2995 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2997 return priv->can_undo;
3001 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3003 ModestMsgEditWindowPrivate *priv;
3004 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3005 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3007 return priv->can_redo;
3012 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3015 GtkTextIter match_start, match_end;
3017 if (image_id == NULL)
3020 gtk_text_buffer_get_start_iter (buffer, &iter);
3022 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3023 GSList *tags = gtk_text_iter_get_tags (&match_start);
3025 for (node = tags; node != NULL; node = g_slist_next (node)) {
3026 GtkTextTag *tag = (GtkTextTag *) node->data;
3027 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3028 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3029 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3031 offset = gtk_text_iter_get_offset (&match_start);
3032 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3033 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3037 gtk_text_iter_forward_char (&iter);
3042 message_is_empty (ModestMsgEditWindow *window)
3044 ModestMsgEditWindowPrivate *priv = NULL;
3046 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3047 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3049 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3050 * so we can ignore markup.
3052 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3055 count = gtk_text_buffer_get_char_count (buf);
3061 msg_body_focus (GtkWidget *focus,
3062 GdkEventFocus *event,
3066 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3067 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3068 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3073 recpt_field_changed (GtkTextBuffer *buffer,
3074 ModestMsgEditWindow *editor)
3076 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3077 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3081 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3083 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3084 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3088 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3091 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3092 GtkTextBuffer *buffer;
3094 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3095 gtk_text_buffer_set_modified (buffer, modified);
3096 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3097 gtk_text_buffer_set_modified (buffer, modified);
3098 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3099 gtk_text_buffer_set_modified (buffer, modified);
3100 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3104 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3106 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3107 const char *account_name;
3108 GtkTextBuffer *buffer;
3110 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3111 if (gtk_text_buffer_get_modified (buffer))
3113 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3114 if (gtk_text_buffer_get_modified (buffer))
3116 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3117 if (gtk_text_buffer_get_modified (buffer))
3119 if (gtk_text_buffer_get_modified (priv->text_buffer))
3121 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3122 if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3133 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3135 ModestMsgEditWindowPrivate *priv = NULL;
3137 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3138 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3140 /* check if there's no recipient added */
3141 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3142 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3143 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3144 /* no recipient contents, then select contacts */
3145 modest_msg_edit_window_open_addressbook (window, NULL);
3149 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3150 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3153 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3154 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3157 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3158 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3162 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3163 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3164 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3171 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3172 ModestMsgEditWindow *window)
3174 modest_msg_edit_window_offer_attach_file (window);
3178 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3180 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3182 return priv->clipboard_text;
3186 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3188 ModestMsgEditWindow *window)
3190 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3191 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3193 if (!GTK_WIDGET_VISIBLE (window))
3196 g_object_ref (window);
3197 text = gtk_clipboard_wait_for_text (selection_clipboard);
3199 if (priv->clipboard_text != NULL) {
3200 g_free (priv->clipboard_text);
3202 priv->clipboard_text = text;
3204 if (GTK_WIDGET_VISIBLE (window)) {
3205 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3207 g_object_unref (window);
3210 static gboolean clipboard_owner_change_idle (gpointer userdata)
3212 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3213 ModestMsgEditWindowPrivate *priv;
3215 gdk_threads_enter ();
3216 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3217 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3219 priv->clipboard_owner_idle = 0;
3220 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3221 gdk_threads_leave ();
3227 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3229 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3230 if (priv->clipboard_owner_idle == 0) {
3231 priv->clipboard_owner_idle = g_idle_add (clipboard_owner_change_idle, window);
3236 subject_field_move_cursor (GtkEntry *entry,
3237 GtkMovementStep step,
3242 if (!GTK_WIDGET_VISIBLE (window))
3245 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3249 update_window_title (ModestMsgEditWindow *window)
3251 ModestMsgEditWindowPrivate *priv = NULL;
3252 const gchar *subject;
3254 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3255 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3256 if (subject == NULL || subject[0] == '\0')
3257 subject = _("mail_va_new_email");
3259 gtk_window_set_title (GTK_WINDOW (window), subject);
3264 subject_field_changed (GtkEditable *editable,
3265 ModestMsgEditWindow *window)
3267 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3268 update_window_title (window);
3269 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3270 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3271 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3275 subject_field_insert_text (GtkEditable *editable,
3277 gint new_text_length,
3279 ModestMsgEditWindow *window)
3281 GString *result = g_string_new ("");
3283 gint result_len = 0;
3284 const gchar *entry_text = NULL;
3287 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3288 old_length = g_utf8_strlen (entry_text, -1);
3290 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3291 gunichar c = g_utf8_get_char_validated (current, 8);
3292 /* Invalid unichar, stop */
3298 result = g_string_append_unichar (result, c);
3302 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3303 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3306 /* Prevent endless recursion */
3307 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3308 g_signal_emit_by_name (editable, "insert-text",
3309 (gpointer) result->str, (gpointer) result->len,
3310 (gpointer) position, (gpointer) window);
3311 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3315 if (result_len + old_length > 1000) {
3316 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3317 _CS("ckdg_ib_maximum_characters_reached"));
3319 g_string_free (result, TRUE);
3323 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3326 ModestMsgEditWindowPrivate *priv = NULL;
3328 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3329 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3331 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3334 gtk_widget_show_all (priv->find_toolbar);
3335 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3337 gtk_widget_hide_all (priv->find_toolbar);
3338 gtk_widget_grab_focus (priv->msg_body);
3343 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3345 GtkTextIter *match_start,
3346 GtkTextIter *match_end)
3348 GtkTextIter end_iter;
3349 gchar *str_casefold;
3352 gchar *range_casefold;
3355 gboolean result = FALSE;
3362 gtk_text_iter_forward_to_end (&end_iter);
3364 str_casefold = g_utf8_casefold (str, -1);
3365 str_chars_n = strlen (str);
3367 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3368 range_casefold = g_utf8_casefold (range_text, -1);
3369 range_chars_n = strlen (range_casefold);
3371 if (range_chars_n < str_chars_n) {
3372 g_free (str_casefold);
3373 g_free (range_text);
3374 g_free (range_casefold);
3378 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3379 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3380 if (!g_utf8_collate (range_subtext, str_casefold)) {
3381 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3383 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3384 match_start, match_end, NULL);
3385 g_free (found_text);
3387 g_free (range_subtext);
3391 g_free (str_casefold);
3392 g_free (range_text);
3393 g_free (range_casefold);
3400 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3401 ModestMsgEditWindow *window)
3403 gchar *current_search = NULL;
3404 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3406 GtkTextIter selection_start, selection_end;
3407 GtkTextIter match_start, match_end;
3408 gboolean continue_search = FALSE;
3410 if (message_is_empty (window)) {
3411 g_free (priv->last_search);
3412 priv->last_search = NULL;
3413 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3417 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3418 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3419 g_free (current_search);
3420 g_free (priv->last_search);
3421 priv->last_search = NULL;
3422 /* Information banner about empty search */
3423 hildon_banner_show_information (NULL, NULL, _CS("ecdg_ib_find_rep_enter_text"));
3427 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3428 continue_search = TRUE;
3430 g_free (priv->last_search);
3431 priv->last_search = g_strdup (current_search);
3434 if (continue_search) {
3435 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3436 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3437 &match_start, &match_end);
3439 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_search_complete"));
3441 GtkTextIter buffer_start;
3442 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3443 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3444 &match_start, &match_end);
3446 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_no_matches"));
3449 /* Mark as selected the string found in search */
3451 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3452 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3453 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3455 g_free (priv->last_search);
3456 priv->last_search = NULL;
3458 g_free (current_search);
3462 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3464 ModestMsgEditWindowPrivate *priv;
3466 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3471 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3474 ModestMsgEditWindowPrivate *priv;
3476 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3481 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3482 ModestMsgEditWindow *window)
3484 modest_msg_edit_window_toggle_find_toolbar (window, FALSE);
3488 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3491 ModestMsgEditWindowPrivate *priv;
3492 TnyHeader *header = NULL;
3494 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3495 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3497 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3498 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3500 if (priv->draft_msg != NULL) {
3501 g_object_unref (priv->draft_msg);
3504 if (draft != NULL) {
3505 g_object_ref (draft);
3506 header = tny_msg_get_header (draft);
3507 if (priv->msg_uid) {
3508 g_free (priv->msg_uid);
3509 priv->msg_uid = NULL;
3511 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3512 if (GTK_WIDGET_REALIZED (window)) {
3513 if (!modest_window_mgr_register_window (mgr, MODEST_WINDOW (window), NULL)) {
3514 gtk_widget_destroy (GTK_WIDGET (window));
3520 priv->draft_msg = draft;
3524 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3525 GtkTextIter *start, GtkTextIter *end,
3528 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3529 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3532 if (tag == NULL) return;
3533 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3534 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3535 replace_with_images (window, priv->images);
3540 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3543 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3545 g_return_if_fail (TNY_IS_MIME_PART (part));
3546 tny_list_prepend (priv->attachments, (GObject *) part);
3547 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3548 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3549 gtk_widget_show_all (priv->attachments_caption);
3550 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3554 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3556 ModestMsgEditWindowPrivate *priv;
3558 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3559 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3561 return priv->msg_uid;
3565 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3566 ModestMsgEditWindowWidgetType widget_type)
3568 ModestMsgEditWindowPrivate *priv;
3570 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3571 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3573 switch (widget_type) {
3574 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3575 return priv->msg_body;
3577 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3578 return priv->to_field;
3580 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3581 return priv->cc_field;
3583 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3584 return priv->bcc_field;
3586 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3587 return priv->subject_field;
3589 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3590 return priv->attachments_view;
3598 remove_tags (WPTextBuffer *buffer)
3600 GtkTextIter start, end;
3602 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3603 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3605 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3609 on_account_removed (TnyAccountStore *account_store,
3610 TnyAccount *account,
3613 /* Do nothing if it's a store account, because we use the
3614 transport to send the messages */
3615 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3616 const gchar *parent_acc = NULL;
3617 const gchar *our_acc = NULL;
3619 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3620 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3621 /* Close this window if I'm showing a message of the removed account */
3622 if (strcmp (parent_acc, our_acc) == 0)
3623 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3627 typedef struct _MessageSettingsHelper {
3628 ModestMsgEditWindow *window;
3629 GSList *priority_group;
3630 GSList *format_group;
3631 GtkToggleButton *current_priority;
3632 GtkToggleButton *current_format;
3633 } MessageSettingsHelper;
3636 on_priority_toggle (GtkToggleButton *button,
3637 MessageSettingsHelper *helper)
3640 ModestMsgEditWindowPrivate *priv;
3642 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3643 if (gtk_toggle_button_get_active (button)) {
3645 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3646 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3647 if ((node_button != button) &&
3648 gtk_toggle_button_get_active (node_button)) {
3649 gtk_toggle_button_set_active (node_button, FALSE);
3652 helper->current_priority = button;
3654 gboolean found = FALSE;
3655 /* If no one is active, activate it again */
3656 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3657 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3658 if (gtk_toggle_button_get_active (node_button)) {
3664 gtk_toggle_button_set_active (button, TRUE);
3670 on_format_toggle (GtkToggleButton *button,
3671 MessageSettingsHelper *helper)
3674 ModestMsgEditWindowPrivate *priv;
3676 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3677 if (gtk_toggle_button_get_active (button)) {
3679 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
3680 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3681 if ((node_button != button) &&
3682 gtk_toggle_button_get_active (node_button)) {
3683 gtk_toggle_button_set_active (node_button, FALSE);
3686 helper->current_format = button;
3688 gboolean found = FALSE;
3689 /* If no one is active, activate it again */
3690 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
3691 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3692 if (gtk_toggle_button_get_active (node_button)) {
3698 gtk_toggle_button_set_active (button, TRUE);
3705 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
3709 GtkWidget *priority_hbox;
3710 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
3711 GtkWidget *captioned;
3712 GtkSizeGroup *title_sizegroup, *value_sizegroup;
3713 GtkWidget *format_hbox;
3714 GtkWidget *html_toggle, *text_toggle;
3715 ModestMsgEditWindowPrivate *priv;
3716 MessageSettingsHelper helper = {0,};
3718 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3719 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3720 helper.window = window;
3721 helper.priority_group = NULL;
3723 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3724 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3726 dialog = gtk_dialog_new_with_buttons (_("mcen_me_message_settings"), NULL,
3727 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
3728 _HL("wdgt_bd_done"), GTK_RESPONSE_ACCEPT, NULL);
3729 vbox = gtk_vbox_new (FALSE, 0);
3730 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), vbox);
3731 gtk_widget_show (vbox);
3733 /* Priority toggles */
3734 priority_hbox = gtk_hbox_new (TRUE, 0);
3735 high_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3736 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
3737 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
3738 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
3739 medium_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3740 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
3741 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
3742 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
3743 low_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3744 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
3745 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
3746 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
3747 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, TRUE, TRUE, 0);
3748 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, TRUE, TRUE, 0);
3749 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, TRUE, TRUE, 0);
3750 gtk_widget_show_all (priority_hbox);
3751 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
3752 _("mcen_me_editor_message_priority"), FALSE, priority_hbox);
3753 gtk_widget_show (captioned);
3754 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
3756 /* format toggles */
3757 format_hbox = gtk_hbox_new (TRUE, 0);
3758 html_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3759 gtk_button_set_label (GTK_BUTTON (html_toggle), _("mcen_me_editor_formatted_text"));
3760 helper.format_group = g_slist_prepend (helper.format_group, html_toggle);
3761 g_object_set_data (G_OBJECT (html_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_HTML));
3762 g_object_set_data (G_OBJECT (html_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_FORMATTED_TEXT));
3763 text_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3764 gtk_button_set_label (GTK_BUTTON (text_toggle), _("mcen_me_editor_plain_text"));
3765 helper.format_group = g_slist_prepend (helper.format_group, text_toggle);
3766 g_object_set_data (G_OBJECT (text_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_TEXT));
3767 g_object_set_data (G_OBJECT (text_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_PLAIN_TEXT));
3768 gtk_box_pack_start (GTK_BOX (format_hbox), html_toggle, TRUE, TRUE, 0);
3769 gtk_box_pack_start (GTK_BOX (format_hbox), text_toggle, TRUE, TRUE, 0);
3770 gtk_widget_show_all (format_hbox);
3771 gtk_widget_show (format_hbox);
3772 gtk_box_pack_start (GTK_BOX (vbox), format_hbox, FALSE, FALSE, 0);
3775 g_object_unref (title_sizegroup);
3776 g_object_unref (value_sizegroup);
3778 /* Set current values */
3779 switch (priv->priority_flags) {
3780 case TNY_HEADER_FLAG_HIGH_PRIORITY:
3781 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (high_toggle), TRUE);
3783 case TNY_HEADER_FLAG_LOW_PRIORITY:
3784 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (low_toggle), TRUE);
3787 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (medium_toggle), TRUE);
3791 switch (modest_msg_edit_window_get_format (window)) {
3792 case MODEST_MSG_EDIT_FORMAT_TEXT:
3793 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_toggle), TRUE);
3795 case MODEST_MSG_EDIT_FORMAT_HTML:
3797 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (html_toggle), TRUE);
3801 /* Signal connects */
3802 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3803 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3804 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3805 g_signal_connect (G_OBJECT (html_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
3806 g_signal_connect (G_OBJECT (text_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
3808 /* Save settings if the user clicked on done */
3809 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
3810 TnyHeaderFlags flags;
3811 ModestMsgEditFormat old_format, new_format;
3813 /* Set priority flags */
3814 flags = (TnyHeaderFlags) g_object_get_data (G_OBJECT (helper.current_priority), "priority");
3815 if (priv->priority_flags != flags)
3816 modest_msg_edit_window_set_priority_flags (window, flags);
3818 /* Set edit format */
3819 old_format = modest_msg_edit_window_get_format (window);
3820 new_format = (ModestMsgEditFormat) g_object_get_data (G_OBJECT (helper.current_format), "format");
3821 if (old_format != new_format) {
3822 gint file_format = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (helper.current_format), "file-format"));
3823 modest_msg_edit_window_set_file_format (window, file_format);
3827 gtk_widget_destroy (dialog);
3828 g_slist_free (helper.priority_group);
3832 on_message_settings (GtkAction *action,
3833 ModestMsgEditWindow *window)
3835 modest_msg_edit_window_show_msg_settings_dialog (window);
3839 on_cc_button_toggled (HildonCheckButton *button,
3840 ModestMsgEditWindow *window)
3842 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
3844 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
3845 hildon_check_button_get_active (button));
3849 on_bcc_button_toggled (HildonCheckButton *button,
3850 ModestMsgEditWindow *window)
3852 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
3854 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
3855 hildon_check_button_get_active (button));
3859 setup_menu (ModestMsgEditWindow *self)
3861 ModestMsgEditWindowPrivate *priv = NULL;
3863 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
3865 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3867 /* Settings menu buttons */
3868 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_checknames"), NULL,
3869 APP_MENU_CALLBACK (modest_ui_actions_on_check_names),
3871 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_undo"), "<Ctrl>z",
3872 APP_MENU_CALLBACK (modest_ui_actions_on_undo),
3873 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_undo));
3875 priv->cc_button = hildon_check_button_new (0);
3876 gtk_button_set_label (GTK_BUTTON (priv->cc_button), _("mcen_me_editor_showcc"));
3877 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button),
3879 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->cc_button),
3881 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
3882 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
3883 priv->bcc_button = hildon_check_button_new (0);
3884 gtk_button_set_label (GTK_BUTTON (priv->bcc_button), _("mcen_me_editor_showbcc"));
3885 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button),
3887 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->bcc_button),
3889 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
3890 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
3892 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_attach_inlineimage"), NULL,
3893 APP_MENU_CALLBACK (modest_ui_actions_on_insert_image),
3894 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_set_style));
3895 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_remove_attachments"), NULL,
3896 APP_MENU_CALLBACK (modest_ui_actions_on_remove_attachments),
3897 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
3898 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_message_settings"), NULL,
3899 APP_MENU_CALLBACK (on_message_settings),
3901 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_viewer_find"), "<Ctrl>f",
3902 APP_MENU_CALLBACK (modest_ui_actions_on_toggle_find_in_page),