1 /* Copyright (c) 2006, Nokia Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of the Nokia Corporation nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include <glib/gi18n.h>
33 #include <glib/gstdio.h>
35 #include <tny-account-store.h>
36 #include <tny-fs-stream.h>
37 #include <tny-vfs-stream.h>
38 #include <tny-camel-mem-stream.h>
42 #include <modest-account-mgr.h>
43 #include <modest-account-mgr-helpers.h>
45 #include <widgets/modest-msg-edit-window.h>
46 #include <modest-selector-picker.h>
47 #include <widgets/modest-recpt-editor.h>
48 #include <widgets/modest-attachments-view.h>
50 #include <modest-runtime.h>
52 #include "modest-platform.h"
53 #include "modest-icon-names.h"
54 #include "modest-widget-memory.h"
55 #include "modest-window-priv.h"
56 #include "modest-mail-operation.h"
57 #include "modest-tny-platform-factory.h"
58 #include "modest-tny-msg.h"
59 #include "modest-tny-folder.h"
60 #include "modest-tny-account.h"
61 #include "modest-address-book.h"
62 #include "modest-text-utils.h"
63 #include <tny-simple-list.h>
64 #include <wptextview.h>
65 #include <wptextbuffer.h>
66 #include <hildon/hildon-pannable-area.h>
67 #include "modest-msg-edit-window-ui-dimming.h"
69 #include "modest-hildon-includes.h"
70 #ifdef MODEST_HAVE_HILDON0_WIDGETS
71 #include <hildon-widgets/hildon-color-chooser.h>
73 #include "widgets/modest-msg-edit-window-ui.h"
74 #ifdef MODEST_HAVE_HILDON0_WIDGETS
75 #include <libgnomevfs/gnome-vfs-mime-utils.h>
77 #include <libgnomevfs/gnome-vfs-mime.h>
79 #include <modest-utils.h>
80 #include "modest-maemo-utils.h"
81 #include <modest-ui-constants.h>
84 #define DEFAULT_FONT_SIZE 3
85 #define DEFAULT_FONT 2
86 #define DEFAULT_SIZE_BUTTON_FONT_FAMILY "Sans"
87 #define DEFAULT_MAIN_VBOX_SPACING 6
88 #define SUBJECT_MAX_LENGTH 1000
89 #define IMAGE_MAX_WIDTH 560
90 #define DEFAULT_FONT_SCALE 1.5
92 static gboolean is_wp_text_buffer_started = FALSE;
94 static void modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass);
95 static void modest_msg_edit_window_init (ModestMsgEditWindow *obj);
96 static void modest_msg_edit_window_finalize (GObject *obj);
98 static gboolean msg_body_focus (GtkWidget *focus, GdkEventFocus *event, gpointer userdata);
99 static void body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
100 static void recpt_field_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
102 static void text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window);
103 static void text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window);
104 static void text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window);
105 static void text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
106 GtkTextIter *start, GtkTextIter *end,
108 static void text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id);
109 static void subject_field_changed (GtkEditable *editable, ModestMsgEditWindow *window);
110 static void subject_field_insert_text (GtkEditable *editable,
112 gint new_text_length,
114 ModestMsgEditWindow *window);
115 static void modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
117 static void modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
119 static void modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
121 static void modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
123 static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
124 ModestRecptEditor *editor);
125 static void modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
126 ModestMsgEditWindow *window);
128 /* ModestWindow methods implementation */
129 static void modest_msg_edit_window_disconnect_signals (ModestWindow *window);
130 static void modest_msg_edit_window_show_toolbar (ModestWindow *window,
131 gboolean show_toolbar);
132 static void modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
134 ModestMsgEditWindow *window);
135 static void modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window);
136 static void subject_field_move_cursor (GtkEntry *entry,
137 GtkMovementStep step,
141 static void update_window_title (ModestMsgEditWindow *window);
144 static void modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
145 ModestMsgEditWindow *window);
146 static void modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
147 ModestMsgEditWindow *window);
148 static gboolean gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
150 GtkTextIter *match_start,
151 GtkTextIter *match_end);
153 static void remove_tags (WPTextBuffer *buffer);
155 static void on_account_removed (TnyAccountStore *account_store,
159 static void init_window (ModestMsgEditWindow *obj);
161 gboolean scroll_drag_timeout (gpointer userdata);
162 static void correct_scroll (ModestMsgEditWindow *w);
163 static void correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused);
164 static void text_buffer_end_user_action (GtkTextBuffer *buffer,
165 ModestMsgEditWindow *userdata);
166 static void text_buffer_mark_set (GtkTextBuffer *buffer,
169 ModestMsgEditWindow *userdata);
170 static void on_message_settings (GtkAction *action,
171 ModestMsgEditWindow *window);
172 static void setup_menu (ModestMsgEditWindow *self);
174 static void DEBUG_BUFFER (WPTextBuffer *buffer)
178 g_message ("BEGIN BUFFER OF SIZE %d", gtk_text_buffer_get_char_count (GTK_TEXT_BUFFER (buffer)));
180 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &iter);
181 while (!gtk_text_iter_is_end (&iter)) {
182 GString *output = g_string_new ("");
183 GSList *toggled_tags;
186 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
187 g_string_append_printf (output, "%d: CLOSED [ ", gtk_text_iter_get_offset (&iter));
188 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
189 GtkTextTag *tag = (GtkTextTag *) node->data;
191 g_object_get (G_OBJECT (tag), "name", &name, NULL);
192 output = g_string_append (output, name);
193 g_string_append (output, " ");
195 output = g_string_append (output, "] OPENED [ ");
196 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
197 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
198 GtkTextTag *tag = (GtkTextTag *) node->data;
200 g_object_get (G_OBJECT (tag), "name", &name, NULL);
201 output = g_string_append (output, name);
202 g_string_append (output, " ");
204 output = g_string_append (output, "]\n");
205 g_message ("%s", output->str);
206 g_string_free (output, TRUE);
207 gtk_text_iter_forward_to_tag_toggle (&iter, NULL);
209 g_message ("END BUFFER");
213 static const GtkActionEntry hildon2_msg_edit_action_entries [] = {
214 { "MessageSettings", NULL, N_("mcen_me_message_settings"), NULL, NULL, G_CALLBACK (on_message_settings)},
218 /* static gboolean */
219 /* on_key_pressed (GtkWidget *self, */
220 /* GdkEventKey *event, */
221 /* gpointer user_data); */
223 /* list my signals */
230 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
231 struct _ModestMsgEditWindowPrivate {
234 GtkWidget *header_box;
236 ModestPairList *from_field_protos;
237 GtkWidget *from_field;
238 gchar *original_account_name;
242 GtkWidget *bcc_field;
243 GtkWidget *subject_field;
244 GtkWidget *attachments_view;
245 GtkWidget *priority_icon;
246 GtkWidget *add_attachment_button;
248 GtkWidget *cc_caption;
249 GtkWidget *bcc_caption;
250 gboolean update_caption_visibility;
251 GtkWidget *attachments_caption;
253 GtkTextBuffer *text_buffer;
255 GtkWidget *font_size_toolitem;
256 GtkWidget *font_face_toolitem;
257 GtkWidget *font_color_button;
258 GtkWidget *font_color_toolitem;
259 GSList *font_items_group;
260 GtkWidget *font_tool_button_label;
261 GSList *size_items_group;
262 GtkWidget *size_tool_button_label;
264 GtkWidget *find_toolbar;
267 GtkWidget *font_dialog;
270 guint correct_scroll_idle;
271 guint scroll_drag_timeout_id;
275 TnyList *attachments;
280 TnyHeaderFlags priority_flags;
282 gboolean can_undo, can_redo;
283 gulong clipboard_change_handler_id;
284 gulong default_clipboard_change_handler_id;
285 gulong account_removed_handler_id;
286 guint clipboard_owner_idle;
287 gchar *clipboard_text;
296 GtkWidget *cc_button;
297 GtkWidget *bcc_button;
300 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
301 MODEST_TYPE_MSG_EDIT_WINDOW, \
302 ModestMsgEditWindowPrivate))
304 static GtkWindowClass *parent_class = NULL;
306 /* uncomment the following if you have defined any signals */
307 /* static guint signals[LAST_SIGNAL] = {0}; */
310 modest_msg_edit_window_get_type (void)
312 static GType my_type = 0;
314 static const GTypeInfo my_info = {
315 sizeof(ModestMsgEditWindowClass),
316 NULL, /* base init */
317 NULL, /* base finalize */
318 (GClassInitFunc) modest_msg_edit_window_class_init,
319 NULL, /* class finalize */
320 NULL, /* class data */
321 sizeof(ModestMsgEditWindow),
323 (GInstanceInitFunc) modest_msg_edit_window_init,
326 my_type = g_type_register_static (MODEST_TYPE_HILDON2_WINDOW,
327 "ModestMsgEditWindow",
335 save_state (ModestWindow *self)
337 modest_widget_memory_save (modest_runtime_get_conf(),
338 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
343 restore_settings (ModestMsgEditWindow *self)
345 ModestConf *conf = NULL;
347 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
349 conf = modest_runtime_get_conf ();
351 /* Dim at start clipboard actions */
352 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
353 gtk_action_set_sensitive (action, FALSE);
354 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
355 gtk_action_set_sensitive (action, FALSE);
356 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
357 gtk_action_set_sensitive (action, FALSE);
359 modest_widget_memory_restore (conf, G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
364 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
366 GObjectClass *gobject_class;
367 ModestWindowClass *modest_window_class;
368 gobject_class = (GObjectClass*) klass;
369 modest_window_class = (ModestWindowClass*) klass;
371 parent_class = g_type_class_peek_parent (klass);
372 gobject_class->finalize = modest_msg_edit_window_finalize;
374 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
375 modest_window_class->save_state_func = save_state;
376 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
378 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
382 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
384 ModestMsgEditWindowPrivate *priv;
385 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
387 priv->msg_body = NULL;
389 priv->from_field = NULL;
390 priv->to_field = NULL;
391 priv->cc_field = NULL;
392 priv->bcc_field = NULL;
393 priv->subject_field = NULL;
394 priv->attachments = TNY_LIST (tny_simple_list_new ());
395 priv->images = TNY_LIST (tny_simple_list_new ());
396 priv->images_size = 0;
397 priv->images_count = 0;
400 priv->cc_caption = NULL;
401 priv->bcc_caption = NULL;
402 priv->update_caption_visibility = FALSE;
404 priv->priority_flags = 0;
406 priv->find_toolbar = NULL;
407 priv->last_search = NULL;
409 priv->draft_msg = NULL;
410 priv->outbox_msg = NULL;
411 priv->msg_uid = NULL;
413 priv->can_undo = FALSE;
414 priv->can_redo = FALSE;
415 priv->clipboard_change_handler_id = 0;
416 priv->default_clipboard_change_handler_id = 0;
417 priv->account_removed_handler_id = 0;
418 priv->clipboard_owner_idle = 0;
419 priv->clipboard_text = NULL;
422 priv->scroll_drag_timeout_id = 0;
423 priv->correct_scroll_idle = 0;
424 priv->last_upper = 0.0;
426 priv->font_dialog = NULL;
427 priv->app_menu = NULL;
429 if (!is_wp_text_buffer_started) {
430 is_wp_text_buffer_started = TRUE;
431 wp_text_buffer_library_init ();
436 hildon_program_add_window (hildon_program_get_instance(),
442 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
444 static ModestPairList*
445 get_transports (void)
447 GSList *transports = NULL;
449 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
450 GSList *accounts = modest_account_mgr_account_names (account_mgr,
451 TRUE /* only enabled accounts. */);
453 GSList *cursor = accounts;
455 gchar *account_name = cursor->data;
456 gchar *from_string = NULL;
458 from_string = modest_account_mgr_get_from_string (account_mgr,
462 if (from_string && account_name) {
463 gchar *name = account_name;
464 ModestPair *pair = modest_pair_new ((gpointer) name,
465 (gpointer) from_string , TRUE);
466 transports = g_slist_prepend (transports, pair);
469 cursor = cursor->next;
471 g_slist_free (accounts); /* only free the accounts, not the elements,
472 * because they are used in the pairlist */
476 static void window_focus (GtkWindow *window,
480 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
484 scroll_drag_timeout (gpointer userdata)
486 ModestMsgEditWindow *win = (ModestMsgEditWindow *) userdata;
487 ModestMsgEditWindowPrivate *priv;
489 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(win);
491 correct_scroll_without_drag_check (win, TRUE);
493 priv->scroll_drag_timeout_id = 0;
499 correct_scroll_without_drag_check_idle (gpointer userdata)
501 ModestMsgEditWindow *w = (ModestMsgEditWindow *) userdata;
502 ModestMsgEditWindowPrivate *priv;
504 GdkRectangle rectangle;
509 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
511 insert = gtk_text_buffer_get_insert (priv->text_buffer);
512 gtk_text_buffer_get_iter_at_mark (priv->text_buffer, &iter, insert);
514 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &iter, &rectangle);
515 offset = priv->msg_body->allocation.y;
517 new_value = (offset + rectangle.y);
519 hildon_pannable_area_jump_to (HILDON_PANNABLE_AREA (priv->pannable), -1, new_value);
521 priv->correct_scroll_idle = 0;
526 correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused)
528 ModestMsgEditWindowPrivate *priv;
530 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
532 if (only_if_focused && !gtk_widget_is_focus (priv->msg_body))
535 if (priv->correct_scroll_idle > 0) {
539 priv->correct_scroll_idle = g_idle_add ((GSourceFunc) correct_scroll_without_drag_check_idle,
544 correct_scroll (ModestMsgEditWindow *w)
546 ModestMsgEditWindowPrivate *priv;
548 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
549 if (gtk_grab_get_current () == priv->msg_body) {
550 if (priv->scroll_drag_timeout_id == 0) {
551 priv->scroll_drag_timeout_id = g_timeout_add (500, (GSourceFunc) scroll_drag_timeout,
557 correct_scroll_without_drag_check (w, TRUE);
561 text_buffer_end_user_action (GtkTextBuffer *buffer,
562 ModestMsgEditWindow *userdata)
565 correct_scroll (userdata);
569 text_buffer_mark_set (GtkTextBuffer *buffer,
572 ModestMsgEditWindow *userdata)
574 gtk_text_buffer_begin_user_action (buffer);
575 gtk_text_buffer_end_user_action (buffer);
579 cut_clipboard_check (GtkTextView *text_view,
582 GtkTextBuffer *buffer;
584 buffer = gtk_text_view_get_buffer (text_view);
585 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
586 g_signal_stop_emission_by_name ((gpointer )text_view, "cut-clipboard");
591 copy_clipboard_check (GtkTextView *text_view,
594 GtkTextBuffer *buffer;
596 buffer = gtk_text_view_get_buffer (text_view);
597 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
598 g_signal_stop_emission_by_name ((gpointer )text_view, "copy-clipboard");
603 attachment_deleted (ModestAttachmentsView *attachments_view,
606 modest_msg_edit_window_remove_attachments (MODEST_MSG_EDIT_WINDOW (user_data),
611 connect_signals (ModestMsgEditWindow *obj)
613 ModestMsgEditWindowPrivate *priv;
615 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
617 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
618 G_CALLBACK (text_buffer_refresh_attributes), obj);
619 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
620 G_CALLBACK (text_buffer_can_undo), obj);
621 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
622 G_CALLBACK (text_buffer_can_redo), obj);
623 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
624 G_CALLBACK (body_changed), obj);
625 g_signal_connect (G_OBJECT (priv->text_buffer), "modified-changed",
626 G_CALLBACK (body_changed), obj);
627 g_signal_connect (G_OBJECT (priv->text_buffer), "end-user-action",
628 G_CALLBACK (text_buffer_end_user_action), obj);
629 g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
630 G_CALLBACK (text_buffer_mark_set), obj);
631 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
632 G_CALLBACK (text_buffer_apply_tag), obj);
633 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
634 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
635 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
636 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
637 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
638 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
640 g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
641 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
643 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
644 G_CALLBACK (msg_body_focus), obj);
645 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
646 G_CALLBACK (msg_body_focus), obj);
647 g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
648 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
649 "changed", G_CALLBACK (recpt_field_changed), obj);
650 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
651 "changed", G_CALLBACK (recpt_field_changed), obj);
652 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
653 "changed", G_CALLBACK (recpt_field_changed), obj);
654 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
655 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
656 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
658 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
659 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
661 priv->clipboard_change_handler_id =
662 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
663 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
664 priv->default_clipboard_change_handler_id =
665 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
666 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
668 g_signal_connect (G_OBJECT (priv->msg_body), "cut-clipboard", G_CALLBACK (cut_clipboard_check), NULL);
669 g_signal_connect (G_OBJECT (priv->msg_body), "copy-clipboard", G_CALLBACK (copy_clipboard_check), NULL);
670 g_signal_connect (G_OBJECT (priv->attachments_view), "delete", G_CALLBACK (attachment_deleted), obj);
674 init_wp_text_view_style ()
676 static gboolean initialized = FALSE;
679 gtk_rc_parse_string ("class \"WPTextView\" style \"fremantle-textview\"");
685 init_window (ModestMsgEditWindow *obj)
687 GtkWidget *to_caption, *subject_caption;
688 GtkWidget *main_vbox;
689 ModestMsgEditWindowPrivate *priv;
690 GtkActionGroup *action_group;
691 ModestWindowPrivate *parent_priv;
692 GdkPixbuf *window_icon = NULL;
693 GError *error = NULL;
695 GtkSizeGroup *title_size_group;
696 GtkSizeGroup *value_size_group;
697 GtkWidget *subject_box;
698 GtkWidget *attachment_icon;
699 GtkWidget *window_box;
700 #if (GTK_MINOR_VERSION >= 10)
701 GdkAtom deserialize_type;
704 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
705 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
707 parent_priv->ui_manager = gtk_ui_manager_new();
708 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
709 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
711 /* Add common actions */
712 gtk_action_group_add_actions (action_group,
713 modest_msg_edit_action_entries,
714 G_N_ELEMENTS (modest_msg_edit_action_entries),
716 gtk_action_group_add_actions (action_group,
717 hildon2_msg_edit_action_entries,
718 G_N_ELEMENTS (hildon2_msg_edit_action_entries),
720 gtk_action_group_add_toggle_actions (action_group,
721 modest_msg_edit_toggle_action_entries,
722 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
724 gtk_action_group_add_radio_actions (action_group,
725 modest_msg_edit_alignment_radio_action_entries,
726 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
728 G_CALLBACK (modest_ui_actions_on_change_justify),
730 gtk_action_group_add_radio_actions (action_group,
731 modest_msg_edit_priority_action_entries,
732 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
734 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
736 gtk_action_group_add_radio_actions (action_group,
737 modest_msg_edit_file_format_action_entries,
738 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
739 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
740 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
742 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
743 g_object_unref (action_group);
745 /* Load the UI definition */
746 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
749 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
750 g_clear_error (&error);
753 /* Add accelerators */
754 gtk_window_add_accel_group (GTK_WINDOW (obj),
755 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
757 parent_priv->menubar = NULL;
759 title_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
760 value_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
762 /* Note: This ModestPairList* must exist for as long as the picker
763 * that uses it, because the ModestSelectorPicker uses the ID opaquely,
764 * so it can't know how to manage its memory. */
765 priv->from_field = modest_selector_picker_new (MODEST_EDITABLE_SIZE,
766 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL,
768 modest_maemo_utils_set_hbutton_layout (title_size_group, value_size_group,
769 _("mail_va_from"), priv->from_field);
771 priv->to_field = modest_recpt_editor_new ();
772 priv->cc_field = modest_recpt_editor_new ();
773 priv->bcc_field = modest_recpt_editor_new ();
774 subject_box = gtk_hbox_new (FALSE, 0);
775 priv->priority_icon = gtk_image_new ();
776 gtk_box_pack_start (GTK_BOX (subject_box), priv->priority_icon, FALSE, FALSE, 0);
777 priv->subject_field = hildon_entry_new (MODEST_EDITABLE_SIZE);
778 gtk_entry_set_max_length (GTK_ENTRY (priv->subject_field) ,SUBJECT_MAX_LENGTH);
779 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
780 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
781 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
782 gtk_box_pack_start (GTK_BOX (subject_box), priv->subject_field, TRUE, TRUE, 0);
783 priv->add_attachment_button = gtk_button_new ();
784 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
785 gtk_button_set_relief (GTK_BUTTON (priv->add_attachment_button), GTK_RELIEF_NONE);
786 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
787 gtk_button_set_alignment (GTK_BUTTON (priv->add_attachment_button), 1.0, 0.5);
788 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, HILDON_ICON_SIZE_FINGER);
789 gtk_container_add (GTK_CONTAINER (priv->add_attachment_button), attachment_icon);
790 gtk_box_pack_start (GTK_BOX (subject_box), priv->add_attachment_button, FALSE, FALSE, 0);
791 priv->attachments_view = modest_attachments_view_new (NULL);
793 priv->header_box = gtk_vbox_new (FALSE, 0);
795 to_caption = modest_maemo_utils_create_captioned_with_size_type
796 (title_size_group, value_size_group,
797 _("mail_va_to"), FALSE, priv->to_field,
798 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
799 priv->cc_caption = modest_maemo_utils_create_captioned_with_size_type
800 (title_size_group, value_size_group,
801 _("mail_va_cc"), FALSE, priv->cc_field,
802 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
803 priv->bcc_caption = modest_maemo_utils_create_captioned_with_size_type
804 (title_size_group, value_size_group,
805 _("mail_va_hotfix1"), FALSE, priv->bcc_field,
806 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
807 subject_caption = modest_maemo_utils_create_captioned (title_size_group, value_size_group,
808 _("mail_va_subject"), FALSE, subject_box);
809 priv->attachments_caption = modest_maemo_utils_create_captioned_with_size_type (title_size_group, value_size_group,
810 _("mail_va_attachment"),
812 priv->attachments_view,
813 HILDON_SIZE_AUTO_WIDTH |
814 HILDON_SIZE_AUTO_HEIGHT);
815 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), value_size_group); */
816 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), value_size_group); */
817 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), value_size_group); */
818 g_object_unref (title_size_group);
819 g_object_unref (value_size_group);
821 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->from_field, FALSE, FALSE, 0);
822 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
823 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
824 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
825 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
826 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
827 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
829 init_wp_text_view_style ();
831 priv->msg_body = wp_text_view_new ();
834 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
835 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
836 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
837 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
838 #if (GTK_MINOR_VERSION >= 10)
839 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
840 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
842 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
843 deserialize_type, TRUE);
845 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
847 priv->find_toolbar = hildon_find_toolbar_new (NULL);
848 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
850 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
852 priv->pannable = hildon_pannable_area_new ();
854 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
856 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
857 priv->frame = gtk_frame_new (NULL);
858 gtk_box_pack_start (GTK_BOX(main_vbox), priv->frame, TRUE, TRUE, 0);
860 hildon_pannable_area_add_with_viewport (HILDON_PANNABLE_AREA (priv->pannable), main_vbox);
861 gtk_container_set_focus_vadjustment (GTK_CONTAINER (main_vbox),
862 hildon_pannable_area_get_vadjustment (HILDON_PANNABLE_AREA (priv->pannable)));
863 gtk_widget_show_all (GTK_WIDGET(priv->pannable));
865 window_box = gtk_vbox_new (FALSE, 0);
866 gtk_container_add (GTK_CONTAINER(obj), window_box);
868 gtk_box_pack_start (GTK_BOX (window_box), priv->pannable, TRUE, TRUE, 0);
870 gtk_container_add (GTK_CONTAINER (priv->frame), priv->msg_body);
872 /* Set window icon */
873 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
875 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
876 g_object_unref (window_icon);
881 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
883 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
885 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
886 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
887 priv->clipboard_change_handler_id))
888 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
889 priv->clipboard_change_handler_id);
890 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
891 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
892 priv->default_clipboard_change_handler_id))
893 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
894 priv->default_clipboard_change_handler_id);
896 if (priv->account_removed_handler_id &&
897 g_signal_handler_is_connected (modest_runtime_get_account_store (),
898 priv->account_removed_handler_id))
899 g_signal_handler_disconnect(modest_runtime_get_account_store (),
900 priv->account_removed_handler_id);
904 modest_msg_edit_window_finalize (GObject *obj)
906 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
908 /* Sanity check: shouldn't be needed, the window mgr should
909 call this function before */
910 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
912 if (priv->font_dialog != NULL) {
913 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
916 if (priv->clipboard_text != NULL) {
917 g_free (priv->clipboard_text);
918 priv->clipboard_text = NULL;
921 if (priv->draft_msg != NULL) {
922 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
923 if (TNY_IS_HEADER (header)) {
924 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
925 modest_window_mgr_unregister_header (mgr, header);
927 g_object_unref (priv->draft_msg);
928 priv->draft_msg = NULL;
930 if (priv->outbox_msg != NULL) {
931 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
932 if (TNY_IS_HEADER (header)) {
933 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
934 modest_window_mgr_unregister_header (mgr, header);
936 g_object_unref (priv->outbox_msg);
937 priv->outbox_msg = NULL;
939 if (priv->correct_scroll_idle > 0) {
940 g_source_remove (priv->correct_scroll_idle);
941 priv->correct_scroll_idle = 0;
943 if (priv->scroll_drag_timeout_id > 0) {
944 g_source_remove (priv->scroll_drag_timeout_id);
945 priv->scroll_drag_timeout_id = 0;
947 if (priv->clipboard_owner_idle > 0) {
948 g_source_remove (priv->clipboard_owner_idle);
949 priv->clipboard_owner_idle = 0;
951 if (priv->original_account_name)
952 g_free (priv->original_account_name);
953 g_free (priv->msg_uid);
954 g_free (priv->last_search);
955 g_slist_free (priv->font_items_group);
956 g_slist_free (priv->size_items_group);
957 g_object_unref (priv->attachments);
958 g_object_unref (priv->images);
960 /* This had to stay alive for as long as the picker that used it: */
961 modest_pair_list_free (priv->from_field_protos);
963 G_OBJECT_CLASS(parent_class)->finalize (obj);
967 pixbuf_from_stream (TnyStream *stream, const gchar *mime_type, guint64 *stream_size)
969 GdkPixbufLoader *loader;
975 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
977 if (loader == NULL) {
983 tny_stream_reset (TNY_STREAM (stream));
984 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
985 GError *error = NULL;
986 unsigned char read_buffer[128];
988 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
990 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
992 g_error_free (error);
997 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
999 g_object_ref (pixbuf);
1000 gdk_pixbuf_loader_close (loader, NULL);
1001 g_object_unref (loader);
1006 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1007 GdkPixbuf *new_pixbuf;
1009 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1010 gdk_pixbuf_get_width (pixbuf);
1011 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1012 g_object_unref (pixbuf);
1013 pixbuf = new_pixbuf;
1017 *stream_size = size;
1023 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1025 ModestMsgEditWindowPrivate *priv;
1028 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1030 for (iter = tny_list_create_iterator (attachments);
1031 !tny_iterator_is_done (iter);
1032 tny_iterator_next (iter)) {
1033 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1034 const gchar *cid = tny_mime_part_get_content_id (part);
1035 const gchar *mime_type = tny_mime_part_get_content_type (part);
1036 if ((cid != NULL)&&(mime_type != NULL)) {
1037 guint64 stream_size;
1038 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1039 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
1042 g_object_unref (stream);
1044 if (pixbuf != NULL) {
1045 priv->images_count ++;
1046 priv->images_size += stream_size;
1047 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1048 g_object_unref (pixbuf);
1051 g_object_unref (part);
1053 g_object_unref (iter);
1057 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1059 TnyMimePart *parent = NULL;
1060 const gchar *content_type = NULL;
1061 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1063 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1065 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1066 parent = g_object_ref (msg);
1067 } else if (content_type && !g_strcasecmp (content_type, "multipart/mixed")) {
1068 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1071 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1072 iter = tny_list_create_iterator (parts);
1073 while (!tny_iterator_is_done (iter)) {
1075 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1076 content_type = tny_mime_part_get_content_type (part);
1077 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1081 g_object_unref (part);
1083 tny_iterator_next (iter);
1085 g_object_unref (iter);
1086 g_object_unref (parts);
1089 if (parent != NULL) {
1090 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1093 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1094 iter = tny_list_create_iterator (parts);
1095 while (!tny_iterator_is_done (iter)) {
1097 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1098 content_type = tny_mime_part_get_content_type (part);
1099 if (content_type && g_str_has_prefix (content_type, "image/")) {
1100 tny_list_prepend (priv->images, (GObject *) part);
1102 g_object_unref (part);
1103 tny_iterator_next (iter);
1105 g_object_unref (iter);
1106 g_object_unref (parts);
1107 g_object_unref (parent);
1112 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1115 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1117 for (iter = tny_list_create_iterator (attachments) ;
1118 !tny_iterator_is_done (iter);
1119 tny_iterator_next (iter)) {
1120 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1121 const gchar *cid = tny_mime_part_get_content_id (part);
1123 char *invalid = NULL;
1124 gint int_cid = strtol (cid, &invalid, 10);
1125 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1126 priv->next_cid = int_cid + 1;
1129 g_object_unref (part);
1131 g_object_unref (iter);
1135 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1138 gchar *to, *cc, *bcc, *subject;
1140 ModestMsgEditWindowPrivate *priv;
1141 ModestWindowPrivate *parent_priv;
1143 TnyHeaderFlags priority_flags;
1144 TnyFolder *msg_folder;
1145 gboolean is_html = FALSE;
1146 gboolean field_view_set;
1148 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1149 g_return_if_fail (TNY_IS_MSG (msg));
1151 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1152 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1154 header = tny_msg_get_header (msg);
1155 to = tny_header_dup_to (header);
1156 cc = tny_header_dup_cc (header);
1157 bcc = tny_header_dup_bcc (header);
1158 subject = tny_header_dup_subject (header);
1159 priority_flags = tny_header_get_priority (header);
1162 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
1164 field_view_set = TRUE;
1166 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
1167 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1168 gtk_widget_show (priv->cc_caption);
1169 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1170 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1171 gtk_widget_hide (priv->cc_caption);
1172 field_view_set = FALSE;
1174 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button), field_view_set);
1176 field_view_set = TRUE;
1178 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
1179 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1180 gtk_widget_show (priv->bcc_caption);
1181 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1182 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1183 gtk_widget_hide (priv->bcc_caption);
1184 field_view_set = FALSE;
1186 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button), field_view_set);
1190 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1191 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1194 update_window_title (self);
1196 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1197 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1199 if ((body == NULL)||(body[0] == '\0')) {
1201 body = modest_text_utils_convert_to_html ("");
1204 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1205 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1208 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1211 /* Add attachments to the view */
1212 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1213 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1214 if (tny_list_get_length (priv->attachments) == 0) {
1215 gtk_widget_hide (priv->attachments_caption);
1217 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1218 gtk_widget_show_all (priv->attachments_caption);
1220 get_related_images (self, msg);
1221 update_next_cid (self, priv->attachments);
1222 update_next_cid (self, priv->images);
1223 replace_with_images (self, priv->images);
1225 if (preserve_is_rich && !is_html) {
1226 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1227 /* Get the default format required from configuration */
1228 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1229 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1232 /* Set the default focus depending on having already a To: field or not */
1233 if ((!to)||(*to == '\0')) {
1234 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1236 gtk_widget_grab_focus (priv->msg_body);
1239 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1241 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1242 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1244 modest_msg_edit_window_set_modified (self, FALSE);
1246 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1247 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1248 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1249 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1251 if (priv->msg_uid) {
1252 g_free (priv->msg_uid);
1253 priv->msg_uid = NULL;
1256 /* we should set a reference to the incoming message if it is a draft */
1257 msg_folder = tny_msg_get_folder (msg);
1259 if (modest_tny_folder_is_local_folder (msg_folder)) {
1260 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1261 if (type == TNY_FOLDER_TYPE_INVALID)
1262 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1264 if (type == TNY_FOLDER_TYPE_DRAFTS)
1265 priv->draft_msg = g_object_ref(msg);
1266 if (type == TNY_FOLDER_TYPE_OUTBOX)
1267 priv->outbox_msg = g_object_ref(msg);
1268 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1270 g_object_unref (msg_folder);
1280 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
1283 GList *item_children, *node;
1284 GtkWidget *bin_child;
1286 bin_child = gtk_bin_get_child (GTK_BIN(item));
1288 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
1290 for (node = item_children; node != NULL; node = g_list_next (node)) {
1291 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
1292 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
1295 g_list_free (item_children);
1299 menu_tool_button_dont_expand (GtkMenuToolButton *item)
1302 GList *item_children, *node;
1304 box = gtk_bin_get_child (GTK_BIN (item));
1305 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
1306 item_children = gtk_container_get_children (GTK_CONTAINER (box));
1308 for (node = item_children; node != NULL; node = g_list_next (node)) {
1309 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
1310 if (GTK_IS_TOGGLE_BUTTON (node->data))
1311 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
1312 else if (GTK_IS_BUTTON (node->data))
1313 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
1315 g_list_free (item_children);
1320 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1322 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1323 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1324 GtkWidget *placeholder;
1325 GtkWidget *tool_item;
1330 GtkWidget *sizes_menu;
1331 GtkWidget *fonts_menu;
1332 GSList *radio_group = NULL;
1333 GSList *node = NULL;
1337 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1338 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1340 /* Font color placeholder */
1341 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1342 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1345 priv->font_color_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1346 priv->font_color_button = hildon_color_button_new ();
1347 GTK_WIDGET_UNSET_FLAGS (priv->font_color_toolitem, GTK_CAN_FOCUS);
1348 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1349 gtk_container_add (GTK_CONTAINER (priv->font_color_toolitem), priv->font_color_button);
1350 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1351 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1352 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->font_color_toolitem), insert_index);
1353 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1355 G_CALLBACK (modest_msg_edit_window_color_button_change),
1358 /* Font size and face placeholder */
1359 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1360 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1362 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1363 priv->size_tool_button_label = gtk_label_new (NULL);
1364 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1365 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1366 size_text,"</span>", NULL);
1367 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1369 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
1370 sizes_menu = gtk_menu_new ();
1371 priv->size_items_group = NULL;
1373 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1374 GtkWidget *size_menu_item;
1376 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1377 size_menu_item = gtk_radio_menu_item_new_with_label (radio_group, size_text);
1378 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (size_menu_item));
1379 gtk_menu_shell_append (GTK_MENU_SHELL (sizes_menu), size_menu_item);
1380 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (size_menu_item), (wp_font_size[size_index] == 12));
1381 gtk_widget_show (size_menu_item);
1383 priv->size_items_group = g_slist_prepend (priv->size_items_group, size_menu_item);
1387 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1388 GtkWidget *item = (GtkWidget *) node->data;
1389 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_size_change),
1393 priv->size_items_group = g_slist_reverse (priv->size_items_group);
1394 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), sizes_menu);
1395 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1396 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1397 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1398 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1399 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1400 priv->font_size_toolitem = tool_item;
1403 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1404 priv->font_tool_button_label = gtk_label_new (NULL);
1405 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1406 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1408 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
1409 fonts_menu = gtk_menu_new ();
1410 priv->font_items_group = NULL;
1412 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1413 GtkWidget *font_menu_item;
1414 GtkWidget *child_label;
1416 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
1417 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
1418 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
1419 wp_get_font_name (font_index), "</span>", NULL);
1420 gtk_label_set_markup (GTK_LABEL (child_label), markup);
1423 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
1424 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
1425 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
1426 gtk_widget_show (font_menu_item);
1428 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
1431 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1432 GtkWidget *item = (GtkWidget *) node->data;
1433 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
1436 priv->font_items_group = g_slist_reverse (priv->font_items_group);
1437 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
1438 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1439 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1440 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1441 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1442 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1443 priv->font_face_toolitem = tool_item;
1445 /* Set expand and homogeneous for remaining items */
1446 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
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/ActionsBold");
1450 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1451 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1452 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1453 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1454 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1456 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1457 will not show the tool items added to the placeholders) */
1458 gtk_widget_show_all (parent_priv->toolbar);
1460 /* Set the no show all *after* showing all items. We do not
1461 want the toolbar to be shown with a show all because it
1462 could go agains the gconf setting regarding showing or not
1463 the toolbar of the editor window */
1464 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1470 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, gboolean preserve_is_rich)
1473 ModestWindowPrivate *parent_priv;
1474 ModestMsgEditWindowPrivate *priv;
1475 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1476 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1477 ModestWindowMgr *mgr = NULL;
1479 g_return_val_if_fail (msg, NULL);
1480 g_return_val_if_fail (account_name, NULL);
1482 mgr = modest_runtime_get_window_mgr ();
1484 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1486 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1487 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1489 /* Menubar. Update the state of some toggles */
1490 priv->from_field_protos = get_transports ();
1491 modest_selector_picker_set_pair_list (MODEST_SELECTOR_PICKER (priv->from_field), priv->from_field_protos);
1492 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1493 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1495 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1496 hildon_touch_selector_get_current_text
1497 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1498 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1499 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1502 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1504 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1506 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1508 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1510 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1511 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1512 /* Add common dimming rules */
1513 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1514 modest_msg_edit_window_toolbar_dimming_entries,
1515 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1516 MODEST_WINDOW (obj));
1517 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_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_size_toolitem,
1521 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1522 MODEST_WINDOW (obj));
1523 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1524 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1525 MODEST_WINDOW (obj));
1526 /* Insert dimming rules group for this window */
1527 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1528 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1530 /* Setup app menu */
1531 setup_menu (MODEST_MSG_EDIT_WINDOW (obj));
1533 /* Checks the dimming rules */
1534 g_object_unref (toolbar_rules_group);
1535 g_object_unref (clipboard_rules_group);
1536 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1538 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1540 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1541 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1542 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1543 priv->update_caption_visibility = TRUE;
1545 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1547 /* Track account-removed signal, this window should be closed
1548 in the case we're creating a mail associated to the account
1550 priv->account_removed_handler_id =
1551 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1553 G_CALLBACK(on_account_removed),
1556 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1558 return (ModestWindow*) obj;
1562 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1564 GString **string_buffer = (GString **) user_data;
1566 *string_buffer = g_string_append (*string_buffer, buffer);
1572 * @result: A new string which should be freed with g_free().
1575 get_formatted_data (ModestMsgEditWindow *edit_window)
1577 ModestMsgEditWindowPrivate *priv;
1578 GString *string_buffer = g_string_new ("");
1580 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1582 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1584 modest_text_utils_hyperlinkify (string_buffer);
1586 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1588 return g_string_free (string_buffer, FALSE);
1593 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1596 const gchar *account_name;
1597 ModestMsgEditWindowPrivate *priv;
1598 TnyIterator *att_iter;
1600 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1602 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1604 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1605 g_return_val_if_fail (account_name, NULL);
1608 /* don't free these (except from) */
1609 data = g_slice_new0 (MsgData);
1610 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1612 data->account_name = g_strdup (account_name);
1613 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1614 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1615 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1616 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1617 if (priv->draft_msg) {
1618 data->draft_msg = g_object_ref (priv->draft_msg);
1619 } else if (priv->outbox_msg) {
1620 data->draft_msg = g_object_ref (priv->outbox_msg);
1622 data->draft_msg = NULL;
1625 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1627 gtk_text_buffer_get_bounds (buf, &b, &e);
1628 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1630 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1631 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1633 data->html_body = NULL;
1635 /* deep-copy the data */
1636 att_iter = tny_list_create_iterator (priv->attachments);
1637 data->attachments = NULL;
1638 while (!tny_iterator_is_done (att_iter)) {
1639 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1640 if (!(TNY_IS_MIME_PART(part))) {
1641 g_warning ("strange data in attachment list");
1642 g_object_unref (part);
1643 tny_iterator_next (att_iter);
1646 data->attachments = g_list_append (data->attachments,
1648 tny_iterator_next (att_iter);
1650 g_object_unref (att_iter);
1652 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1653 att_iter = tny_list_create_iterator (priv->images);
1654 data->images = NULL;
1655 while (!tny_iterator_is_done (att_iter)) {
1656 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1658 if (!(TNY_IS_MIME_PART(part))) {
1659 g_warning ("strange data in attachment list");
1660 g_object_unref (part);
1661 tny_iterator_next (att_iter);
1664 cid = tny_mime_part_get_content_id (part);
1666 gchar *image_tag_id;
1667 GtkTextTag *image_tag;
1669 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1670 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1671 g_free (image_tag_id);
1673 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1675 ((gtk_text_iter_has_tag (&iter, image_tag))||
1676 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1677 data->images = g_list_append (data->images,
1678 g_object_ref (part));
1680 g_object_unref (part);
1681 tny_iterator_next (att_iter);
1683 g_object_unref (att_iter);
1685 data->priority_flags = priv->priority_flags;
1692 unref_gobject (GObject *obj, gpointer data)
1694 if (!G_IS_OBJECT(obj))
1696 g_object_unref (obj);
1700 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1703 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1711 g_free (data->from);
1712 g_free (data->subject);
1713 g_free (data->plain_body);
1714 g_free (data->html_body);
1715 g_free (data->account_name);
1717 if (data->draft_msg != NULL) {
1718 g_object_unref (data->draft_msg);
1719 data->draft_msg = NULL;
1722 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1723 g_list_free (data->attachments);
1724 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1725 g_list_free (data->images);
1727 g_slice_free (MsgData, data);
1731 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1733 guint64 *parts_size)
1735 ModestMsgEditWindowPrivate *priv;
1737 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1739 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1741 /* TODO: add images */
1742 *parts_size += priv->images_size;
1743 *parts_count += priv->images_count;
1748 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1751 ModestMsgEditWindowPrivate *priv = NULL;
1752 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1754 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1756 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1758 return MODEST_MSG_EDIT_FORMAT_HTML;
1760 return MODEST_MSG_EDIT_FORMAT_TEXT;
1764 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1765 ModestMsgEditFormat format)
1767 ModestMsgEditWindowPrivate *priv;
1769 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1770 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1773 case MODEST_MSG_EDIT_FORMAT_HTML:
1774 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1776 case MODEST_MSG_EDIT_FORMAT_TEXT:
1777 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1780 g_return_if_reached ();
1784 ModestMsgEditFormatState *
1785 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1787 ModestMsgEditFormatState *format_state = NULL;
1788 ModestMsgEditWindowPrivate *priv;
1789 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1791 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1792 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1794 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1796 format_state = g_new0 (ModestMsgEditFormatState, 1);
1797 format_state->bold = buffer_format->bold&0x1;
1798 format_state->italics = buffer_format->italic&0x1;
1799 format_state->bullet = buffer_format->bullet&0x1;
1800 format_state->color = buffer_format->color;
1801 format_state->font_size = buffer_format->font_size;
1802 format_state->font_family = wp_get_font_name (buffer_format->font);
1803 format_state->justification = buffer_format->justification;
1804 g_free (buffer_format);
1806 return format_state;
1811 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1812 const ModestMsgEditFormatState *format_state)
1814 ModestMsgEditWindowPrivate *priv;
1815 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1816 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1817 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1818 g_return_if_fail (format_state != NULL);
1820 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1821 gtk_widget_grab_focus (priv->msg_body);
1822 buffer_format->bold = (format_state->bold != FALSE);
1823 buffer_format->italic = (format_state->italics != FALSE);
1824 buffer_format->color = format_state->color;
1825 buffer_format->font_size = format_state->font_size;
1826 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1827 buffer_format->justification = format_state->justification;
1828 buffer_format->bullet = format_state->bullet;
1830 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1832 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1833 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1834 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1835 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1836 buffer_format->cs.font = (buffer_format->font != current_format->font);
1837 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1838 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1840 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1841 if (buffer_format->cs.bold) {
1842 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
1843 GINT_TO_POINTER (buffer_format->bold&0x1));
1845 if (buffer_format->cs.italic) {
1846 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
1847 GINT_TO_POINTER (buffer_format->italic&0x1));
1849 if (buffer_format->cs.color) {
1850 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1851 GINT_TO_POINTER (&(buffer_format->color)));
1853 if (buffer_format->cs.font_size) {
1854 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1855 GINT_TO_POINTER (buffer_format->font_size));
1857 if (buffer_format->cs.justification) {
1858 switch (buffer_format->justification) {
1859 case GTK_JUSTIFY_LEFT:
1860 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
1861 GINT_TO_POINTER(TRUE));
1863 case GTK_JUSTIFY_CENTER:
1864 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
1865 GINT_TO_POINTER(TRUE));
1867 case GTK_JUSTIFY_RIGHT:
1868 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
1869 GINT_TO_POINTER(TRUE));
1876 if (buffer_format->cs.font) {
1877 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1878 GINT_TO_POINTER (buffer_format->font));
1880 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1881 if (buffer_format->cs.bullet) {
1882 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
1883 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
1885 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1887 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
1889 g_free (buffer_format);
1890 g_free (current_format);
1892 /* Check dimming rules */
1893 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1894 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1898 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1900 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1902 ModestWindowPrivate *parent_priv;
1903 ModestMsgEditWindowPrivate *priv;
1904 GtkWidget *new_size_menuitem;
1905 GtkWidget *new_font_menuitem;
1907 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1908 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1910 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1911 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu");
1912 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1913 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1915 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatPlainTextMenu");
1916 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1917 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1920 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1922 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1923 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1925 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1926 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1928 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
1929 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
1932 switch (buffer_format->justification)
1934 case GTK_JUSTIFY_LEFT:
1935 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
1937 case GTK_JUSTIFY_CENTER:
1938 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
1940 case GTK_JUSTIFY_RIGHT:
1941 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
1948 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
1950 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1951 G_CALLBACK (modest_msg_edit_window_color_button_change),
1953 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1954 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1955 G_CALLBACK (modest_msg_edit_window_color_button_change),
1958 new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group,
1959 buffer_format->font_size))->data);
1960 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1964 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1965 markup = g_strconcat ("<span font_family='Sans'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1966 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1968 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1969 G_CALLBACK (modest_msg_edit_window_size_change),
1971 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
1972 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
1973 G_CALLBACK (modest_msg_edit_window_size_change),
1977 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
1978 buffer_format->font))->data);
1979 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
1983 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
1984 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1985 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1987 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
1988 G_CALLBACK (modest_msg_edit_window_font_change),
1990 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
1991 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
1992 G_CALLBACK (modest_msg_edit_window_font_change),
1996 g_free (buffer_format);
2000 #ifdef MODEST_HILDON_VERSION_0
2002 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2005 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2006 ModestMsgEditWindowPrivate *priv;
2007 GtkWidget *dialog = NULL;
2009 GdkColor *new_color = NULL;
2011 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2012 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2014 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2015 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
2016 g_free (buffer_format);
2018 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2019 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2020 if (new_color != NULL) {
2021 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2022 (gpointer) new_color);
2025 gtk_widget_destroy (dialog);
2030 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2033 ModestMsgEditWindowPrivate *priv;
2034 GtkWidget *dialog = NULL;
2036 GdkColor *old_color = NULL;
2037 const GdkColor *new_color = NULL;
2039 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2040 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2042 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2043 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2045 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2046 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2047 if (new_color != NULL)
2048 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2050 gtk_widget_destroy (dialog);
2056 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2059 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2060 ModestMsgEditWindowPrivate *priv;
2061 GtkWidget *dialog = NULL;
2063 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2064 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2066 dialog = hildon_color_chooser_new ();
2067 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2068 g_free (buffer_format);
2070 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2072 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2073 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2076 gtk_widget_destroy (dialog);
2081 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2084 ModestMsgEditWindowPrivate *priv;
2085 GtkWidget *dialog = NULL;
2086 GdkColor *old_color = NULL;
2088 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2089 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2091 dialog = hildon_color_chooser_new ();
2092 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2094 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2096 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2097 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2099 gtk_widget_destroy (dialog);
2102 #endif /*!MODEST_HILDON_VERSION_0*/
2107 create_stream_for_uri (const gchar* uri)
2112 TnyStream *result = NULL;
2114 GnomeVFSHandle *handle = NULL;
2115 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2116 if (test == GNOME_VFS_OK) {
2117 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2118 /* Streams over OBEX (Bluetooth) are not seekable but
2119 * we expect them to be (we might need to read them
2120 * several times). So if this is a Bluetooth URI just
2121 * read the whole file into memory (this is not a fast
2122 * protocol so we can assume that these files are not
2123 * going to be very big) */
2124 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2125 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2126 TnyStream *memstream = tny_camel_mem_stream_new ();
2127 tny_stream_write_to_stream (vfssstream, memstream);
2128 g_object_unref (vfssstream);
2131 result = vfssstream;
2139 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2142 ModestMsgEditWindowPrivate *priv;
2143 GtkWidget *dialog = NULL;
2145 GSList *uris = NULL;
2146 GSList *uri_node = NULL;
2148 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2150 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2151 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2152 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2154 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2156 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2157 GTK_WINDOW (dialog), GTK_WINDOW (window));
2159 response = gtk_dialog_run (GTK_DIALOG (dialog));
2161 case GTK_RESPONSE_OK:
2162 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2167 gtk_widget_destroy (dialog);
2169 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2171 GnomeVFSHandle *handle = NULL;
2172 GnomeVFSResult result;
2173 GtkTextIter position;
2174 GtkTextMark *insert_mark;
2176 uri = (const gchar *) uri_node->data;
2177 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2178 if (result == GNOME_VFS_OK) {
2180 GnomeVFSFileInfo *info;
2181 gchar *filename, *basename, *escaped_filename;
2182 TnyMimePart *mime_part;
2184 const gchar *mime_type = NULL;
2185 GnomeVFSURI *vfs_uri;
2186 guint64 stream_size;
2188 gnome_vfs_close (handle);
2189 vfs_uri = gnome_vfs_uri_new (uri);
2191 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2192 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2193 g_free (escaped_filename);
2194 gnome_vfs_uri_unref (vfs_uri);
2195 info = gnome_vfs_file_info_new ();
2197 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2198 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2200 mime_type = gnome_vfs_file_info_get_mime_type (info);
2202 mime_part = tny_platform_factory_new_mime_part
2203 (modest_runtime_get_platform_factory ());
2205 TnyStream *stream = create_stream_for_uri (uri);
2207 if (stream == NULL) {
2209 modest_platform_information_banner (NULL, NULL, dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2211 g_object_unref (mime_part);
2212 gnome_vfs_file_info_unref (info);
2216 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2218 content_id = g_strdup_printf ("%d", priv->next_cid);
2219 tny_mime_part_set_content_id (mime_part, content_id);
2220 g_free (content_id);
2223 basename = g_path_get_basename (filename);
2224 tny_mime_part_set_filename (mime_part, basename);
2227 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
2229 if (pixbuf != NULL) {
2230 priv->images_size += stream_size;
2231 priv->images_count ++;
2232 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2233 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2234 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
2235 g_object_unref (pixbuf);
2238 tny_list_prepend (priv->images, (GObject *) mime_part);
2239 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2241 g_object_unref (mime_part);
2242 gnome_vfs_file_info_unref (info);
2251 on_attach_file_response (GtkDialog *dialog,
2255 GSList *uris = NULL;
2257 GnomeVFSFileSize total_size, allowed_size;
2258 ModestMsgEditWindow *window;
2259 ModestMsgEditWindowPrivate *priv;
2264 case GTK_RESPONSE_OK:
2265 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2271 window = MODEST_MSG_EDIT_WINDOW (user_data);
2272 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2274 /* allowed size is the maximum size - what's already there */
2275 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2276 &att_num, &att_size);
2277 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2280 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2282 const gchar *uri = (const gchar *) uri_node->data;
2285 modest_msg_edit_window_attach_file_one (window, uri, allowed_size);
2287 if (total_size > allowed_size) {
2288 g_warning ("%s: total size: %u",
2289 __FUNCTION__, (unsigned int)total_size);
2292 allowed_size -= total_size;
2294 g_slist_foreach (uris, (GFunc) g_free, NULL);
2295 g_slist_free (uris);
2297 gtk_widget_destroy (GTK_WIDGET (dialog));
2301 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2303 GtkWidget *dialog = NULL;
2304 ModestMsgEditWindowPrivate *priv;
2306 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2308 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2310 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2313 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window),
2314 GTK_FILE_CHOOSER_ACTION_OPEN);
2315 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2316 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2317 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2318 GTK_WINDOW (dialog), GTK_WINDOW (window));
2320 /* Connect to response & show */
2321 g_signal_connect (dialog, "response",
2322 G_CALLBACK (on_attach_file_response), window);
2323 gtk_widget_show (dialog);
2328 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2330 GnomeVFSFileSize allowed_size)
2333 GnomeVFSHandle *handle = NULL;
2334 ModestMsgEditWindowPrivate *priv;
2335 GnomeVFSResult result;
2336 GnomeVFSFileSize size = 0;
2337 g_return_val_if_fail (window, 0);
2338 g_return_val_if_fail (uri, 0);
2340 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2342 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2343 if (result == GNOME_VFS_OK) {
2344 TnyMimePart *mime_part;
2346 const gchar *mime_type = NULL;
2348 gchar *escaped_filename;
2351 GnomeVFSFileInfo *info;
2352 GnomeVFSURI *vfs_uri;
2354 gnome_vfs_close (handle);
2355 vfs_uri = gnome_vfs_uri_new (uri);
2358 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2359 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2360 g_free (escaped_filename);
2361 gnome_vfs_uri_unref (vfs_uri);
2363 info = gnome_vfs_file_info_new ();
2365 if (gnome_vfs_get_file_info (uri,
2367 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2369 mime_type = gnome_vfs_file_info_get_mime_type (info);
2370 mime_part = tny_platform_factory_new_mime_part
2371 (modest_runtime_get_platform_factory ());
2373 /* try to get the attachment's size; this may fail for weird
2374 * file systems, like obex, upnp... */
2375 if (allowed_size != 0 &&
2376 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2378 if (size > allowed_size) {
2379 modest_platform_information_banner (NULL, NULL,
2380 dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2384 g_warning ("%s: could not get attachment size", __FUNCTION__);
2386 stream = create_stream_for_uri (uri);
2388 if (stream == NULL) {
2390 modest_platform_information_banner (NULL, NULL, dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2392 g_object_unref (mime_part);
2393 gnome_vfs_file_info_unref (info);
2397 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2398 g_object_unref (stream);
2400 content_id = g_strdup_printf ("%d", priv->next_cid);
2401 tny_mime_part_set_content_id (mime_part, content_id);
2402 g_free (content_id);
2405 basename = g_path_get_basename (filename);
2406 tny_mime_part_set_filename (mime_part, basename);
2409 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2410 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2412 info->size == 0, info->size);
2413 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2414 gtk_widget_show_all (priv->attachments_caption);
2415 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2417 g_object_unref (mime_part);
2418 gnome_vfs_file_info_unref (info);
2425 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2428 ModestMsgEditWindowPrivate *priv;
2431 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2432 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2434 if (att_list == NULL) {
2435 att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2437 g_object_ref (att_list);
2440 if (tny_list_get_length (att_list) == 0) {
2441 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2443 gboolean dialog_response;
2444 gchar *message = NULL;
2445 gchar *filename = NULL;
2447 if (tny_list_get_length (att_list) == 1) {
2449 iter = tny_list_create_iterator (att_list);
2450 part = (TnyMimePart *) tny_iterator_get_current (iter);
2451 g_object_unref (iter);
2452 if (TNY_IS_MSG (part)) {
2453 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2455 filename = tny_header_dup_subject (header);
2456 g_object_unref (header);
2458 if (filename == NULL) {
2459 filename = g_strdup (_("mail_va_no_subject"));
2462 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2464 g_object_unref (part);
2466 filename = g_strdup ("");
2468 message = g_strdup_printf (ngettext("emev_nc_delete_attachment",
2469 "emev_nc_delete_attachments",
2470 tny_list_get_length (att_list)), filename);
2473 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
2477 if (dialog_response != GTK_RESPONSE_OK) {
2478 g_object_unref (att_list);
2482 for (iter = tny_list_create_iterator (att_list);
2483 !tny_iterator_is_done (iter);
2484 tny_iterator_next (iter)) {
2485 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2486 const gchar *att_id;
2487 tny_list_remove (priv->attachments, (GObject *) mime_part);
2489 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2491 if (tny_list_get_length (priv->attachments) == 0)
2492 gtk_widget_hide (priv->attachments_caption);
2493 att_id = tny_mime_part_get_content_id (mime_part);
2495 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2497 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2498 g_object_unref (mime_part);
2500 g_object_unref (iter);
2503 g_object_unref (att_list);
2505 /* if the last attachment has been removed, focus the Subject: field */
2506 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2507 gtk_widget_grab_focus (priv->subject_field);
2511 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2514 ModestMsgEditWindowPrivate *priv;
2515 GdkColor *new_color;
2516 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2518 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2519 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2522 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2524 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2526 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2528 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2533 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
2536 ModestMsgEditWindowPrivate *priv;
2537 gint new_size_index;
2538 ModestMsgEditWindow *window;
2541 window = MODEST_MSG_EDIT_WINDOW (userdata);
2542 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2543 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2545 if (gtk_check_menu_item_get_active (menu_item)) {
2547 WPTextBufferFormat format;
2549 memset (&format, 0, sizeof (format));
2550 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2552 label = gtk_bin_get_child (GTK_BIN (menu_item));
2554 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
2555 format.cs.font_size = TRUE;
2556 format.cs.text_position = TRUE;
2557 format.cs.font = TRUE;
2558 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
2559 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2561 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2562 GINT_TO_POINTER (wp_get_font_size_index (new_size_index, 12))))
2563 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2565 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2566 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
2567 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2573 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
2576 ModestMsgEditWindowPrivate *priv;
2577 gint new_font_index;
2578 ModestMsgEditWindow *window;
2581 window = MODEST_MSG_EDIT_WINDOW (userdata);
2582 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2583 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2585 if (gtk_check_menu_item_get_active (menu_item)) {
2588 label = gtk_bin_get_child (GTK_BIN (menu_item));
2590 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
2592 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2593 GINT_TO_POINTER(new_font_index)))
2594 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2596 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2597 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2598 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2604 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2607 ModestMsgEditWindowPrivate *priv = NULL;
2608 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2610 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2611 if (!priv->update_caption_visibility)
2614 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2616 gtk_widget_show (priv->cc_caption);
2618 gtk_widget_hide (priv->cc_caption);
2620 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2624 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2627 ModestMsgEditWindowPrivate *priv = NULL;
2628 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2630 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2631 if (!priv->update_caption_visibility)
2634 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2636 gtk_widget_show (priv->bcc_caption);
2638 gtk_widget_hide (priv->bcc_caption);
2640 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2644 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2645 ModestRecptEditor *editor)
2647 ModestMsgEditWindowPrivate *priv;
2649 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2650 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2652 /* we check for low-mem; in that case, show a warning, and don't allow
2653 * for the addressbook
2655 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2658 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2660 if (editor == NULL) {
2661 GtkWidget *view_focus;
2662 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2664 /* This code should be kept in sync with ModestRecptEditor. The
2665 textview inside the recpt editor is the one that really gets the
2666 focus. As it's inside a scrolled window, and this one inside the
2667 hbox recpt editor inherits from, we'll need to go up in the
2668 hierarchy to know if the text view is part of the recpt editor
2669 or if it's a different text entry */
2671 if (gtk_widget_get_parent (view_focus)) {
2672 GtkWidget *first_parent;
2674 first_parent = gtk_widget_get_parent (view_focus);
2675 if (gtk_widget_get_parent (first_parent) &&
2676 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2677 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2682 editor = MODEST_RECPT_EDITOR (priv->to_field);
2686 modest_address_book_select_addresses (editor);
2691 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2693 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2695 modest_msg_edit_window_open_addressbook (window, NULL);
2699 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2700 gboolean show_toolbar)
2702 ModestWindowPrivate *parent_priv;
2704 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2705 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2707 /* We can not just use the code of
2708 modest_msg_edit_window_setup_toolbar because it has a
2709 mixture of both initialization and creation code. */
2711 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2713 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2717 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2718 TnyHeaderFlags priority_flags)
2720 ModestMsgEditWindowPrivate *priv;
2721 ModestWindowPrivate *parent_priv;
2723 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2725 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2726 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2728 if (priv->priority_flags != priority_flags) {
2729 GtkAction *priority_action = NULL;
2731 priv->priority_flags = priority_flags;
2733 switch (priority_flags) {
2734 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2735 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2736 MODEST_HEADER_ICON_HIGH,
2737 HILDON_ICON_SIZE_XSMALL);
2738 gtk_widget_show (priv->priority_icon);
2739 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2740 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2742 case TNY_HEADER_FLAG_LOW_PRIORITY:
2743 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2744 MODEST_HEADER_ICON_LOW,
2745 HILDON_ICON_SIZE_XSMALL);
2746 gtk_widget_show (priv->priority_icon);
2747 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2748 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2751 gtk_widget_hide (priv->priority_icon);
2752 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2753 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2756 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2757 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2762 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2765 ModestMsgEditWindowPrivate *priv;
2766 ModestWindowPrivate *parent_priv;
2767 gint current_format;
2769 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2771 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2772 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2774 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2775 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2777 if (current_format != file_format) {
2778 switch (file_format) {
2779 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2780 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2781 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
2783 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2787 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2788 response = gtk_dialog_run (GTK_DIALOG (dialog));
2789 gtk_widget_destroy (dialog);
2790 if (response == GTK_RESPONSE_OK) {
2791 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2793 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
2794 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
2799 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2800 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2801 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2806 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2809 ModestMsgEditWindowPrivate *priv;
2810 WPTextBufferFormat oldfmt, fmt;
2811 gint old_position = 0;
2815 GdkColor *color = NULL;
2816 gboolean bold, bold_set, italic, italic_set;
2817 gboolean underline, underline_set;
2818 gboolean strikethrough, strikethrough_set;
2819 gboolean position_set;
2820 gboolean font_size_set, font_set, color_set;
2823 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2824 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2826 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2827 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
2828 GTK_WINDOW(dialog), GTK_WINDOW (window));
2830 /* First we get the currently selected font information */
2831 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2833 switch (oldfmt.text_position) {
2834 case TEXT_POSITION_NORMAL:
2837 case TEXT_POSITION_SUPERSCRIPT:
2845 g_object_set (G_OBJECT (dialog),
2846 "bold", oldfmt.bold != FALSE,
2847 "bold-set", !oldfmt.cs.bold,
2848 "underline", oldfmt.underline != FALSE,
2849 "underline-set", !oldfmt.cs.underline,
2850 "italic", oldfmt.italic != FALSE,
2851 "italic-set", !oldfmt.cs.italic,
2852 "strikethrough", oldfmt.strikethrough != FALSE,
2853 "strikethrough-set", !oldfmt.cs.strikethrough,
2854 "color", &oldfmt.color,
2855 "color-set", !oldfmt.cs.color,
2856 "size", wp_font_size[oldfmt.font_size],
2857 "size-set", !oldfmt.cs.font_size,
2858 "position", old_position,
2859 "position-set", !oldfmt.cs.text_position,
2860 "family", wp_get_font_name (oldfmt.font),
2861 "family-set", !oldfmt.cs.font,
2864 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2865 GTK_WINDOW (dialog), GTK_WINDOW (window));
2866 gtk_widget_show_all (dialog);
2867 priv->font_dialog = dialog;
2868 response = gtk_dialog_run (GTK_DIALOG (dialog));
2869 priv->font_dialog = NULL;
2870 if (response == GTK_RESPONSE_OK) {
2872 g_object_get( dialog,
2874 "bold-set", &bold_set,
2875 "underline", &underline,
2876 "underline-set", &underline_set,
2878 "italic-set", &italic_set,
2879 "strikethrough", &strikethrough,
2880 "strikethrough-set", &strikethrough_set,
2882 "color-set", &color_set,
2884 "size-set", &font_size_set,
2885 "family", &font_name,
2886 "family-set", &font_set,
2887 "position", &position,
2888 "position-set", &position_set,
2893 if (response == GTK_RESPONSE_OK) {
2894 memset(&fmt, 0, sizeof(fmt));
2900 fmt.italic = italic;
2901 fmt.cs.italic = TRUE;
2903 if (underline_set) {
2904 fmt.underline = underline;
2905 fmt.cs.underline = TRUE;
2907 if (strikethrough_set) {
2908 fmt.strikethrough = strikethrough;
2909 fmt.cs.strikethrough = TRUE;
2914 ? TEXT_POSITION_NORMAL
2915 : ( ( position == 1 )
2916 ? TEXT_POSITION_SUPERSCRIPT
2917 : TEXT_POSITION_SUBSCRIPT );
2918 fmt.cs.text_position = TRUE;
2919 fmt.font_size = oldfmt.font_size;
2923 fmt.cs.color = TRUE;
2926 fmt.font = wp_get_font_index(font_name,
2931 if (font_size_set) {
2932 fmt.cs.font_size = TRUE;
2933 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
2935 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2936 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2938 gtk_widget_destroy (dialog);
2940 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2944 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2946 ModestMsgEditWindowPrivate *priv;
2948 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2949 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2951 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2953 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2954 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2958 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
2960 ModestMsgEditWindowPrivate *priv;
2962 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2963 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2965 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
2967 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2968 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2973 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
2975 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2977 priv->can_undo = can_undo;
2981 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
2983 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2985 priv->can_redo = can_redo;
2989 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
2991 ModestMsgEditWindowPrivate *priv;
2992 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2993 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2995 return priv->can_undo;
2999 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3001 ModestMsgEditWindowPrivate *priv;
3002 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3003 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3005 return priv->can_redo;
3010 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3013 GtkTextIter match_start, match_end;
3015 if (image_id == NULL)
3018 gtk_text_buffer_get_start_iter (buffer, &iter);
3020 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3021 GSList *tags = gtk_text_iter_get_tags (&match_start);
3023 for (node = tags; node != NULL; node = g_slist_next (node)) {
3024 GtkTextTag *tag = (GtkTextTag *) node->data;
3025 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3026 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3027 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3029 offset = gtk_text_iter_get_offset (&match_start);
3030 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3031 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3035 gtk_text_iter_forward_char (&iter);
3040 message_is_empty (ModestMsgEditWindow *window)
3042 ModestMsgEditWindowPrivate *priv = NULL;
3044 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3045 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3047 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3048 * so we can ignore markup.
3050 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3053 count = gtk_text_buffer_get_char_count (buf);
3059 msg_body_focus (GtkWidget *focus,
3060 GdkEventFocus *event,
3064 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3065 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3066 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3071 recpt_field_changed (GtkTextBuffer *buffer,
3072 ModestMsgEditWindow *editor)
3074 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3075 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3079 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3081 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3082 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3086 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3089 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3090 GtkTextBuffer *buffer;
3092 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3093 gtk_text_buffer_set_modified (buffer, modified);
3094 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3095 gtk_text_buffer_set_modified (buffer, modified);
3096 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3097 gtk_text_buffer_set_modified (buffer, modified);
3098 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3102 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3104 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3105 const char *account_name;
3106 GtkTextBuffer *buffer;
3108 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3109 if (gtk_text_buffer_get_modified (buffer))
3111 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3112 if (gtk_text_buffer_get_modified (buffer))
3114 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3115 if (gtk_text_buffer_get_modified (buffer))
3117 if (gtk_text_buffer_get_modified (priv->text_buffer))
3119 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3120 if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3131 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3133 ModestMsgEditWindowPrivate *priv = NULL;
3135 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3136 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3138 /* check if there's no recipient added */
3139 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3140 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3141 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3142 /* no recipient contents, then select contacts */
3143 modest_msg_edit_window_open_addressbook (window, NULL);
3147 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3148 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3151 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3152 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3155 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3156 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3160 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3161 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3162 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3169 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3170 ModestMsgEditWindow *window)
3172 modest_msg_edit_window_offer_attach_file (window);
3176 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3178 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3180 return priv->clipboard_text;
3184 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3186 ModestMsgEditWindow *window)
3188 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3189 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3191 if (!GTK_WIDGET_VISIBLE (window))
3194 g_object_ref (window);
3195 text = gtk_clipboard_wait_for_text (selection_clipboard);
3197 if (priv->clipboard_text != NULL) {
3198 g_free (priv->clipboard_text);
3200 priv->clipboard_text = text;
3202 if (GTK_WIDGET_VISIBLE (window)) {
3203 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3205 g_object_unref (window);
3208 static gboolean clipboard_owner_change_idle (gpointer userdata)
3210 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3211 ModestMsgEditWindowPrivate *priv;
3213 gdk_threads_enter ();
3214 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3215 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3217 priv->clipboard_owner_idle = 0;
3218 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3219 gdk_threads_leave ();
3225 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3227 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3228 if (priv->clipboard_owner_idle == 0) {
3229 priv->clipboard_owner_idle = g_idle_add (clipboard_owner_change_idle, window);
3234 subject_field_move_cursor (GtkEntry *entry,
3235 GtkMovementStep step,
3240 if (!GTK_WIDGET_VISIBLE (window))
3243 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3247 update_window_title (ModestMsgEditWindow *window)
3249 ModestMsgEditWindowPrivate *priv = NULL;
3250 const gchar *subject;
3252 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3253 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3254 if (subject == NULL || subject[0] == '\0')
3255 subject = _("mail_va_new_email");
3257 gtk_window_set_title (GTK_WINDOW (window), subject);
3262 subject_field_changed (GtkEditable *editable,
3263 ModestMsgEditWindow *window)
3265 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3266 update_window_title (window);
3267 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3268 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3269 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3273 subject_field_insert_text (GtkEditable *editable,
3275 gint new_text_length,
3277 ModestMsgEditWindow *window)
3279 GString *result = g_string_new ("");
3281 gint result_len = 0;
3282 const gchar *entry_text = NULL;
3285 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3286 old_length = g_utf8_strlen (entry_text, -1);
3288 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3289 gunichar c = g_utf8_get_char_validated (current, 8);
3290 /* Invalid unichar, stop */
3296 result = g_string_append_unichar (result, c);
3300 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3301 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3304 /* Prevent endless recursion */
3305 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3306 g_signal_emit_by_name (editable, "insert-text",
3307 (gpointer) result->str, (gpointer) result->len,
3308 (gpointer) position, (gpointer) window);
3309 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3313 if (result_len + old_length > 1000) {
3314 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3315 dgettext("hildon-common-strings",
3316 "ckdg_ib_maximum_characters_reached"));
3318 g_string_free (result, TRUE);
3322 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3325 ModestMsgEditWindowPrivate *priv = NULL;
3327 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3328 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3330 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3333 gtk_widget_show_all (priv->find_toolbar);
3334 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3336 gtk_widget_hide_all (priv->find_toolbar);
3337 gtk_widget_grab_focus (priv->msg_body);
3342 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3344 GtkTextIter *match_start,
3345 GtkTextIter *match_end)
3347 GtkTextIter end_iter;
3348 gchar *str_casefold;
3351 gchar *range_casefold;
3354 gboolean result = FALSE;
3361 gtk_text_iter_forward_to_end (&end_iter);
3363 str_casefold = g_utf8_casefold (str, -1);
3364 str_chars_n = strlen (str);
3366 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3367 range_casefold = g_utf8_casefold (range_text, -1);
3368 range_chars_n = strlen (range_casefold);
3370 if (range_chars_n < str_chars_n) {
3371 g_free (str_casefold);
3372 g_free (range_text);
3373 g_free (range_casefold);
3377 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3378 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3379 if (!g_utf8_collate (range_subtext, str_casefold)) {
3380 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3382 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3383 match_start, match_end, NULL);
3384 g_free (found_text);
3386 g_free (range_subtext);
3390 g_free (str_casefold);
3391 g_free (range_text);
3392 g_free (range_casefold);
3399 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3400 ModestMsgEditWindow *window)
3402 gchar *current_search = NULL;
3403 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3405 GtkTextIter selection_start, selection_end;
3406 GtkTextIter match_start, match_end;
3407 gboolean continue_search = FALSE;
3409 if (message_is_empty (window)) {
3410 g_free (priv->last_search);
3411 priv->last_search = NULL;
3412 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3416 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3417 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3418 g_free (current_search);
3419 g_free (priv->last_search);
3420 priv->last_search = NULL;
3421 /* Information banner about empty search */
3422 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-common-strings", "ecdg_ib_find_rep_enter_text"));
3426 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3427 continue_search = TRUE;
3429 g_free (priv->last_search);
3430 priv->last_search = g_strdup (current_search);
3433 if (continue_search) {
3434 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3435 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3436 &match_start, &match_end);
3438 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_search_complete"));
3440 GtkTextIter buffer_start;
3441 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3442 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3443 &match_start, &match_end);
3445 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_no_matches"));
3448 /* Mark as selected the string found in search */
3450 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3451 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3452 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3454 g_free (priv->last_search);
3455 priv->last_search = NULL;
3457 g_free (current_search);
3461 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3463 ModestMsgEditWindowPrivate *priv;
3465 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3470 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3473 ModestMsgEditWindowPrivate *priv;
3475 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3480 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3481 ModestMsgEditWindow *window)
3483 modest_msg_edit_window_toggle_find_toolbar (window, FALSE);
3487 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3490 ModestMsgEditWindowPrivate *priv;
3491 TnyHeader *header = NULL;
3493 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3494 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3496 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3497 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3499 if (priv->draft_msg != NULL) {
3500 g_object_unref (priv->draft_msg);
3503 if (draft != NULL) {
3504 g_object_ref (draft);
3505 header = tny_msg_get_header (draft);
3506 if (priv->msg_uid) {
3507 g_free (priv->msg_uid);
3508 priv->msg_uid = NULL;
3510 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3511 if (GTK_WIDGET_REALIZED (window)) {
3512 if (!modest_window_mgr_register_window (mgr, MODEST_WINDOW (window), NULL)) {
3513 gtk_widget_destroy (GTK_WIDGET (window));
3519 priv->draft_msg = draft;
3523 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3524 GtkTextIter *start, GtkTextIter *end,
3527 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3528 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3531 if (tag == NULL) return;
3532 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3533 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3534 replace_with_images (window, priv->images);
3539 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3542 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3544 g_return_if_fail (TNY_IS_MIME_PART (part));
3545 tny_list_prepend (priv->attachments, (GObject *) part);
3546 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3547 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3548 gtk_widget_show_all (priv->attachments_caption);
3549 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3553 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3555 ModestMsgEditWindowPrivate *priv;
3557 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3558 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3560 return priv->msg_uid;
3564 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3565 ModestMsgEditWindowWidgetType widget_type)
3567 ModestMsgEditWindowPrivate *priv;
3569 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3570 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3572 switch (widget_type) {
3573 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3574 return priv->msg_body;
3576 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3577 return priv->to_field;
3579 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3580 return priv->cc_field;
3582 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3583 return priv->bcc_field;
3585 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3586 return priv->subject_field;
3588 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3589 return priv->attachments_view;
3597 remove_tags (WPTextBuffer *buffer)
3599 GtkTextIter start, end;
3601 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3602 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3604 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3608 on_account_removed (TnyAccountStore *account_store,
3609 TnyAccount *account,
3612 /* Do nothing if it's a store account, because we use the
3613 transport to send the messages */
3614 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3615 const gchar *parent_acc = NULL;
3616 const gchar *our_acc = NULL;
3618 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3619 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3620 /* Close this window if I'm showing a message of the removed account */
3621 if (strcmp (parent_acc, our_acc) == 0)
3622 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3626 typedef struct _MessageSettingsHelper {
3627 ModestMsgEditWindow *window;
3628 GSList *priority_group;
3629 GSList *format_group;
3630 } MessageSettingsHelper;
3633 on_priority_toggle (GtkToggleButton *button,
3634 MessageSettingsHelper *helper)
3637 ModestMsgEditWindowPrivate *priv;
3639 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3640 if (gtk_toggle_button_get_active (button)) {
3642 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3643 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3644 if ((node_button != button) &&
3645 gtk_toggle_button_get_active (node_button)) {
3646 gtk_toggle_button_set_active (node_button, FALSE);
3649 if (priv->priority_flags != (TnyHeaderFlags) g_object_get_data (G_OBJECT (button), "priority"))
3650 modest_msg_edit_window_set_priority_flags (helper->window,
3652 g_object_get_data (G_OBJECT (button),
3656 gboolean found = FALSE;
3657 /* If no one is active, activate it again */
3658 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3659 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3660 if (gtk_toggle_button_get_active (node_button)) {
3666 gtk_toggle_button_set_active (button, TRUE);
3672 on_format_toggle (GtkToggleButton *button,
3673 MessageSettingsHelper *helper)
3676 ModestMsgEditWindowPrivate *priv;
3677 ModestMsgEditFormat old_format;
3679 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3680 old_format = modest_msg_edit_window_get_format (helper->window);
3681 if (gtk_toggle_button_get_active (button)) {
3683 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
3684 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3685 if ((node_button != button) &&
3686 gtk_toggle_button_get_active (node_button)) {
3687 gtk_toggle_button_set_active (node_button, FALSE);
3690 if (old_format != (ModestMsgEditFormat) g_object_get_data (G_OBJECT (button), "format")) {
3691 modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (helper->window),
3692 GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button), "file-format")));
3696 gboolean found = FALSE;
3697 /* If no one is active, activate it again */
3698 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
3699 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3700 if (gtk_toggle_button_get_active (node_button)) {
3706 gtk_toggle_button_set_active (button, TRUE);
3713 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
3717 GtkWidget *priority_hbox;
3718 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
3719 GtkWidget *captioned;
3720 GtkSizeGroup *title_sizegroup, *value_sizegroup;
3721 GtkWidget *format_hbox;
3722 GtkWidget *html_toggle, *text_toggle;
3723 ModestMsgEditWindowPrivate *priv;
3724 MessageSettingsHelper helper = {0,};
3726 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3727 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3728 helper.window = window;
3729 helper.priority_group = NULL;
3731 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3732 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3734 dialog = gtk_dialog_new ();
3735 vbox = gtk_vbox_new (FALSE, 0);
3736 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), vbox);
3737 gtk_widget_show (vbox);
3739 /* Priority toggles */
3740 priority_hbox = gtk_hbox_new (TRUE, 0);
3741 high_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3742 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
3743 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
3744 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
3745 medium_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3746 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
3747 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
3748 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
3749 low_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3750 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
3751 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
3752 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
3753 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, TRUE, TRUE, 0);
3754 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, TRUE, TRUE, 0);
3755 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, TRUE, TRUE, 0);
3756 gtk_widget_show_all (priority_hbox);
3757 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
3758 _("mcen_me_editor_message_priority"), FALSE, priority_hbox);
3759 gtk_widget_show (captioned);
3760 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
3762 /* format toggles */
3763 format_hbox = gtk_hbox_new (TRUE, 0);
3764 html_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3765 gtk_button_set_label (GTK_BUTTON (html_toggle), _("mcen_me_editor_formatted_text"));
3766 helper.format_group = g_slist_prepend (helper.format_group, html_toggle);
3767 g_object_set_data (G_OBJECT (html_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_HTML));
3768 g_object_set_data (G_OBJECT (html_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_FORMATTED_TEXT));
3769 text_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3770 gtk_button_set_label (GTK_BUTTON (text_toggle), _("mcen_me_editor_plain_text"));
3771 helper.format_group = g_slist_prepend (helper.format_group, text_toggle);
3772 g_object_set_data (G_OBJECT (text_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_TEXT));
3773 g_object_set_data (G_OBJECT (text_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_PLAIN_TEXT));
3774 gtk_box_pack_start (GTK_BOX (format_hbox), html_toggle, TRUE, TRUE, 0);
3775 gtk_box_pack_start (GTK_BOX (format_hbox), text_toggle, TRUE, TRUE, 0);
3776 gtk_widget_show_all (format_hbox);
3777 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
3778 _("mcen_me_editor_format"), FALSE, format_hbox);
3779 gtk_widget_show (captioned);
3780 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
3783 g_object_unref (title_sizegroup);
3784 g_object_unref (value_sizegroup);
3785 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_me_message_settings"));
3787 /* Set current values */
3788 switch (priv->priority_flags) {
3789 case TNY_HEADER_FLAG_HIGH_PRIORITY:
3790 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (high_toggle), TRUE);
3792 case TNY_HEADER_FLAG_LOW_PRIORITY:
3793 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (low_toggle), TRUE);
3796 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (medium_toggle), TRUE);
3800 switch (modest_msg_edit_window_get_format (window)) {
3801 case MODEST_MSG_EDIT_FORMAT_TEXT:
3802 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_toggle), TRUE);
3804 case MODEST_MSG_EDIT_FORMAT_HTML:
3806 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (html_toggle), TRUE);
3810 /* Signal connects */
3811 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3812 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3813 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3814 g_signal_connect (G_OBJECT (html_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
3815 g_signal_connect (G_OBJECT (text_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
3817 gtk_dialog_run (GTK_DIALOG (dialog));
3819 /* Read new values */
3821 gtk_widget_destroy (dialog);
3822 g_slist_free (helper.priority_group);
3826 static void on_message_settings (GtkAction *action,
3827 ModestMsgEditWindow *window)
3829 modest_msg_edit_window_show_msg_settings_dialog (window);
3833 on_cc_button_toggled (HildonCheckButton *button,
3834 ModestMsgEditWindow *window)
3836 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
3838 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
3839 hildon_check_button_get_active (button));
3843 on_bcc_button_toggled (HildonCheckButton *button,
3844 ModestMsgEditWindow *window)
3846 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
3848 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
3849 hildon_check_button_get_active (button));
3853 setup_menu (ModestMsgEditWindow *self)
3855 ModestMsgEditWindowPrivate *priv = NULL;
3857 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
3859 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3861 /* Settings menu buttons */
3862 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_checknames"), NULL,
3863 APP_MENU_CALLBACK (modest_ui_actions_on_check_names),
3865 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_undo"), "<Ctrl>z",
3866 APP_MENU_CALLBACK (modest_ui_actions_on_undo),
3867 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_undo));
3869 priv->cc_button = hildon_check_button_new (0);
3870 gtk_button_set_label (GTK_BUTTON (priv->cc_button), _("mcen_me_editor_showcc"));
3871 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button),
3873 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->cc_button),
3875 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
3876 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
3877 priv->bcc_button = hildon_check_button_new (0);
3878 gtk_button_set_label (GTK_BUTTON (priv->bcc_button), _("mcen_me_editor_showbcc"));
3879 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button),
3881 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->bcc_button),
3883 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
3884 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
3886 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_attach_inlineimage"), NULL,
3887 APP_MENU_CALLBACK (modest_ui_actions_on_insert_image),
3888 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_set_style));
3889 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_remove_attachments"), NULL,
3890 APP_MENU_CALLBACK (modest_ui_actions_on_remove_attachments),
3891 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
3892 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_message_settings"), NULL,
3893 APP_MENU_CALLBACK (on_message_settings),
3895 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_viewer_find"), "<Ctrl>f",
3896 APP_MENU_CALLBACK (modest_ui_actions_on_toggle_find_in_page),