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"), 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"), 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"), 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"), subject_box);
809 priv->attachments_caption = modest_maemo_utils_create_captioned_with_size_type (title_size_group, value_size_group,
810 _("mail_va_attachment"),
811 priv->attachments_view,
812 HILDON_SIZE_AUTO_WIDTH |
813 HILDON_SIZE_AUTO_HEIGHT);
814 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), value_size_group); */
815 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), value_size_group); */
816 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), value_size_group); */
817 g_object_unref (title_size_group);
818 g_object_unref (value_size_group);
820 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->from_field, FALSE, FALSE, 0);
821 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
822 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
823 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
824 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
825 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
826 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
828 init_wp_text_view_style ();
830 priv->msg_body = wp_text_view_new ();
833 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
834 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
835 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
836 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
837 #if (GTK_MINOR_VERSION >= 10)
838 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
839 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
841 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
842 deserialize_type, TRUE);
844 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
846 priv->find_toolbar = hildon_find_toolbar_new (NULL);
847 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
849 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
851 priv->pannable = hildon_pannable_area_new ();
853 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
855 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
856 priv->frame = gtk_frame_new (NULL);
857 gtk_box_pack_start (GTK_BOX(main_vbox), priv->frame, TRUE, TRUE, 0);
859 hildon_pannable_area_add_with_viewport (HILDON_PANNABLE_AREA (priv->pannable), main_vbox);
860 gtk_widget_show_all (GTK_WIDGET(priv->pannable));
862 window_box = gtk_vbox_new (FALSE, 0);
863 gtk_container_add (GTK_CONTAINER(obj), window_box);
865 gtk_box_pack_start (GTK_BOX (window_box), priv->pannable, TRUE, TRUE, 0);
867 gtk_container_add (GTK_CONTAINER (priv->frame), priv->msg_body);
869 /* Set window icon */
870 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
872 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
873 g_object_unref (window_icon);
878 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
880 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
882 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
883 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
884 priv->clipboard_change_handler_id))
885 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
886 priv->clipboard_change_handler_id);
887 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
888 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
889 priv->default_clipboard_change_handler_id))
890 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
891 priv->default_clipboard_change_handler_id);
893 if (priv->account_removed_handler_id &&
894 g_signal_handler_is_connected (modest_runtime_get_account_store (),
895 priv->account_removed_handler_id))
896 g_signal_handler_disconnect(modest_runtime_get_account_store (),
897 priv->account_removed_handler_id);
901 modest_msg_edit_window_finalize (GObject *obj)
903 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
905 /* Sanity check: shouldn't be needed, the window mgr should
906 call this function before */
907 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
909 if (priv->font_dialog != NULL) {
910 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
913 if (priv->clipboard_text != NULL) {
914 g_free (priv->clipboard_text);
915 priv->clipboard_text = NULL;
918 if (priv->draft_msg != NULL) {
919 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
920 if (TNY_IS_HEADER (header)) {
921 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
922 modest_window_mgr_unregister_header (mgr, header);
924 g_object_unref (priv->draft_msg);
925 priv->draft_msg = NULL;
927 if (priv->outbox_msg != NULL) {
928 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
929 if (TNY_IS_HEADER (header)) {
930 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
931 modest_window_mgr_unregister_header (mgr, header);
933 g_object_unref (priv->outbox_msg);
934 priv->outbox_msg = NULL;
936 if (priv->correct_scroll_idle > 0) {
937 g_source_remove (priv->correct_scroll_idle);
938 priv->correct_scroll_idle = 0;
940 if (priv->scroll_drag_timeout_id > 0) {
941 g_source_remove (priv->scroll_drag_timeout_id);
942 priv->scroll_drag_timeout_id = 0;
944 if (priv->clipboard_owner_idle > 0) {
945 g_source_remove (priv->clipboard_owner_idle);
946 priv->clipboard_owner_idle = 0;
948 if (priv->original_account_name)
949 g_free (priv->original_account_name);
950 g_free (priv->msg_uid);
951 g_free (priv->last_search);
952 g_slist_free (priv->font_items_group);
953 g_slist_free (priv->size_items_group);
954 g_object_unref (priv->attachments);
955 g_object_unref (priv->images);
957 /* This had to stay alive for as long as the picker that used it: */
958 modest_pair_list_free (priv->from_field_protos);
960 G_OBJECT_CLASS(parent_class)->finalize (obj);
964 pixbuf_from_stream (TnyStream *stream, const gchar *mime_type, guint64 *stream_size)
966 GdkPixbufLoader *loader;
972 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
974 if (loader == NULL) {
980 tny_stream_reset (TNY_STREAM (stream));
981 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
982 GError *error = NULL;
983 unsigned char read_buffer[128];
985 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
987 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
989 g_error_free (error);
994 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
996 g_object_ref (pixbuf);
997 gdk_pixbuf_loader_close (loader, NULL);
998 g_object_unref (loader);
1003 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1004 GdkPixbuf *new_pixbuf;
1006 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1007 gdk_pixbuf_get_width (pixbuf);
1008 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1009 g_object_unref (pixbuf);
1010 pixbuf = new_pixbuf;
1014 *stream_size = size;
1020 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1022 ModestMsgEditWindowPrivate *priv;
1025 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1027 for (iter = tny_list_create_iterator (attachments);
1028 !tny_iterator_is_done (iter);
1029 tny_iterator_next (iter)) {
1030 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1031 const gchar *cid = tny_mime_part_get_content_id (part);
1032 const gchar *mime_type = tny_mime_part_get_content_type (part);
1033 if ((cid != NULL)&&(mime_type != NULL)) {
1034 guint64 stream_size;
1035 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1036 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
1039 g_object_unref (stream);
1041 if (pixbuf != NULL) {
1042 priv->images_count ++;
1043 priv->images_size += stream_size;
1044 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1045 g_object_unref (pixbuf);
1048 g_object_unref (part);
1050 g_object_unref (iter);
1054 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1056 TnyMimePart *parent = NULL;
1057 const gchar *content_type = NULL;
1058 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1060 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1062 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1063 parent = g_object_ref (msg);
1064 } else if (content_type && !g_strcasecmp (content_type, "multipart/mixed")) {
1065 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1068 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1069 iter = tny_list_create_iterator (parts);
1070 while (!tny_iterator_is_done (iter)) {
1072 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1073 content_type = tny_mime_part_get_content_type (part);
1074 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1078 g_object_unref (part);
1080 tny_iterator_next (iter);
1082 g_object_unref (iter);
1083 g_object_unref (parts);
1086 if (parent != NULL) {
1087 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1090 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1091 iter = tny_list_create_iterator (parts);
1092 while (!tny_iterator_is_done (iter)) {
1094 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1095 content_type = tny_mime_part_get_content_type (part);
1096 if (content_type && g_str_has_prefix (content_type, "image/")) {
1097 tny_list_prepend (priv->images, (GObject *) part);
1099 g_object_unref (part);
1100 tny_iterator_next (iter);
1102 g_object_unref (iter);
1103 g_object_unref (parts);
1104 g_object_unref (parent);
1109 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1112 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1114 for (iter = tny_list_create_iterator (attachments) ;
1115 !tny_iterator_is_done (iter);
1116 tny_iterator_next (iter)) {
1117 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1118 const gchar *cid = tny_mime_part_get_content_id (part);
1120 char *invalid = NULL;
1121 gint int_cid = strtol (cid, &invalid, 10);
1122 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1123 priv->next_cid = int_cid + 1;
1126 g_object_unref (part);
1128 g_object_unref (iter);
1132 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1135 gchar *to, *cc, *bcc, *subject;
1137 ModestMsgEditWindowPrivate *priv;
1138 ModestWindowPrivate *parent_priv;
1140 TnyHeaderFlags priority_flags;
1141 TnyFolder *msg_folder;
1142 gboolean is_html = FALSE;
1143 gboolean field_view_set;
1145 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1146 g_return_if_fail (TNY_IS_MSG (msg));
1148 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1149 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1151 header = tny_msg_get_header (msg);
1152 to = tny_header_dup_to (header);
1153 cc = tny_header_dup_cc (header);
1154 bcc = tny_header_dup_bcc (header);
1155 subject = tny_header_dup_subject (header);
1156 priority_flags = tny_header_get_priority (header);
1159 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
1161 field_view_set = TRUE;
1163 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
1164 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1165 gtk_widget_show (priv->cc_caption);
1166 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1167 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1168 gtk_widget_hide (priv->cc_caption);
1169 field_view_set = FALSE;
1171 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button), field_view_set);
1173 field_view_set = TRUE;
1175 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
1176 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1177 gtk_widget_show (priv->bcc_caption);
1178 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1179 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1180 gtk_widget_hide (priv->bcc_caption);
1181 field_view_set = FALSE;
1183 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button), field_view_set);
1187 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1188 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1191 update_window_title (self);
1193 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1194 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1196 if ((body == NULL)||(body[0] == '\0')) {
1198 body = modest_text_utils_convert_to_html ("");
1201 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1202 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1205 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1208 /* Add attachments to the view */
1209 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1210 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1211 if (tny_list_get_length (priv->attachments) == 0) {
1212 gtk_widget_hide (priv->attachments_caption);
1214 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1215 gtk_widget_show_all (priv->attachments_caption);
1217 get_related_images (self, msg);
1218 update_next_cid (self, priv->attachments);
1219 update_next_cid (self, priv->images);
1220 replace_with_images (self, priv->images);
1222 if (preserve_is_rich && !is_html) {
1223 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1224 /* Get the default format required from configuration */
1225 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1226 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1229 /* Set the default focus depending on having already a To: field or not */
1230 if ((!to)||(*to == '\0')) {
1231 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1233 gtk_widget_grab_focus (priv->msg_body);
1236 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1238 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1239 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1241 modest_msg_edit_window_set_modified (self, FALSE);
1243 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1244 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1245 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1246 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1248 if (priv->msg_uid) {
1249 g_free (priv->msg_uid);
1250 priv->msg_uid = NULL;
1253 /* we should set a reference to the incoming message if it is a draft */
1254 msg_folder = tny_msg_get_folder (msg);
1256 if (modest_tny_folder_is_local_folder (msg_folder)) {
1257 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1258 if (type == TNY_FOLDER_TYPE_INVALID)
1259 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1261 if (type == TNY_FOLDER_TYPE_DRAFTS)
1262 priv->draft_msg = g_object_ref(msg);
1263 if (type == TNY_FOLDER_TYPE_OUTBOX)
1264 priv->outbox_msg = g_object_ref(msg);
1265 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1267 g_object_unref (msg_folder);
1277 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
1280 GList *item_children, *node;
1281 GtkWidget *bin_child;
1283 bin_child = gtk_bin_get_child (GTK_BIN(item));
1285 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
1287 for (node = item_children; node != NULL; node = g_list_next (node)) {
1288 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
1289 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
1292 g_list_free (item_children);
1296 menu_tool_button_dont_expand (GtkMenuToolButton *item)
1299 GList *item_children, *node;
1301 box = gtk_bin_get_child (GTK_BIN (item));
1302 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
1303 item_children = gtk_container_get_children (GTK_CONTAINER (box));
1305 for (node = item_children; node != NULL; node = g_list_next (node)) {
1306 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
1307 if (GTK_IS_TOGGLE_BUTTON (node->data))
1308 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
1309 else if (GTK_IS_BUTTON (node->data))
1310 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
1312 g_list_free (item_children);
1317 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1319 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1320 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1321 GtkWidget *placeholder;
1322 GtkWidget *tool_item;
1327 GtkWidget *sizes_menu;
1328 GtkWidget *fonts_menu;
1329 GSList *radio_group = NULL;
1330 GSList *node = NULL;
1334 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1335 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1337 /* Font color placeholder */
1338 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1339 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1342 priv->font_color_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1343 priv->font_color_button = hildon_color_button_new ();
1344 GTK_WIDGET_UNSET_FLAGS (priv->font_color_toolitem, GTK_CAN_FOCUS);
1345 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1346 gtk_container_add (GTK_CONTAINER (priv->font_color_toolitem), priv->font_color_button);
1347 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1348 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1349 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->font_color_toolitem), insert_index);
1350 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1352 G_CALLBACK (modest_msg_edit_window_color_button_change),
1355 /* Font size and face placeholder */
1356 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1357 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1359 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1360 priv->size_tool_button_label = gtk_label_new (NULL);
1361 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1362 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1363 size_text,"</span>", NULL);
1364 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1366 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
1367 sizes_menu = gtk_menu_new ();
1368 priv->size_items_group = NULL;
1370 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1371 GtkWidget *size_menu_item;
1373 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1374 size_menu_item = gtk_radio_menu_item_new_with_label (radio_group, size_text);
1375 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (size_menu_item));
1376 gtk_menu_shell_append (GTK_MENU_SHELL (sizes_menu), size_menu_item);
1377 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (size_menu_item), (wp_font_size[size_index] == 12));
1378 gtk_widget_show (size_menu_item);
1380 priv->size_items_group = g_slist_prepend (priv->size_items_group, size_menu_item);
1384 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1385 GtkWidget *item = (GtkWidget *) node->data;
1386 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_size_change),
1390 priv->size_items_group = g_slist_reverse (priv->size_items_group);
1391 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), sizes_menu);
1392 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1393 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1394 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1395 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1396 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1397 priv->font_size_toolitem = tool_item;
1400 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1401 priv->font_tool_button_label = gtk_label_new (NULL);
1402 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1403 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1405 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
1406 fonts_menu = gtk_menu_new ();
1407 priv->font_items_group = NULL;
1409 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1410 GtkWidget *font_menu_item;
1411 GtkWidget *child_label;
1413 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
1414 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
1415 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
1416 wp_get_font_name (font_index), "</span>", NULL);
1417 gtk_label_set_markup (GTK_LABEL (child_label), markup);
1420 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
1421 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
1422 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
1423 gtk_widget_show (font_menu_item);
1425 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
1428 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1429 GtkWidget *item = (GtkWidget *) node->data;
1430 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
1433 priv->font_items_group = g_slist_reverse (priv->font_items_group);
1434 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
1435 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1436 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1437 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1438 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1439 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1440 priv->font_face_toolitem = tool_item;
1442 /* Set expand and homogeneous for remaining items */
1443 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
1444 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1445 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1446 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1447 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1448 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1449 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1450 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1451 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1453 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1454 will not show the tool items added to the placeholders) */
1455 gtk_widget_show_all (parent_priv->toolbar);
1457 /* Set the no show all *after* showing all items. We do not
1458 want the toolbar to be shown with a show all because it
1459 could go agains the gconf setting regarding showing or not
1460 the toolbar of the editor window */
1461 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1467 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, gboolean preserve_is_rich)
1470 ModestWindowPrivate *parent_priv;
1471 ModestMsgEditWindowPrivate *priv;
1472 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1473 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1474 ModestWindowMgr *mgr = NULL;
1476 g_return_val_if_fail (msg, NULL);
1477 g_return_val_if_fail (account_name, NULL);
1479 mgr = modest_runtime_get_window_mgr ();
1481 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1483 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1484 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1486 /* Menubar. Update the state of some toggles */
1487 priv->from_field_protos = get_transports ();
1488 modest_selector_picker_set_pair_list (MODEST_SELECTOR_PICKER (priv->from_field), priv->from_field_protos);
1489 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1490 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1492 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1493 hildon_touch_selector_get_current_text
1494 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1495 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1496 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1499 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1501 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1503 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1505 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1507 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1508 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1509 /* Add common dimming rules */
1510 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1511 modest_msg_edit_window_toolbar_dimming_entries,
1512 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1513 MODEST_WINDOW (obj));
1514 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_toolitem,
1515 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1516 MODEST_WINDOW (obj));
1517 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1518 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1519 MODEST_WINDOW (obj));
1520 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1521 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1522 MODEST_WINDOW (obj));
1523 /* Insert dimming rules group for this window */
1524 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1525 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1527 /* Setup app menu */
1528 setup_menu (MODEST_MSG_EDIT_WINDOW (obj));
1530 /* Checks the dimming rules */
1531 g_object_unref (toolbar_rules_group);
1532 g_object_unref (clipboard_rules_group);
1533 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1535 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1537 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1538 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1539 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1540 priv->update_caption_visibility = TRUE;
1542 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1544 /* Track account-removed signal, this window should be closed
1545 in the case we're creating a mail associated to the account
1547 priv->account_removed_handler_id =
1548 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1550 G_CALLBACK(on_account_removed),
1553 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1555 return (ModestWindow*) obj;
1559 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1561 GString **string_buffer = (GString **) user_data;
1563 *string_buffer = g_string_append (*string_buffer, buffer);
1569 * @result: A new string which should be freed with g_free().
1572 get_formatted_data (ModestMsgEditWindow *edit_window)
1574 ModestMsgEditWindowPrivate *priv;
1575 GString *string_buffer = g_string_new ("");
1577 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1579 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1581 modest_text_utils_hyperlinkify (string_buffer);
1583 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1585 return g_string_free (string_buffer, FALSE);
1590 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1593 const gchar *account_name;
1594 ModestMsgEditWindowPrivate *priv;
1595 TnyIterator *att_iter;
1597 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1599 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1601 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1602 g_return_val_if_fail (account_name, NULL);
1605 /* don't free these (except from) */
1606 data = g_slice_new0 (MsgData);
1607 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1609 data->account_name = g_strdup (account_name);
1610 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1611 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1612 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1613 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1614 if (priv->draft_msg) {
1615 data->draft_msg = g_object_ref (priv->draft_msg);
1616 } else if (priv->outbox_msg) {
1617 data->draft_msg = g_object_ref (priv->outbox_msg);
1619 data->draft_msg = NULL;
1622 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1624 gtk_text_buffer_get_bounds (buf, &b, &e);
1625 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1627 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1628 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1630 data->html_body = NULL;
1632 /* deep-copy the data */
1633 att_iter = tny_list_create_iterator (priv->attachments);
1634 data->attachments = NULL;
1635 while (!tny_iterator_is_done (att_iter)) {
1636 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1637 if (!(TNY_IS_MIME_PART(part))) {
1638 g_warning ("strange data in attachment list");
1639 g_object_unref (part);
1640 tny_iterator_next (att_iter);
1643 data->attachments = g_list_append (data->attachments,
1645 tny_iterator_next (att_iter);
1647 g_object_unref (att_iter);
1649 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1650 att_iter = tny_list_create_iterator (priv->images);
1651 data->images = NULL;
1652 while (!tny_iterator_is_done (att_iter)) {
1653 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1655 if (!(TNY_IS_MIME_PART(part))) {
1656 g_warning ("strange data in attachment list");
1657 g_object_unref (part);
1658 tny_iterator_next (att_iter);
1661 cid = tny_mime_part_get_content_id (part);
1663 gchar *image_tag_id;
1664 GtkTextTag *image_tag;
1666 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1667 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1668 g_free (image_tag_id);
1670 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1672 ((gtk_text_iter_has_tag (&iter, image_tag))||
1673 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1674 data->images = g_list_append (data->images,
1675 g_object_ref (part));
1677 g_object_unref (part);
1678 tny_iterator_next (att_iter);
1680 g_object_unref (att_iter);
1682 data->priority_flags = priv->priority_flags;
1689 unref_gobject (GObject *obj, gpointer data)
1691 if (!G_IS_OBJECT(obj))
1693 g_object_unref (obj);
1697 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1700 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1708 g_free (data->from);
1709 g_free (data->subject);
1710 g_free (data->plain_body);
1711 g_free (data->html_body);
1712 g_free (data->account_name);
1714 if (data->draft_msg != NULL) {
1715 g_object_unref (data->draft_msg);
1716 data->draft_msg = NULL;
1719 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1720 g_list_free (data->attachments);
1721 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1722 g_list_free (data->images);
1724 g_slice_free (MsgData, data);
1728 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1730 guint64 *parts_size)
1732 ModestMsgEditWindowPrivate *priv;
1734 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1736 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1738 /* TODO: add images */
1739 *parts_size += priv->images_size;
1740 *parts_count += priv->images_count;
1745 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1748 ModestMsgEditWindowPrivate *priv = NULL;
1749 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1751 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1753 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1755 return MODEST_MSG_EDIT_FORMAT_HTML;
1757 return MODEST_MSG_EDIT_FORMAT_TEXT;
1761 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1762 ModestMsgEditFormat format)
1764 ModestMsgEditWindowPrivate *priv;
1766 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1767 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1770 case MODEST_MSG_EDIT_FORMAT_HTML:
1771 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1773 case MODEST_MSG_EDIT_FORMAT_TEXT:
1774 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1777 g_return_if_reached ();
1781 ModestMsgEditFormatState *
1782 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1784 ModestMsgEditFormatState *format_state = NULL;
1785 ModestMsgEditWindowPrivate *priv;
1786 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1788 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1789 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1791 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1793 format_state = g_new0 (ModestMsgEditFormatState, 1);
1794 format_state->bold = buffer_format->bold&0x1;
1795 format_state->italics = buffer_format->italic&0x1;
1796 format_state->bullet = buffer_format->bullet&0x1;
1797 format_state->color = buffer_format->color;
1798 format_state->font_size = buffer_format->font_size;
1799 format_state->font_family = wp_get_font_name (buffer_format->font);
1800 format_state->justification = buffer_format->justification;
1801 g_free (buffer_format);
1803 return format_state;
1808 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1809 const ModestMsgEditFormatState *format_state)
1811 ModestMsgEditWindowPrivate *priv;
1812 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1813 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1814 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1815 g_return_if_fail (format_state != NULL);
1817 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1818 gtk_widget_grab_focus (priv->msg_body);
1819 buffer_format->bold = (format_state->bold != FALSE);
1820 buffer_format->italic = (format_state->italics != FALSE);
1821 buffer_format->color = format_state->color;
1822 buffer_format->font_size = format_state->font_size;
1823 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1824 buffer_format->justification = format_state->justification;
1825 buffer_format->bullet = format_state->bullet;
1827 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1829 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1830 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1831 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1832 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1833 buffer_format->cs.font = (buffer_format->font != current_format->font);
1834 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1835 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1837 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1838 if (buffer_format->cs.bold) {
1839 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
1840 GINT_TO_POINTER (buffer_format->bold&0x1));
1842 if (buffer_format->cs.italic) {
1843 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
1844 GINT_TO_POINTER (buffer_format->italic&0x1));
1846 if (buffer_format->cs.color) {
1847 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1848 GINT_TO_POINTER (&(buffer_format->color)));
1850 if (buffer_format->cs.font_size) {
1851 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1852 GINT_TO_POINTER (buffer_format->font_size));
1854 if (buffer_format->cs.justification) {
1855 switch (buffer_format->justification) {
1856 case GTK_JUSTIFY_LEFT:
1857 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
1858 GINT_TO_POINTER(TRUE));
1860 case GTK_JUSTIFY_CENTER:
1861 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
1862 GINT_TO_POINTER(TRUE));
1864 case GTK_JUSTIFY_RIGHT:
1865 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
1866 GINT_TO_POINTER(TRUE));
1873 if (buffer_format->cs.font) {
1874 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1875 GINT_TO_POINTER (buffer_format->font));
1877 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1878 if (buffer_format->cs.bullet) {
1879 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
1880 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
1882 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1884 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
1886 g_free (buffer_format);
1887 g_free (current_format);
1889 /* Check dimming rules */
1890 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1891 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1895 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1897 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1899 ModestWindowPrivate *parent_priv;
1900 ModestMsgEditWindowPrivate *priv;
1901 GtkWidget *new_size_menuitem;
1902 GtkWidget *new_font_menuitem;
1904 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1905 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1907 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1908 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu");
1909 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1910 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1912 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatPlainTextMenu");
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);
1917 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1919 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1920 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1922 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1923 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1925 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
1926 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
1929 switch (buffer_format->justification)
1931 case GTK_JUSTIFY_LEFT:
1932 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
1934 case GTK_JUSTIFY_CENTER:
1935 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
1937 case GTK_JUSTIFY_RIGHT:
1938 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
1945 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
1947 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1948 G_CALLBACK (modest_msg_edit_window_color_button_change),
1950 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1951 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1952 G_CALLBACK (modest_msg_edit_window_color_button_change),
1955 new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group,
1956 buffer_format->font_size))->data);
1957 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1961 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1962 markup = g_strconcat ("<span font_family='Sans'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1963 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1965 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1966 G_CALLBACK (modest_msg_edit_window_size_change),
1968 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
1969 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
1970 G_CALLBACK (modest_msg_edit_window_size_change),
1974 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
1975 buffer_format->font))->data);
1976 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
1980 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
1981 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1982 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1984 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
1985 G_CALLBACK (modest_msg_edit_window_font_change),
1987 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
1988 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
1989 G_CALLBACK (modest_msg_edit_window_font_change),
1993 g_free (buffer_format);
1997 #ifdef MODEST_HILDON_VERSION_0
1999 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2002 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2003 ModestMsgEditWindowPrivate *priv;
2004 GtkWidget *dialog = NULL;
2006 GdkColor *new_color = NULL;
2008 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2009 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2011 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2012 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
2013 g_free (buffer_format);
2015 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2016 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2017 if (new_color != NULL) {
2018 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2019 (gpointer) new_color);
2022 gtk_widget_destroy (dialog);
2027 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2030 ModestMsgEditWindowPrivate *priv;
2031 GtkWidget *dialog = NULL;
2033 GdkColor *old_color = NULL;
2034 const GdkColor *new_color = NULL;
2036 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2037 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2039 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2040 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2042 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2043 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2044 if (new_color != NULL)
2045 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2047 gtk_widget_destroy (dialog);
2053 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2056 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2057 ModestMsgEditWindowPrivate *priv;
2058 GtkWidget *dialog = NULL;
2060 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2061 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2063 dialog = hildon_color_chooser_new ();
2064 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2065 g_free (buffer_format);
2067 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2069 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2070 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2073 gtk_widget_destroy (dialog);
2078 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2081 ModestMsgEditWindowPrivate *priv;
2082 GtkWidget *dialog = NULL;
2083 GdkColor *old_color = NULL;
2085 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2086 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2088 dialog = hildon_color_chooser_new ();
2089 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2091 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2093 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2094 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2096 gtk_widget_destroy (dialog);
2099 #endif /*!MODEST_HILDON_VERSION_0*/
2104 create_stream_for_uri (const gchar* uri)
2109 TnyStream *result = NULL;
2111 GnomeVFSHandle *handle = NULL;
2112 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2113 if (test == GNOME_VFS_OK) {
2114 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2115 /* Streams over OBEX (Bluetooth) are not seekable but
2116 * we expect them to be (we might need to read them
2117 * several times). So if this is a Bluetooth URI just
2118 * read the whole file into memory (this is not a fast
2119 * protocol so we can assume that these files are not
2120 * going to be very big) */
2121 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2122 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2123 TnyStream *memstream = tny_camel_mem_stream_new ();
2124 tny_stream_write_to_stream (vfssstream, memstream);
2125 g_object_unref (vfssstream);
2128 result = vfssstream;
2136 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2139 ModestMsgEditWindowPrivate *priv;
2140 GtkWidget *dialog = NULL;
2142 GSList *uris = NULL;
2143 GSList *uri_node = NULL;
2145 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2147 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2148 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2149 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2151 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2153 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2154 GTK_WINDOW (dialog), GTK_WINDOW (window));
2156 response = gtk_dialog_run (GTK_DIALOG (dialog));
2158 case GTK_RESPONSE_OK:
2159 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2164 gtk_widget_destroy (dialog);
2166 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2168 GnomeVFSHandle *handle = NULL;
2169 GnomeVFSResult result;
2170 GtkTextIter position;
2171 GtkTextMark *insert_mark;
2173 uri = (const gchar *) uri_node->data;
2174 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2175 if (result == GNOME_VFS_OK) {
2177 GnomeVFSFileInfo *info;
2178 gchar *filename, *basename, *escaped_filename;
2179 TnyMimePart *mime_part;
2181 const gchar *mime_type = NULL;
2182 GnomeVFSURI *vfs_uri;
2183 guint64 stream_size;
2185 gnome_vfs_close (handle);
2186 vfs_uri = gnome_vfs_uri_new (uri);
2188 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2189 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2190 g_free (escaped_filename);
2191 gnome_vfs_uri_unref (vfs_uri);
2192 info = gnome_vfs_file_info_new ();
2194 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2195 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2197 mime_type = gnome_vfs_file_info_get_mime_type (info);
2199 mime_part = tny_platform_factory_new_mime_part
2200 (modest_runtime_get_platform_factory ());
2202 TnyStream *stream = create_stream_for_uri (uri);
2204 if (stream == NULL) {
2206 modest_platform_information_banner (NULL, NULL, dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2208 g_object_unref (mime_part);
2209 gnome_vfs_file_info_unref (info);
2213 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2215 content_id = g_strdup_printf ("%d", priv->next_cid);
2216 tny_mime_part_set_content_id (mime_part, content_id);
2217 g_free (content_id);
2220 basename = g_path_get_basename (filename);
2221 tny_mime_part_set_filename (mime_part, basename);
2224 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
2226 if (pixbuf != NULL) {
2227 priv->images_size += stream_size;
2228 priv->images_count ++;
2229 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2230 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2231 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
2232 g_object_unref (pixbuf);
2235 tny_list_prepend (priv->images, (GObject *) mime_part);
2236 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2238 g_object_unref (mime_part);
2239 gnome_vfs_file_info_unref (info);
2248 on_attach_file_response (GtkDialog *dialog,
2252 GSList *uris = NULL;
2254 GnomeVFSFileSize total_size, allowed_size;
2255 ModestMsgEditWindow *window;
2256 ModestMsgEditWindowPrivate *priv;
2261 case GTK_RESPONSE_OK:
2262 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2268 window = MODEST_MSG_EDIT_WINDOW (user_data);
2269 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2271 /* allowed size is the maximum size - what's already there */
2272 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2273 &att_num, &att_size);
2274 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2277 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2279 const gchar *uri = (const gchar *) uri_node->data;
2282 modest_msg_edit_window_attach_file_one (window, uri, allowed_size);
2284 if (total_size > allowed_size) {
2285 g_warning ("%s: total size: %u",
2286 __FUNCTION__, (unsigned int)total_size);
2289 allowed_size -= total_size;
2291 g_slist_foreach (uris, (GFunc) g_free, NULL);
2292 g_slist_free (uris);
2294 gtk_widget_destroy (GTK_WIDGET (dialog));
2298 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2300 GtkWidget *dialog = NULL;
2301 ModestMsgEditWindowPrivate *priv;
2303 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2305 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2307 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2310 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window),
2311 GTK_FILE_CHOOSER_ACTION_OPEN);
2312 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2313 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2314 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2315 GTK_WINDOW (dialog), GTK_WINDOW (window));
2317 /* Connect to response & show */
2318 g_signal_connect (dialog, "response",
2319 G_CALLBACK (on_attach_file_response), window);
2320 gtk_widget_show (dialog);
2325 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2327 GnomeVFSFileSize allowed_size)
2330 GnomeVFSHandle *handle = NULL;
2331 ModestMsgEditWindowPrivate *priv;
2332 GnomeVFSResult result;
2333 GnomeVFSFileSize size = 0;
2334 g_return_val_if_fail (window, 0);
2335 g_return_val_if_fail (uri, 0);
2337 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2339 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2340 if (result == GNOME_VFS_OK) {
2341 TnyMimePart *mime_part;
2343 const gchar *mime_type = NULL;
2345 gchar *escaped_filename;
2348 GnomeVFSFileInfo *info;
2349 GnomeVFSURI *vfs_uri;
2351 gnome_vfs_close (handle);
2352 vfs_uri = gnome_vfs_uri_new (uri);
2355 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2356 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2357 g_free (escaped_filename);
2358 gnome_vfs_uri_unref (vfs_uri);
2360 info = gnome_vfs_file_info_new ();
2362 if (gnome_vfs_get_file_info (uri,
2364 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2366 mime_type = gnome_vfs_file_info_get_mime_type (info);
2367 mime_part = tny_platform_factory_new_mime_part
2368 (modest_runtime_get_platform_factory ());
2370 /* try to get the attachment's size; this may fail for weird
2371 * file systems, like obex, upnp... */
2372 if (allowed_size != 0 &&
2373 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2375 if (size > allowed_size) {
2376 modest_platform_information_banner (NULL, NULL,
2377 dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2381 g_warning ("%s: could not get attachment size", __FUNCTION__);
2383 stream = create_stream_for_uri (uri);
2385 if (stream == NULL) {
2387 modest_platform_information_banner (NULL, NULL, dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2389 g_object_unref (mime_part);
2390 gnome_vfs_file_info_unref (info);
2394 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2395 g_object_unref (stream);
2397 content_id = g_strdup_printf ("%d", priv->next_cid);
2398 tny_mime_part_set_content_id (mime_part, content_id);
2399 g_free (content_id);
2402 basename = g_path_get_basename (filename);
2403 tny_mime_part_set_filename (mime_part, basename);
2406 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2407 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2409 info->size == 0, info->size);
2410 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2411 gtk_widget_show_all (priv->attachments_caption);
2412 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2414 g_object_unref (mime_part);
2415 gnome_vfs_file_info_unref (info);
2422 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2425 ModestMsgEditWindowPrivate *priv;
2428 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2429 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2431 if (att_list == NULL) {
2432 att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2434 g_object_ref (att_list);
2437 if (tny_list_get_length (att_list) == 0) {
2438 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2440 gboolean dialog_response;
2441 gchar *message = NULL;
2442 gchar *filename = NULL;
2444 if (tny_list_get_length (att_list) == 1) {
2446 iter = tny_list_create_iterator (att_list);
2447 part = (TnyMimePart *) tny_iterator_get_current (iter);
2448 g_object_unref (iter);
2449 if (TNY_IS_MSG (part)) {
2450 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2452 filename = tny_header_dup_subject (header);
2453 g_object_unref (header);
2455 if (filename == NULL) {
2456 filename = g_strdup (_("mail_va_no_subject"));
2459 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2461 g_object_unref (part);
2463 filename = g_strdup ("");
2465 message = g_strdup_printf (ngettext("emev_nc_delete_attachment",
2466 "emev_nc_delete_attachments",
2467 tny_list_get_length (att_list)), filename);
2470 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
2474 if (dialog_response != GTK_RESPONSE_OK) {
2475 g_object_unref (att_list);
2479 for (iter = tny_list_create_iterator (att_list);
2480 !tny_iterator_is_done (iter);
2481 tny_iterator_next (iter)) {
2482 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2483 const gchar *att_id;
2484 tny_list_remove (priv->attachments, (GObject *) mime_part);
2486 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2488 if (tny_list_get_length (priv->attachments) == 0)
2489 gtk_widget_hide (priv->attachments_caption);
2490 att_id = tny_mime_part_get_content_id (mime_part);
2492 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2494 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2495 g_object_unref (mime_part);
2497 g_object_unref (iter);
2500 g_object_unref (att_list);
2502 /* if the last attachment has been removed, focus the Subject: field */
2503 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2504 gtk_widget_grab_focus (priv->subject_field);
2508 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2511 ModestMsgEditWindowPrivate *priv;
2512 GdkColor *new_color;
2513 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2515 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2516 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2519 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2521 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2523 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2525 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2530 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
2533 ModestMsgEditWindowPrivate *priv;
2534 gint new_size_index;
2535 ModestMsgEditWindow *window;
2538 window = MODEST_MSG_EDIT_WINDOW (userdata);
2539 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2540 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2542 if (gtk_check_menu_item_get_active (menu_item)) {
2544 WPTextBufferFormat format;
2546 memset (&format, 0, sizeof (format));
2547 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2549 label = gtk_bin_get_child (GTK_BIN (menu_item));
2551 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
2552 format.cs.font_size = TRUE;
2553 format.cs.text_position = TRUE;
2554 format.cs.font = TRUE;
2555 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
2556 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2558 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2559 GINT_TO_POINTER (wp_get_font_size_index (new_size_index, 12))))
2560 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2562 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2563 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
2564 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2570 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
2573 ModestMsgEditWindowPrivate *priv;
2574 gint new_font_index;
2575 ModestMsgEditWindow *window;
2578 window = MODEST_MSG_EDIT_WINDOW (userdata);
2579 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2580 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2582 if (gtk_check_menu_item_get_active (menu_item)) {
2585 label = gtk_bin_get_child (GTK_BIN (menu_item));
2587 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
2589 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2590 GINT_TO_POINTER(new_font_index)))
2591 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2593 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2594 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2595 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2601 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2604 ModestMsgEditWindowPrivate *priv = NULL;
2605 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2607 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2608 if (!priv->update_caption_visibility)
2611 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2613 gtk_widget_show (priv->cc_caption);
2615 gtk_widget_hide (priv->cc_caption);
2617 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2621 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2624 ModestMsgEditWindowPrivate *priv = NULL;
2625 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2627 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2628 if (!priv->update_caption_visibility)
2631 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2633 gtk_widget_show (priv->bcc_caption);
2635 gtk_widget_hide (priv->bcc_caption);
2637 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2641 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2642 ModestRecptEditor *editor)
2644 ModestMsgEditWindowPrivate *priv;
2646 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2647 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2649 /* we check for low-mem; in that case, show a warning, and don't allow
2650 * for the addressbook
2652 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2655 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2657 if (editor == NULL) {
2658 GtkWidget *view_focus;
2659 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2661 /* This code should be kept in sync with ModestRecptEditor. The
2662 textview inside the recpt editor is the one that really gets the
2663 focus. As it's inside a scrolled window, and this one inside the
2664 hbox recpt editor inherits from, we'll need to go up in the
2665 hierarchy to know if the text view is part of the recpt editor
2666 or if it's a different text entry */
2668 if (gtk_widget_get_parent (view_focus)) {
2669 GtkWidget *first_parent;
2671 first_parent = gtk_widget_get_parent (view_focus);
2672 if (gtk_widget_get_parent (first_parent) &&
2673 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2674 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2679 editor = MODEST_RECPT_EDITOR (priv->to_field);
2683 modest_address_book_select_addresses (editor);
2688 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2690 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2692 modest_msg_edit_window_open_addressbook (window, NULL);
2696 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2697 gboolean show_toolbar)
2699 ModestWindowPrivate *parent_priv;
2701 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2702 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2704 /* We can not just use the code of
2705 modest_msg_edit_window_setup_toolbar because it has a
2706 mixture of both initialization and creation code. */
2708 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2710 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2714 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2715 TnyHeaderFlags priority_flags)
2717 ModestMsgEditWindowPrivate *priv;
2718 ModestWindowPrivate *parent_priv;
2720 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2722 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2723 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2725 if (priv->priority_flags != priority_flags) {
2726 GtkAction *priority_action = NULL;
2728 priv->priority_flags = priority_flags;
2730 switch (priority_flags) {
2731 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2732 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2733 MODEST_HEADER_ICON_HIGH,
2734 HILDON_ICON_SIZE_XSMALL);
2735 gtk_widget_show (priv->priority_icon);
2736 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2737 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2739 case TNY_HEADER_FLAG_LOW_PRIORITY:
2740 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2741 MODEST_HEADER_ICON_LOW,
2742 HILDON_ICON_SIZE_XSMALL);
2743 gtk_widget_show (priv->priority_icon);
2744 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2745 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2748 gtk_widget_hide (priv->priority_icon);
2749 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2750 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2753 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2754 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2759 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2762 ModestMsgEditWindowPrivate *priv;
2763 ModestWindowPrivate *parent_priv;
2764 gint current_format;
2766 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2768 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2769 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2771 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2772 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2774 if (current_format != file_format) {
2775 switch (file_format) {
2776 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2777 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2778 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
2780 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2784 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2785 response = gtk_dialog_run (GTK_DIALOG (dialog));
2786 gtk_widget_destroy (dialog);
2787 if (response == GTK_RESPONSE_OK) {
2788 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2790 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
2791 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
2796 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2797 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2798 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2803 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2806 ModestMsgEditWindowPrivate *priv;
2807 WPTextBufferFormat oldfmt, fmt;
2808 gint old_position = 0;
2812 GdkColor *color = NULL;
2813 gboolean bold, bold_set, italic, italic_set;
2814 gboolean underline, underline_set;
2815 gboolean strikethrough, strikethrough_set;
2816 gboolean position_set;
2817 gboolean font_size_set, font_set, color_set;
2820 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2821 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2823 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2824 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
2825 GTK_WINDOW(dialog), GTK_WINDOW (window));
2827 /* First we get the currently selected font information */
2828 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2830 switch (oldfmt.text_position) {
2831 case TEXT_POSITION_NORMAL:
2834 case TEXT_POSITION_SUPERSCRIPT:
2842 g_object_set (G_OBJECT (dialog),
2843 "bold", oldfmt.bold != FALSE,
2844 "bold-set", !oldfmt.cs.bold,
2845 "underline", oldfmt.underline != FALSE,
2846 "underline-set", !oldfmt.cs.underline,
2847 "italic", oldfmt.italic != FALSE,
2848 "italic-set", !oldfmt.cs.italic,
2849 "strikethrough", oldfmt.strikethrough != FALSE,
2850 "strikethrough-set", !oldfmt.cs.strikethrough,
2851 "color", &oldfmt.color,
2852 "color-set", !oldfmt.cs.color,
2853 "size", wp_font_size[oldfmt.font_size],
2854 "size-set", !oldfmt.cs.font_size,
2855 "position", old_position,
2856 "position-set", !oldfmt.cs.text_position,
2857 "family", wp_get_font_name (oldfmt.font),
2858 "family-set", !oldfmt.cs.font,
2861 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2862 GTK_WINDOW (dialog), GTK_WINDOW (window));
2863 gtk_widget_show_all (dialog);
2864 priv->font_dialog = dialog;
2865 response = gtk_dialog_run (GTK_DIALOG (dialog));
2866 priv->font_dialog = NULL;
2867 if (response == GTK_RESPONSE_OK) {
2869 g_object_get( dialog,
2871 "bold-set", &bold_set,
2872 "underline", &underline,
2873 "underline-set", &underline_set,
2875 "italic-set", &italic_set,
2876 "strikethrough", &strikethrough,
2877 "strikethrough-set", &strikethrough_set,
2879 "color-set", &color_set,
2881 "size-set", &font_size_set,
2882 "family", &font_name,
2883 "family-set", &font_set,
2884 "position", &position,
2885 "position-set", &position_set,
2890 if (response == GTK_RESPONSE_OK) {
2891 memset(&fmt, 0, sizeof(fmt));
2897 fmt.italic = italic;
2898 fmt.cs.italic = TRUE;
2900 if (underline_set) {
2901 fmt.underline = underline;
2902 fmt.cs.underline = TRUE;
2904 if (strikethrough_set) {
2905 fmt.strikethrough = strikethrough;
2906 fmt.cs.strikethrough = TRUE;
2911 ? TEXT_POSITION_NORMAL
2912 : ( ( position == 1 )
2913 ? TEXT_POSITION_SUPERSCRIPT
2914 : TEXT_POSITION_SUBSCRIPT );
2915 fmt.cs.text_position = TRUE;
2916 fmt.font_size = oldfmt.font_size;
2920 fmt.cs.color = TRUE;
2923 fmt.font = wp_get_font_index(font_name,
2928 if (font_size_set) {
2929 fmt.cs.font_size = TRUE;
2930 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
2932 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2933 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2935 gtk_widget_destroy (dialog);
2937 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2941 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2943 ModestMsgEditWindowPrivate *priv;
2945 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2946 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2948 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2950 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2951 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2955 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
2957 ModestMsgEditWindowPrivate *priv;
2959 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2960 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2962 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
2964 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2965 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2970 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
2972 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2974 priv->can_undo = can_undo;
2978 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
2980 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2982 priv->can_redo = can_redo;
2986 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
2988 ModestMsgEditWindowPrivate *priv;
2989 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2990 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2992 return priv->can_undo;
2996 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
2998 ModestMsgEditWindowPrivate *priv;
2999 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3000 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3002 return priv->can_redo;
3007 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3010 GtkTextIter match_start, match_end;
3012 if (image_id == NULL)
3015 gtk_text_buffer_get_start_iter (buffer, &iter);
3017 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3018 GSList *tags = gtk_text_iter_get_tags (&match_start);
3020 for (node = tags; node != NULL; node = g_slist_next (node)) {
3021 GtkTextTag *tag = (GtkTextTag *) node->data;
3022 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3023 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3024 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3026 offset = gtk_text_iter_get_offset (&match_start);
3027 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3028 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3032 gtk_text_iter_forward_char (&iter);
3037 message_is_empty (ModestMsgEditWindow *window)
3039 ModestMsgEditWindowPrivate *priv = NULL;
3041 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3042 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3044 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3045 * so we can ignore markup.
3047 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3050 count = gtk_text_buffer_get_char_count (buf);
3056 msg_body_focus (GtkWidget *focus,
3057 GdkEventFocus *event,
3061 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3062 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3063 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3068 recpt_field_changed (GtkTextBuffer *buffer,
3069 ModestMsgEditWindow *editor)
3071 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3072 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3076 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3078 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3079 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3083 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3086 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3087 GtkTextBuffer *buffer;
3089 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3090 gtk_text_buffer_set_modified (buffer, modified);
3091 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3092 gtk_text_buffer_set_modified (buffer, modified);
3093 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3094 gtk_text_buffer_set_modified (buffer, modified);
3095 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3099 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3101 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3102 const char *account_name;
3103 GtkTextBuffer *buffer;
3105 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3106 if (gtk_text_buffer_get_modified (buffer))
3108 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3109 if (gtk_text_buffer_get_modified (buffer))
3111 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3112 if (gtk_text_buffer_get_modified (buffer))
3114 if (gtk_text_buffer_get_modified (priv->text_buffer))
3116 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3117 if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3128 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3130 ModestMsgEditWindowPrivate *priv = NULL;
3132 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3133 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3135 /* check if there's no recipient added */
3136 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3137 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3138 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3139 /* no recipient contents, then select contacts */
3140 modest_msg_edit_window_open_addressbook (window, NULL);
3144 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3145 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3148 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3149 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3152 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3153 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3157 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3158 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3159 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3166 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3167 ModestMsgEditWindow *window)
3169 modest_msg_edit_window_offer_attach_file (window);
3173 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3175 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3177 return priv->clipboard_text;
3181 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3183 ModestMsgEditWindow *window)
3185 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3186 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3188 if (!GTK_WIDGET_VISIBLE (window))
3191 g_object_ref (window);
3192 text = gtk_clipboard_wait_for_text (selection_clipboard);
3194 if (priv->clipboard_text != NULL) {
3195 g_free (priv->clipboard_text);
3197 priv->clipboard_text = text;
3199 if (GTK_WIDGET_VISIBLE (window)) {
3200 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3202 g_object_unref (window);
3205 static gboolean clipboard_owner_change_idle (gpointer userdata)
3207 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3208 ModestMsgEditWindowPrivate *priv;
3210 gdk_threads_enter ();
3211 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3212 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3214 priv->clipboard_owner_idle = 0;
3215 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3216 gdk_threads_leave ();
3222 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3224 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3225 if (priv->clipboard_owner_idle == 0) {
3226 priv->clipboard_owner_idle = g_idle_add (clipboard_owner_change_idle, window);
3231 subject_field_move_cursor (GtkEntry *entry,
3232 GtkMovementStep step,
3237 if (!GTK_WIDGET_VISIBLE (window))
3240 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3244 update_window_title (ModestMsgEditWindow *window)
3246 ModestMsgEditWindowPrivate *priv = NULL;
3247 const gchar *subject;
3249 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3250 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3251 if (subject == NULL || subject[0] == '\0')
3252 subject = _("mail_va_new_email");
3254 gtk_window_set_title (GTK_WINDOW (window), subject);
3259 subject_field_changed (GtkEditable *editable,
3260 ModestMsgEditWindow *window)
3262 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3263 update_window_title (window);
3264 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3265 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3266 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3270 subject_field_insert_text (GtkEditable *editable,
3272 gint new_text_length,
3274 ModestMsgEditWindow *window)
3276 GString *result = g_string_new ("");
3278 gint result_len = 0;
3279 const gchar *entry_text = NULL;
3282 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3283 old_length = g_utf8_strlen (entry_text, -1);
3285 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3286 gunichar c = g_utf8_get_char_validated (current, 8);
3287 /* Invalid unichar, stop */
3293 result = g_string_append_unichar (result, c);
3297 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3298 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3301 /* Prevent endless recursion */
3302 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3303 g_signal_emit_by_name (editable, "insert-text",
3304 (gpointer) result->str, (gpointer) result->len,
3305 (gpointer) position, (gpointer) window);
3306 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3310 if (result_len + old_length > 1000) {
3311 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3312 dgettext("hildon-common-strings",
3313 "ckdg_ib_maximum_characters_reached"));
3315 g_string_free (result, TRUE);
3319 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3322 ModestMsgEditWindowPrivate *priv = NULL;
3324 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3325 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3327 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3330 gtk_widget_show_all (priv->find_toolbar);
3331 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3333 gtk_widget_hide_all (priv->find_toolbar);
3334 gtk_widget_grab_focus (priv->msg_body);
3339 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3341 GtkTextIter *match_start,
3342 GtkTextIter *match_end)
3344 GtkTextIter end_iter;
3345 gchar *str_casefold;
3348 gchar *range_casefold;
3351 gboolean result = FALSE;
3358 gtk_text_iter_forward_to_end (&end_iter);
3360 str_casefold = g_utf8_casefold (str, -1);
3361 str_chars_n = strlen (str);
3363 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3364 range_casefold = g_utf8_casefold (range_text, -1);
3365 range_chars_n = strlen (range_casefold);
3367 if (range_chars_n < str_chars_n) {
3368 g_free (str_casefold);
3369 g_free (range_text);
3370 g_free (range_casefold);
3374 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3375 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3376 if (!g_utf8_collate (range_subtext, str_casefold)) {
3377 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3379 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3380 match_start, match_end, NULL);
3381 g_free (found_text);
3383 g_free (range_subtext);
3387 g_free (str_casefold);
3388 g_free (range_text);
3389 g_free (range_casefold);
3396 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3397 ModestMsgEditWindow *window)
3399 gchar *current_search = NULL;
3400 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3402 GtkTextIter selection_start, selection_end;
3403 GtkTextIter match_start, match_end;
3404 gboolean continue_search = FALSE;
3406 if (message_is_empty (window)) {
3407 g_free (priv->last_search);
3408 priv->last_search = NULL;
3409 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3413 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3414 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3415 g_free (current_search);
3416 g_free (priv->last_search);
3417 priv->last_search = NULL;
3418 /* Information banner about empty search */
3419 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-common-strings", "ecdg_ib_find_rep_enter_text"));
3423 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3424 continue_search = TRUE;
3426 g_free (priv->last_search);
3427 priv->last_search = g_strdup (current_search);
3430 if (continue_search) {
3431 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3432 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3433 &match_start, &match_end);
3435 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_search_complete"));
3437 GtkTextIter buffer_start;
3438 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3439 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3440 &match_start, &match_end);
3442 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_no_matches"));
3445 /* Mark as selected the string found in search */
3447 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3448 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3449 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3451 g_free (priv->last_search);
3452 priv->last_search = NULL;
3454 g_free (current_search);
3458 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3460 ModestMsgEditWindowPrivate *priv;
3462 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3467 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3470 ModestMsgEditWindowPrivate *priv;
3472 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3477 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3478 ModestMsgEditWindow *window)
3480 modest_msg_edit_window_toggle_find_toolbar (window, FALSE);
3484 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3487 ModestMsgEditWindowPrivate *priv;
3488 TnyHeader *header = NULL;
3490 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3491 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3493 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3494 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3496 if (priv->draft_msg != NULL) {
3497 g_object_unref (priv->draft_msg);
3500 if (draft != NULL) {
3501 g_object_ref (draft);
3502 header = tny_msg_get_header (draft);
3503 if (priv->msg_uid) {
3504 g_free (priv->msg_uid);
3505 priv->msg_uid = NULL;
3507 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3508 if (GTK_WIDGET_REALIZED (window)) {
3509 if (!modest_window_mgr_register_window (mgr, MODEST_WINDOW (window), NULL)) {
3510 gtk_widget_destroy (GTK_WIDGET (window));
3516 priv->draft_msg = draft;
3520 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3521 GtkTextIter *start, GtkTextIter *end,
3524 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3525 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3528 if (tag == NULL) return;
3529 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3530 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3531 replace_with_images (window, priv->images);
3536 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3539 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3541 g_return_if_fail (TNY_IS_MIME_PART (part));
3542 tny_list_prepend (priv->attachments, (GObject *) part);
3543 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3544 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3545 gtk_widget_show_all (priv->attachments_caption);
3546 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3550 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3552 ModestMsgEditWindowPrivate *priv;
3554 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3555 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3557 return priv->msg_uid;
3561 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3562 ModestMsgEditWindowWidgetType widget_type)
3564 ModestMsgEditWindowPrivate *priv;
3566 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3567 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3569 switch (widget_type) {
3570 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3571 return priv->msg_body;
3573 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3574 return priv->to_field;
3576 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3577 return priv->cc_field;
3579 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3580 return priv->bcc_field;
3582 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3583 return priv->subject_field;
3585 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3586 return priv->attachments_view;
3594 remove_tags (WPTextBuffer *buffer)
3596 GtkTextIter start, end;
3598 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3599 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3601 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3605 on_account_removed (TnyAccountStore *account_store,
3606 TnyAccount *account,
3609 /* Do nothing if it's a store account, because we use the
3610 transport to send the messages */
3611 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3612 const gchar *parent_acc = NULL;
3613 const gchar *our_acc = NULL;
3615 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3616 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3617 /* Close this window if I'm showing a message of the removed account */
3618 if (strcmp (parent_acc, our_acc) == 0)
3619 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3623 typedef struct _MessageSettingsHelper {
3624 ModestMsgEditWindow *window;
3625 GSList *priority_group;
3626 GSList *format_group;
3627 } MessageSettingsHelper;
3630 on_priority_toggle (GtkToggleButton *button,
3631 MessageSettingsHelper *helper)
3634 ModestMsgEditWindowPrivate *priv;
3636 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3637 if (gtk_toggle_button_get_active (button)) {
3639 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3640 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3641 if ((node_button != button) &&
3642 gtk_toggle_button_get_active (node_button)) {
3643 gtk_toggle_button_set_active (node_button, FALSE);
3646 if (priv->priority_flags != (TnyHeaderFlags) g_object_get_data (G_OBJECT (button), "priority"))
3647 modest_msg_edit_window_set_priority_flags (helper->window,
3649 g_object_get_data (G_OBJECT (button),
3653 gboolean found = FALSE;
3654 /* If no one is active, activate it again */
3655 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3656 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3657 if (gtk_toggle_button_get_active (node_button)) {
3663 gtk_toggle_button_set_active (button, TRUE);
3669 on_format_toggle (GtkToggleButton *button,
3670 MessageSettingsHelper *helper)
3673 ModestMsgEditWindowPrivate *priv;
3674 ModestMsgEditFormat old_format;
3676 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3677 old_format = modest_msg_edit_window_get_format (helper->window);
3678 if (gtk_toggle_button_get_active (button)) {
3680 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
3681 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3682 if ((node_button != button) &&
3683 gtk_toggle_button_get_active (node_button)) {
3684 gtk_toggle_button_set_active (node_button, FALSE);
3687 if (old_format != (ModestMsgEditFormat) g_object_get_data (G_OBJECT (button), "format")) {
3688 modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (helper->window),
3689 GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button), "file-format")));
3693 gboolean found = FALSE;
3694 /* If no one is active, activate it again */
3695 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
3696 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3697 if (gtk_toggle_button_get_active (node_button)) {
3703 gtk_toggle_button_set_active (button, TRUE);
3710 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
3714 GtkWidget *priority_hbox;
3715 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
3716 GtkWidget *captioned;
3717 GtkSizeGroup *title_sizegroup, *value_sizegroup;
3718 GtkWidget *format_hbox;
3719 GtkWidget *html_toggle, *text_toggle;
3720 ModestMsgEditWindowPrivate *priv;
3721 MessageSettingsHelper helper = {0,};
3723 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3724 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3725 helper.window = window;
3726 helper.priority_group = NULL;
3728 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3729 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3731 dialog = gtk_dialog_new ();
3732 vbox = gtk_vbox_new (FALSE, 0);
3733 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), vbox);
3734 gtk_widget_show (vbox);
3736 /* Priority toggles */
3737 priority_hbox = gtk_hbox_new (TRUE, 0);
3738 high_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3739 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
3740 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
3741 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
3742 medium_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3743 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
3744 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
3745 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
3746 low_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3747 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
3748 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
3749 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
3750 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, TRUE, TRUE, 0);
3751 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, TRUE, TRUE, 0);
3752 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, TRUE, TRUE, 0);
3753 gtk_widget_show_all (priority_hbox);
3754 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
3755 _("mcen_me_editor_message_priority"), priority_hbox);
3756 gtk_widget_show (captioned);
3757 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
3759 /* format toggles */
3760 format_hbox = gtk_hbox_new (TRUE, 0);
3761 html_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3762 gtk_button_set_label (GTK_BUTTON (html_toggle), _("mcen_me_editor_formatted_text"));
3763 helper.format_group = g_slist_prepend (helper.format_group, html_toggle);
3764 g_object_set_data (G_OBJECT (html_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_HTML));
3765 g_object_set_data (G_OBJECT (html_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_FORMATTED_TEXT));
3766 text_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3767 gtk_button_set_label (GTK_BUTTON (text_toggle), _("mcen_me_editor_plain_text"));
3768 helper.format_group = g_slist_prepend (helper.format_group, text_toggle);
3769 g_object_set_data (G_OBJECT (text_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_TEXT));
3770 g_object_set_data (G_OBJECT (text_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_PLAIN_TEXT));
3771 gtk_box_pack_start (GTK_BOX (format_hbox), html_toggle, TRUE, TRUE, 0);
3772 gtk_box_pack_start (GTK_BOX (format_hbox), text_toggle, TRUE, TRUE, 0);
3773 gtk_widget_show_all (format_hbox);
3774 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
3775 _("mcen_me_editor_format"), format_hbox);
3776 gtk_widget_show (captioned);
3777 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
3780 g_object_unref (title_sizegroup);
3781 g_object_unref (value_sizegroup);
3782 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_me_message_settings"));
3784 /* Set current values */
3785 switch (priv->priority_flags) {
3786 case TNY_HEADER_FLAG_HIGH_PRIORITY:
3787 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (high_toggle), TRUE);
3789 case TNY_HEADER_FLAG_LOW_PRIORITY:
3790 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (low_toggle), TRUE);
3793 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (medium_toggle), TRUE);
3797 switch (modest_msg_edit_window_get_format (window)) {
3798 case MODEST_MSG_EDIT_FORMAT_TEXT:
3799 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_toggle), TRUE);
3801 case MODEST_MSG_EDIT_FORMAT_HTML:
3803 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (html_toggle), TRUE);
3807 /* Signal connects */
3808 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3809 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3810 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3811 g_signal_connect (G_OBJECT (html_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
3812 g_signal_connect (G_OBJECT (text_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
3814 gtk_dialog_run (GTK_DIALOG (dialog));
3816 /* Read new values */
3818 gtk_widget_destroy (dialog);
3819 g_slist_free (helper.priority_group);
3823 static void on_message_settings (GtkAction *action,
3824 ModestMsgEditWindow *window)
3826 modest_msg_edit_window_show_msg_settings_dialog (window);
3830 on_cc_button_toggled (HildonCheckButton *button,
3831 ModestMsgEditWindow *window)
3833 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
3835 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
3836 hildon_check_button_get_active (button));
3840 on_bcc_button_toggled (HildonCheckButton *button,
3841 ModestMsgEditWindow *window)
3843 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
3845 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
3846 hildon_check_button_get_active (button));
3850 setup_menu (ModestMsgEditWindow *self)
3852 ModestMsgEditWindowPrivate *priv = NULL;
3854 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
3856 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3858 /* Settings menu buttons */
3859 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_checknames"), NULL,
3860 APP_MENU_CALLBACK (modest_ui_actions_on_check_names),
3862 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_undo"), "<Ctrl>z",
3863 APP_MENU_CALLBACK (modest_ui_actions_on_undo),
3864 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_undo));
3866 priv->cc_button = hildon_check_button_new (0);
3867 gtk_button_set_label (GTK_BUTTON (priv->cc_button), _("mcen_me_editor_showcc"));
3868 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button),
3870 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->cc_button),
3872 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
3873 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
3874 priv->bcc_button = hildon_check_button_new (0);
3875 gtk_button_set_label (GTK_BUTTON (priv->bcc_button), _("mcen_me_editor_showbcc"));
3876 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button),
3878 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->bcc_button),
3880 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
3881 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
3883 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_attach_inlineimage"), NULL,
3884 APP_MENU_CALLBACK (modest_ui_actions_on_insert_image),
3885 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_set_style));
3886 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_remove_attachments"), NULL,
3887 APP_MENU_CALLBACK (modest_ui_actions_on_remove_attachments),
3888 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
3889 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_message_settings"), NULL,
3890 APP_MENU_CALLBACK (on_message_settings),
3892 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_viewer_find"), "<Ctrl>f",
3893 APP_MENU_CALLBACK (modest_ui_actions_on_toggle_find_in_page),