1 /* Copyright (c) 2006, Nokia Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of the Nokia Corporation nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include <glib/gi18n.h>
33 #include <glib/gstdio.h>
35 #include <tny-account-store.h>
36 #include <tny-fs-stream.h>
37 #include <tny-vfs-stream.h>
38 #include <tny-camel-mem-stream.h>
42 #include <modest-account-mgr.h>
43 #include <modest-account-mgr-helpers.h>
45 #include <widgets/modest-msg-edit-window.h>
46 #include <modest-selector-picker.h>
47 #include <widgets/modest-recpt-editor.h>
48 #include <widgets/modest-attachments-view.h>
50 #include <modest-runtime.h>
52 #include "modest-platform.h"
53 #include "modest-icon-names.h"
54 #include "modest-widget-memory.h"
55 #include "modest-window-priv.h"
56 #include "modest-mail-operation.h"
57 #include "modest-tny-platform-factory.h"
58 #include "modest-tny-msg.h"
59 #include "modest-tny-folder.h"
60 #include "modest-tny-account.h"
61 #include "modest-address-book.h"
62 #include "modest-text-utils.h"
63 #include <tny-simple-list.h>
64 #include <wptextview.h>
65 #include <wptextbuffer.h>
66 #include <hildon/hildon-pannable-area.h>
67 #include "modest-msg-edit-window-ui-dimming.h"
69 #include "modest-hildon-includes.h"
70 #ifdef MODEST_HAVE_HILDON0_WIDGETS
71 #include <hildon-widgets/hildon-color-chooser.h>
73 #include "widgets/modest-msg-edit-window-ui.h"
74 #ifdef MODEST_HAVE_HILDON0_WIDGETS
75 #include <libgnomevfs/gnome-vfs-mime-utils.h>
77 #include <libgnomevfs/gnome-vfs-mime.h>
79 #include <modest-utils.h>
80 #include "modest-maemo-utils.h"
81 #include <modest-ui-constants.h>
84 #define DEFAULT_FONT_SIZE 3
85 #define DEFAULT_FONT 2
86 #define DEFAULT_SIZE_BUTTON_FONT_FAMILY "Sans"
87 #define DEFAULT_MAIN_VBOX_SPACING 6
88 #define SUBJECT_MAX_LENGTH 1000
89 #define IMAGE_MAX_WIDTH 560
90 #define DEFAULT_FONT_SCALE 1.5
91 #define ATTACHMENT_BUTTON_WIDTH 118
93 static gboolean is_wp_text_buffer_started = FALSE;
95 static void modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass);
96 static void modest_msg_edit_window_init (ModestMsgEditWindow *obj);
97 static void modest_msg_edit_window_finalize (GObject *obj);
99 static gboolean msg_body_focus (GtkWidget *focus, GdkEventFocus *event, gpointer userdata);
100 static void body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
101 static void recpt_field_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
103 static void text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window);
104 static void text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window);
105 static void text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window);
106 static void text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
107 GtkTextIter *start, GtkTextIter *end,
109 static void text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id);
110 static void subject_field_changed (GtkEditable *editable, ModestMsgEditWindow *window);
111 static void subject_field_insert_text (GtkEditable *editable,
113 gint new_text_length,
115 ModestMsgEditWindow *window);
116 static void modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
118 static void modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
120 static void modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
122 static void modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
124 static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
125 ModestRecptEditor *editor);
126 static void modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
127 ModestMsgEditWindow *window);
129 /* ModestWindow methods implementation */
130 static void modest_msg_edit_window_disconnect_signals (ModestWindow *window);
131 static void modest_msg_edit_window_show_toolbar (ModestWindow *window,
132 gboolean show_toolbar);
133 static void modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
135 ModestMsgEditWindow *window);
136 static void modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window);
137 static void subject_field_move_cursor (GtkEntry *entry,
138 GtkMovementStep step,
142 static void update_window_title (ModestMsgEditWindow *window);
145 static void modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
146 ModestMsgEditWindow *window);
147 static void modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
148 ModestMsgEditWindow *window);
149 static gboolean gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
151 GtkTextIter *match_start,
152 GtkTextIter *match_end);
154 static void remove_tags (WPTextBuffer *buffer);
156 static void on_account_removed (TnyAccountStore *account_store,
160 static void init_window (ModestMsgEditWindow *obj);
162 gboolean scroll_drag_timeout (gpointer userdata);
163 static void correct_scroll (ModestMsgEditWindow *w);
164 static void correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused);
165 static void text_buffer_end_user_action (GtkTextBuffer *buffer,
166 ModestMsgEditWindow *userdata);
167 static void text_buffer_mark_set (GtkTextBuffer *buffer,
170 ModestMsgEditWindow *userdata);
171 static void on_message_settings (GtkAction *action,
172 ModestMsgEditWindow *window);
173 static void setup_menu (ModestMsgEditWindow *self);
175 static void from_field_changed (HildonPickerButton *button,
176 ModestMsgEditWindow *self);
177 static void DEBUG_BUFFER (WPTextBuffer *buffer)
181 g_message ("BEGIN BUFFER OF SIZE %d", gtk_text_buffer_get_char_count (GTK_TEXT_BUFFER (buffer)));
183 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &iter);
184 while (!gtk_text_iter_is_end (&iter)) {
185 GString *output = g_string_new ("");
186 GSList *toggled_tags;
189 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
190 g_string_append_printf (output, "%d: CLOSED [ ", gtk_text_iter_get_offset (&iter));
191 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
192 GtkTextTag *tag = (GtkTextTag *) node->data;
194 g_object_get (G_OBJECT (tag), "name", &name, NULL);
195 output = g_string_append (output, name);
196 g_string_append (output, " ");
198 output = g_string_append (output, "] OPENED [ ");
199 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
200 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
201 GtkTextTag *tag = (GtkTextTag *) node->data;
203 g_object_get (G_OBJECT (tag), "name", &name, NULL);
204 output = g_string_append (output, name);
205 g_string_append (output, " ");
207 output = g_string_append (output, "]\n");
208 g_message ("%s", output->str);
209 g_string_free (output, TRUE);
210 gtk_text_iter_forward_to_tag_toggle (&iter, NULL);
212 g_message ("END BUFFER");
216 static const GtkActionEntry hildon2_msg_edit_action_entries [] = {
217 { "MessageSettings", NULL, N_("mcen_me_message_settings"), NULL, NULL, G_CALLBACK (on_message_settings)},
221 /* static gboolean */
222 /* on_key_pressed (GtkWidget *self, */
223 /* GdkEventKey *event, */
224 /* gpointer user_data); */
226 /* list my signals */
233 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
234 struct _ModestMsgEditWindowPrivate {
236 GtkWidget *header_box;
238 ModestPairList *from_field_protos;
239 GtkWidget *from_field;
240 gchar *last_from_account;
241 gchar *original_account_name;
245 GtkWidget *bcc_field;
246 GtkWidget *subject_field;
247 GtkWidget *attachments_view;
248 GtkWidget *priority_icon;
249 GtkWidget *subject_box;
250 GtkWidget *add_attachment_button;
252 GtkWidget *cc_caption;
253 GtkWidget *bcc_caption;
254 gboolean update_caption_visibility;
255 GtkWidget *attachments_caption;
257 GtkTextBuffer *text_buffer;
259 GtkWidget *font_size_toolitem;
260 GtkWidget *font_face_toolitem;
261 GtkWidget *font_color_button;
262 GtkWidget *font_color_toolitem;
263 GSList *font_items_group;
264 GtkWidget *font_tool_button_label;
265 GSList *size_items_group;
266 GtkWidget *size_tool_button_label;
268 GtkWidget *find_toolbar;
271 GtkWidget *font_dialog;
274 guint correct_scroll_idle;
275 guint scroll_drag_timeout_id;
279 TnyList *attachments;
284 TnyHeaderFlags priority_flags;
286 gboolean can_undo, can_redo;
287 gulong clipboard_change_handler_id;
288 gulong default_clipboard_change_handler_id;
289 gulong account_removed_handler_id;
290 guint clipboard_owner_idle;
291 gchar *clipboard_text;
300 GtkWidget *cc_button;
301 GtkWidget *bcc_button;
304 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
305 MODEST_TYPE_MSG_EDIT_WINDOW, \
306 ModestMsgEditWindowPrivate))
308 static GtkWindowClass *parent_class = NULL;
310 /* uncomment the following if you have defined any signals */
311 /* static guint signals[LAST_SIGNAL] = {0}; */
314 modest_msg_edit_window_get_type (void)
316 static GType my_type = 0;
318 static const GTypeInfo my_info = {
319 sizeof(ModestMsgEditWindowClass),
320 NULL, /* base init */
321 NULL, /* base finalize */
322 (GClassInitFunc) modest_msg_edit_window_class_init,
323 NULL, /* class finalize */
324 NULL, /* class data */
325 sizeof(ModestMsgEditWindow),
327 (GInstanceInitFunc) modest_msg_edit_window_init,
330 my_type = g_type_register_static (MODEST_TYPE_HILDON2_WINDOW,
331 "ModestMsgEditWindow",
339 save_state (ModestWindow *self)
341 modest_widget_memory_save (modest_runtime_get_conf(),
342 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
347 restore_settings (ModestMsgEditWindow *self)
349 ModestConf *conf = NULL;
351 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
353 conf = modest_runtime_get_conf ();
355 /* Dim at start clipboard actions */
356 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
357 gtk_action_set_sensitive (action, FALSE);
358 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
359 gtk_action_set_sensitive (action, FALSE);
360 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
361 gtk_action_set_sensitive (action, FALSE);
363 modest_widget_memory_restore (conf, G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
368 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
370 GObjectClass *gobject_class;
371 ModestWindowClass *modest_window_class;
372 gobject_class = (GObjectClass*) klass;
373 modest_window_class = (ModestWindowClass*) klass;
375 parent_class = g_type_class_peek_parent (klass);
376 gobject_class->finalize = modest_msg_edit_window_finalize;
378 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
379 modest_window_class->save_state_func = save_state;
380 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
382 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
386 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
388 ModestMsgEditWindowPrivate *priv;
389 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
391 priv->msg_body = NULL;
392 priv->from_field = NULL;
393 priv->to_field = NULL;
394 priv->cc_field = NULL;
395 priv->bcc_field = NULL;
396 priv->subject_field = NULL;
397 priv->attachments = TNY_LIST (tny_simple_list_new ());
398 priv->images = TNY_LIST (tny_simple_list_new ());
399 priv->images_size = 0;
400 priv->images_count = 0;
403 priv->cc_caption = NULL;
404 priv->bcc_caption = NULL;
405 priv->update_caption_visibility = FALSE;
407 priv->priority_flags = 0;
409 priv->find_toolbar = NULL;
410 priv->last_search = NULL;
412 priv->draft_msg = NULL;
413 priv->outbox_msg = NULL;
414 priv->msg_uid = NULL;
416 priv->can_undo = FALSE;
417 priv->can_redo = FALSE;
418 priv->clipboard_change_handler_id = 0;
419 priv->default_clipboard_change_handler_id = 0;
420 priv->account_removed_handler_id = 0;
421 priv->clipboard_owner_idle = 0;
422 priv->clipboard_text = NULL;
425 priv->scroll_drag_timeout_id = 0;
426 priv->correct_scroll_idle = 0;
427 priv->last_upper = 0.0;
429 priv->font_dialog = NULL;
430 priv->app_menu = NULL;
432 if (!is_wp_text_buffer_started) {
433 is_wp_text_buffer_started = TRUE;
434 wp_text_buffer_library_init ();
439 hildon_program_add_window (hildon_program_get_instance(),
445 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
447 static ModestPairList*
448 get_transports (void)
450 GSList *transports = NULL;
452 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
453 GSList *accounts = modest_account_mgr_account_names (account_mgr,
454 TRUE /* only enabled accounts. */);
456 GSList *cursor = accounts;
458 gchar *account_name = cursor->data;
459 gchar *from_string = NULL;
461 from_string = modest_account_mgr_get_from_string (account_mgr,
465 if (from_string && account_name) {
466 gchar *name = account_name;
467 ModestPair *pair = modest_pair_new ((gpointer) name,
468 (gpointer) from_string , TRUE);
469 transports = g_slist_prepend (transports, pair);
472 cursor = cursor->next;
474 g_slist_free (accounts); /* only free the accounts, not the elements,
475 * because they are used in the pairlist */
479 static void window_focus (GtkWindow *window,
483 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
487 scroll_drag_timeout (gpointer userdata)
489 ModestMsgEditWindow *win = (ModestMsgEditWindow *) userdata;
490 ModestMsgEditWindowPrivate *priv;
492 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(win);
494 correct_scroll_without_drag_check (win, TRUE);
496 priv->scroll_drag_timeout_id = 0;
502 correct_scroll_without_drag_check_idle (gpointer userdata)
504 ModestMsgEditWindow *w = (ModestMsgEditWindow *) userdata;
505 ModestMsgEditWindowPrivate *priv;
507 GdkRectangle rectangle;
512 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
514 if (!gtk_widget_is_focus (priv->msg_body))
517 insert = gtk_text_buffer_get_insert (priv->text_buffer);
518 gtk_text_buffer_get_iter_at_mark (priv->text_buffer, &iter, insert);
520 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &iter, &rectangle);
521 offset = priv->msg_body->allocation.y;
523 new_value = (offset + rectangle.y);
525 hildon_pannable_area_jump_to (HILDON_PANNABLE_AREA (priv->pannable), -1, new_value);
527 priv->correct_scroll_idle = 0;
532 correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused)
534 ModestMsgEditWindowPrivate *priv;
536 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
538 if (only_if_focused && !gtk_widget_is_focus (priv->msg_body))
541 if (priv->correct_scroll_idle > 0) {
545 priv->correct_scroll_idle = g_idle_add ((GSourceFunc) correct_scroll_without_drag_check_idle,
550 correct_scroll (ModestMsgEditWindow *w)
552 ModestMsgEditWindowPrivate *priv;
554 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
555 if (gtk_grab_get_current () == priv->msg_body) {
556 if (priv->scroll_drag_timeout_id == 0) {
557 priv->scroll_drag_timeout_id = g_timeout_add (500, (GSourceFunc) scroll_drag_timeout,
563 correct_scroll_without_drag_check (w, TRUE);
567 text_buffer_end_user_action (GtkTextBuffer *buffer,
568 ModestMsgEditWindow *userdata)
571 correct_scroll (userdata);
575 text_buffer_mark_set (GtkTextBuffer *buffer,
578 ModestMsgEditWindow *userdata)
580 gtk_text_buffer_begin_user_action (buffer);
581 gtk_text_buffer_end_user_action (buffer);
585 cut_clipboard_check (GtkTextView *text_view,
588 GtkTextBuffer *buffer;
590 buffer = gtk_text_view_get_buffer (text_view);
591 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
592 g_signal_stop_emission_by_name ((gpointer )text_view, "cut-clipboard");
597 copy_clipboard_check (GtkTextView *text_view,
600 GtkTextBuffer *buffer;
602 buffer = gtk_text_view_get_buffer (text_view);
603 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
604 g_signal_stop_emission_by_name ((gpointer )text_view, "copy-clipboard");
609 attachment_deleted (ModestAttachmentsView *attachments_view,
612 modest_msg_edit_window_remove_attachments (MODEST_MSG_EDIT_WINDOW (user_data),
617 connect_signals (ModestMsgEditWindow *obj)
619 ModestMsgEditWindowPrivate *priv;
621 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
623 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
624 G_CALLBACK (text_buffer_refresh_attributes), obj);
625 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
626 G_CALLBACK (text_buffer_can_undo), obj);
627 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
628 G_CALLBACK (text_buffer_can_redo), obj);
629 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
630 G_CALLBACK (body_changed), obj);
631 g_signal_connect (G_OBJECT (priv->text_buffer), "modified-changed",
632 G_CALLBACK (body_changed), obj);
633 g_signal_connect (G_OBJECT (priv->text_buffer), "end-user-action",
634 G_CALLBACK (text_buffer_end_user_action), obj);
635 g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
636 G_CALLBACK (text_buffer_mark_set), obj);
637 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
638 G_CALLBACK (text_buffer_apply_tag), obj);
639 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
640 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
641 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
642 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
643 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
644 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
646 g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
647 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
648 g_signal_connect (G_OBJECT (priv->from_field), "value-changed",
649 G_CALLBACK (from_field_changed), obj);
651 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
652 G_CALLBACK (msg_body_focus), obj);
653 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
654 G_CALLBACK (msg_body_focus), obj);
655 g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
656 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
657 "changed", G_CALLBACK (recpt_field_changed), obj);
658 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
659 "changed", G_CALLBACK (recpt_field_changed), obj);
660 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
661 "changed", G_CALLBACK (recpt_field_changed), obj);
662 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
663 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
664 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
666 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
667 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
669 priv->clipboard_change_handler_id =
670 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
671 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
672 priv->default_clipboard_change_handler_id =
673 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
674 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
676 g_signal_connect (G_OBJECT (priv->msg_body), "cut-clipboard", G_CALLBACK (cut_clipboard_check), NULL);
677 g_signal_connect (G_OBJECT (priv->msg_body), "copy-clipboard", G_CALLBACK (copy_clipboard_check), NULL);
678 g_signal_connect (G_OBJECT (priv->attachments_view), "delete", G_CALLBACK (attachment_deleted), obj);
682 init_wp_text_view_style ()
684 static gboolean initialized = FALSE;
687 gtk_rc_parse_string ("class \"WPTextView\" style \"fremantle-textview\"");
693 init_window (ModestMsgEditWindow *obj)
695 GtkWidget *to_caption, *subject_caption;
696 GtkWidget *main_vbox;
697 GtkWidget *add_attachment_align;
698 ModestMsgEditWindowPrivate *priv;
699 GtkActionGroup *action_group;
700 ModestWindowPrivate *parent_priv;
701 GdkPixbuf *window_icon = NULL;
702 GError *error = NULL;
704 GtkSizeGroup *title_size_group;
705 GtkSizeGroup *value_size_group;
706 GtkWidget *attachment_icon;
707 GtkWidget *window_box;
708 #if (GTK_MINOR_VERSION >= 10)
709 GdkAtom deserialize_type;
712 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
713 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
715 parent_priv->ui_manager = gtk_ui_manager_new();
716 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
717 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
719 /* Add common actions */
720 gtk_action_group_add_actions (action_group,
721 modest_msg_edit_action_entries,
722 G_N_ELEMENTS (modest_msg_edit_action_entries),
724 gtk_action_group_add_actions (action_group,
725 hildon2_msg_edit_action_entries,
726 G_N_ELEMENTS (hildon2_msg_edit_action_entries),
728 gtk_action_group_add_toggle_actions (action_group,
729 modest_msg_edit_toggle_action_entries,
730 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
732 gtk_action_group_add_radio_actions (action_group,
733 modest_msg_edit_alignment_radio_action_entries,
734 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
736 G_CALLBACK (modest_ui_actions_on_change_justify),
738 gtk_action_group_add_radio_actions (action_group,
739 modest_msg_edit_priority_action_entries,
740 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
742 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
744 gtk_action_group_add_radio_actions (action_group,
745 modest_msg_edit_file_format_action_entries,
746 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
747 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
748 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
750 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
751 g_object_unref (action_group);
753 /* Load the UI definition */
754 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
757 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
758 g_clear_error (&error);
761 /* Add accelerators */
762 gtk_window_add_accel_group (GTK_WINDOW (obj),
763 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
765 parent_priv->menubar = NULL;
767 title_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
768 value_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
770 /* Note: This ModestPairList* must exist for as long as the picker
771 * that uses it, because the ModestSelectorPicker uses the ID opaquely,
772 * so it can't know how to manage its memory. */
773 priv->from_field = modest_selector_picker_new (MODEST_EDITABLE_SIZE,
774 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL,
776 modest_maemo_utils_set_hbutton_layout (title_size_group, value_size_group,
777 _("mail_va_from"), priv->from_field);
779 priv->to_field = modest_recpt_editor_new ();
780 priv->cc_field = modest_recpt_editor_new ();
781 priv->bcc_field = modest_recpt_editor_new ();
782 priv->subject_box = gtk_hbox_new (FALSE, MODEST_MARGIN_NONE);
783 priv->priority_icon = gtk_image_new ();
784 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->priority_icon, FALSE, FALSE, 0);
785 priv->subject_field = hildon_entry_new (MODEST_EDITABLE_SIZE);
786 gtk_entry_set_max_length (GTK_ENTRY (priv->subject_field) ,SUBJECT_MAX_LENGTH);
787 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
788 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
789 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
790 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->subject_field, TRUE, TRUE, 0);
791 priv->add_attachment_button = hildon_button_new (MODEST_EDITABLE_SIZE, HILDON_BUTTON_ARRANGEMENT_VERTICAL);
792 gtk_widget_set_size_request (priv->add_attachment_button, ATTACHMENT_BUTTON_WIDTH, -1);
793 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
794 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
795 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, HILDON_ICON_SIZE_FINGER);
796 hildon_button_set_image (HILDON_BUTTON (priv->add_attachment_button), attachment_icon);
797 add_attachment_align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
798 gtk_alignment_set_padding (GTK_ALIGNMENT (add_attachment_align), 0, 0, MODEST_MARGIN_DEFAULT, 0);
799 gtk_container_add (GTK_CONTAINER (add_attachment_align), priv->add_attachment_button);
800 gtk_box_pack_start (GTK_BOX (priv->subject_box), add_attachment_align, FALSE, FALSE, 0);
801 priv->attachments_view = modest_attachments_view_new (NULL);
802 modest_attachments_view_set_style (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
803 MODEST_ATTACHMENTS_VIEW_STYLE_NO_FOCUS);
805 priv->header_box = gtk_vbox_new (FALSE, 0);
807 to_caption = modest_maemo_utils_create_captioned_with_size_type
808 (title_size_group, value_size_group,
809 _("mail_va_to"), FALSE, priv->to_field,
810 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
811 priv->cc_caption = modest_maemo_utils_create_captioned_with_size_type
812 (title_size_group, value_size_group,
813 _("mail_va_cc"), FALSE, priv->cc_field,
814 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
815 priv->bcc_caption = modest_maemo_utils_create_captioned_with_size_type
816 (title_size_group, value_size_group,
817 _("mail_va_hotfix1"), FALSE, priv->bcc_field,
818 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
819 subject_caption = modest_maemo_utils_create_captioned (title_size_group, value_size_group,
820 _("mail_va_subject"), FALSE, priv->subject_box);
821 priv->attachments_caption = modest_maemo_utils_create_captioned_with_size_type (title_size_group, value_size_group,
822 _("mail_va_attachment"),
824 priv->attachments_view,
825 HILDON_SIZE_AUTO_WIDTH |
826 HILDON_SIZE_AUTO_HEIGHT);
827 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), value_size_group); */
828 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), value_size_group); */
829 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), value_size_group); */
830 g_object_unref (title_size_group);
831 g_object_unref (value_size_group);
833 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->from_field, FALSE, FALSE, 0);
834 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
835 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
836 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
837 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
838 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
839 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
841 init_wp_text_view_style ();
843 priv->msg_body = wp_text_view_new ();
846 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
847 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
848 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
849 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
850 #if (GTK_MINOR_VERSION >= 10)
851 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
852 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
854 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
855 deserialize_type, TRUE);
857 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
859 priv->find_toolbar = hildon_find_toolbar_new (NULL);
860 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
862 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
864 priv->pannable = hildon_pannable_area_new ();
866 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
868 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
869 gtk_box_pack_start (GTK_BOX(main_vbox), priv->msg_body, TRUE, TRUE, 0);
871 hildon_pannable_area_add_with_viewport (HILDON_PANNABLE_AREA (priv->pannable), main_vbox);
872 gtk_container_set_focus_vadjustment (GTK_CONTAINER (main_vbox),
873 hildon_pannable_area_get_vadjustment (HILDON_PANNABLE_AREA (priv->pannable)));
874 gtk_widget_show_all (GTK_WIDGET(priv->pannable));
876 window_box = gtk_vbox_new (FALSE, 0);
877 gtk_container_add (GTK_CONTAINER(obj), window_box);
879 gtk_box_pack_start (GTK_BOX (window_box), priv->pannable, TRUE, TRUE, 0);
881 /* Set window icon */
882 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
884 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
885 g_object_unref (window_icon);
890 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
892 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
894 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
895 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
896 priv->clipboard_change_handler_id))
897 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
898 priv->clipboard_change_handler_id);
899 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
900 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
901 priv->default_clipboard_change_handler_id))
902 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
903 priv->default_clipboard_change_handler_id);
905 if (priv->account_removed_handler_id &&
906 g_signal_handler_is_connected (modest_runtime_get_account_store (),
907 priv->account_removed_handler_id))
908 g_signal_handler_disconnect(modest_runtime_get_account_store (),
909 priv->account_removed_handler_id);
913 modest_msg_edit_window_finalize (GObject *obj)
915 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
917 /* Sanity check: shouldn't be needed, the window mgr should
918 call this function before */
919 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
921 if (priv->font_dialog != NULL) {
922 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
925 if (priv->clipboard_text != NULL) {
926 g_free (priv->clipboard_text);
927 priv->clipboard_text = NULL;
930 if (priv->draft_msg != NULL) {
931 TnyHeader *header = tny_msg_get_header (priv->draft_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->draft_msg);
937 priv->draft_msg = NULL;
939 if (priv->outbox_msg != NULL) {
940 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
941 if (TNY_IS_HEADER (header)) {
942 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
943 modest_window_mgr_unregister_header (mgr, header);
945 g_object_unref (priv->outbox_msg);
946 priv->outbox_msg = NULL;
948 if (priv->correct_scroll_idle > 0) {
949 g_source_remove (priv->correct_scroll_idle);
950 priv->correct_scroll_idle = 0;
952 if (priv->scroll_drag_timeout_id > 0) {
953 g_source_remove (priv->scroll_drag_timeout_id);
954 priv->scroll_drag_timeout_id = 0;
956 if (priv->clipboard_owner_idle > 0) {
957 g_source_remove (priv->clipboard_owner_idle);
958 priv->clipboard_owner_idle = 0;
960 if (priv->original_account_name)
961 g_free (priv->original_account_name);
962 g_free (priv->msg_uid);
963 g_free (priv->last_search);
964 g_slist_free (priv->font_items_group);
965 g_slist_free (priv->size_items_group);
966 g_object_unref (priv->attachments);
967 g_object_unref (priv->images);
969 /* This had to stay alive for as long as the picker that used it: */
970 modest_pair_list_free (priv->from_field_protos);
972 G_OBJECT_CLASS(parent_class)->finalize (obj);
976 pixbuf_from_stream (TnyStream *stream, const gchar *mime_type, guint64 *stream_size)
978 GdkPixbufLoader *loader;
984 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
986 if (loader == NULL) {
992 tny_stream_reset (TNY_STREAM (stream));
993 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
994 GError *error = NULL;
995 unsigned char read_buffer[128];
997 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
999 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
1001 g_error_free (error);
1006 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1008 g_object_ref (pixbuf);
1009 gdk_pixbuf_loader_close (loader, NULL);
1010 g_object_unref (loader);
1015 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1016 GdkPixbuf *new_pixbuf;
1018 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1019 gdk_pixbuf_get_width (pixbuf);
1020 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1021 g_object_unref (pixbuf);
1022 pixbuf = new_pixbuf;
1026 *stream_size = size;
1032 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1034 ModestMsgEditWindowPrivate *priv;
1037 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1039 for (iter = tny_list_create_iterator (attachments);
1040 !tny_iterator_is_done (iter);
1041 tny_iterator_next (iter)) {
1042 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1043 const gchar *cid = tny_mime_part_get_content_id (part);
1044 const gchar *mime_type = tny_mime_part_get_content_type (part);
1045 if ((cid != NULL)&&(mime_type != NULL)) {
1046 guint64 stream_size;
1047 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1048 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
1051 g_object_unref (stream);
1053 if (pixbuf != NULL) {
1054 priv->images_count ++;
1055 priv->images_size += stream_size;
1056 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1057 g_object_unref (pixbuf);
1060 g_object_unref (part);
1062 g_object_unref (iter);
1066 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1068 TnyMimePart *parent = NULL;
1069 const gchar *content_type = NULL;
1070 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1072 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1074 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1075 parent = g_object_ref (msg);
1076 } else if (content_type && !g_strcasecmp (content_type, "multipart/mixed")) {
1077 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1080 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1081 iter = tny_list_create_iterator (parts);
1082 while (!tny_iterator_is_done (iter)) {
1084 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1085 content_type = tny_mime_part_get_content_type (part);
1086 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1090 g_object_unref (part);
1092 tny_iterator_next (iter);
1094 g_object_unref (iter);
1095 g_object_unref (parts);
1098 if (parent != NULL) {
1099 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1102 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1103 iter = tny_list_create_iterator (parts);
1104 while (!tny_iterator_is_done (iter)) {
1106 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1107 content_type = tny_mime_part_get_content_type (part);
1108 if (content_type && g_str_has_prefix (content_type, "image/")) {
1109 tny_list_prepend (priv->images, (GObject *) part);
1111 g_object_unref (part);
1112 tny_iterator_next (iter);
1114 g_object_unref (iter);
1115 g_object_unref (parts);
1116 g_object_unref (parent);
1121 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1124 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1126 for (iter = tny_list_create_iterator (attachments) ;
1127 !tny_iterator_is_done (iter);
1128 tny_iterator_next (iter)) {
1129 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1130 const gchar *cid = tny_mime_part_get_content_id (part);
1132 char *invalid = NULL;
1133 gint int_cid = strtol (cid, &invalid, 10);
1134 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1135 priv->next_cid = int_cid + 1;
1138 g_object_unref (part);
1140 g_object_unref (iter);
1144 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1147 gchar *to, *cc, *bcc, *subject;
1149 ModestMsgEditWindowPrivate *priv;
1150 ModestWindowPrivate *parent_priv;
1152 TnyHeaderFlags priority_flags;
1153 TnyFolder *msg_folder;
1154 gboolean is_html = FALSE;
1155 gboolean field_view_set;
1157 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1158 g_return_if_fail (TNY_IS_MSG (msg));
1160 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1161 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1163 header = tny_msg_get_header (msg);
1164 to = tny_header_dup_to (header);
1165 cc = tny_header_dup_cc (header);
1166 bcc = tny_header_dup_bcc (header);
1167 subject = tny_header_dup_subject (header);
1168 priority_flags = tny_header_get_priority (header);
1171 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
1173 field_view_set = TRUE;
1175 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
1176 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1177 gtk_widget_show (priv->cc_caption);
1178 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1179 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1180 gtk_widget_hide (priv->cc_caption);
1181 field_view_set = FALSE;
1183 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button), field_view_set);
1185 field_view_set = TRUE;
1187 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
1188 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1189 gtk_widget_show (priv->bcc_caption);
1190 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1191 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1192 gtk_widget_hide (priv->bcc_caption);
1193 field_view_set = FALSE;
1195 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button), field_view_set);
1199 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1200 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1203 update_window_title (self);
1205 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1206 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1208 if ((body == NULL)||(body[0] == '\0')) {
1210 body = modest_text_utils_convert_to_html ("");
1213 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1214 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1217 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1220 /* Add attachments to the view */
1221 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1222 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1223 if (tny_list_get_length (priv->attachments) == 0) {
1224 gtk_widget_hide (priv->attachments_caption);
1226 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1227 gtk_widget_show_all (priv->attachments_caption);
1229 get_related_images (self, msg);
1230 update_next_cid (self, priv->attachments);
1231 update_next_cid (self, priv->images);
1232 replace_with_images (self, priv->images);
1234 if (preserve_is_rich && !is_html) {
1235 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1236 /* Get the default format required from configuration */
1237 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1238 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1241 /* Set the default focus depending on having already a To: field or not */
1242 if ((!to)||(*to == '\0')) {
1243 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1245 gtk_widget_grab_focus (priv->msg_body);
1248 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1250 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1251 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1253 modest_msg_edit_window_set_modified (self, FALSE);
1255 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1256 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1257 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1258 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1260 if (priv->msg_uid) {
1261 g_free (priv->msg_uid);
1262 priv->msg_uid = NULL;
1265 /* we should set a reference to the incoming message if it is a draft */
1266 msg_folder = tny_msg_get_folder (msg);
1268 if (modest_tny_folder_is_local_folder (msg_folder)) {
1269 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1270 if (type == TNY_FOLDER_TYPE_INVALID)
1271 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1273 if (type == TNY_FOLDER_TYPE_DRAFTS)
1274 priv->draft_msg = g_object_ref(msg);
1275 if (type == TNY_FOLDER_TYPE_OUTBOX)
1276 priv->outbox_msg = g_object_ref(msg);
1277 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1279 g_object_unref (msg_folder);
1289 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
1292 GList *item_children, *node;
1293 GtkWidget *bin_child;
1295 bin_child = gtk_bin_get_child (GTK_BIN(item));
1297 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
1299 for (node = item_children; node != NULL; node = g_list_next (node)) {
1300 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
1301 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
1304 g_list_free (item_children);
1308 menu_tool_button_dont_expand (GtkMenuToolButton *item)
1311 GList *item_children, *node;
1313 box = gtk_bin_get_child (GTK_BIN (item));
1314 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
1315 item_children = gtk_container_get_children (GTK_CONTAINER (box));
1317 for (node = item_children; node != NULL; node = g_list_next (node)) {
1318 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
1319 if (GTK_IS_TOGGLE_BUTTON (node->data))
1320 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
1321 else if (GTK_IS_BUTTON (node->data))
1322 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
1324 g_list_free (item_children);
1329 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1331 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1332 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1333 GtkWidget *placeholder;
1334 GtkWidget *tool_item;
1339 GtkWidget *sizes_menu;
1340 GtkWidget *fonts_menu;
1341 GSList *radio_group = NULL;
1342 GSList *node = NULL;
1346 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1347 gtk_toolbar_set_show_arrow (GTK_TOOLBAR (parent_priv->toolbar), FALSE);
1348 gtk_toolbar_set_icon_size (GTK_TOOLBAR (parent_priv->toolbar), HILDON_ICON_SIZE_FINGER);
1349 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1351 /* Font color placeholder */
1352 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1353 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1356 priv->font_color_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1357 priv->font_color_button = hildon_color_button_new ();
1358 gtk_widget_set_size_request (priv->font_color_button, -1, 48);
1359 GTK_WIDGET_UNSET_FLAGS (priv->font_color_toolitem, GTK_CAN_FOCUS);
1360 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1361 gtk_container_add (GTK_CONTAINER (priv->font_color_toolitem), priv->font_color_button);
1362 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1363 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1364 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->font_color_toolitem), insert_index);
1365 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1367 G_CALLBACK (modest_msg_edit_window_color_button_change),
1370 /* Font size and face placeholder */
1371 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1372 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1374 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1375 priv->size_tool_button_label = gtk_label_new (NULL);
1376 hildon_helper_set_logical_color (GTK_WIDGET (priv->size_tool_button_label), GTK_RC_TEXT,
1377 GTK_STATE_INSENSITIVE, "SecondaryTextColor");
1378 hildon_helper_set_logical_color (GTK_WIDGET (priv->size_tool_button_label), GTK_RC_FG,
1379 GTK_STATE_INSENSITIVE, "SecondaryTextColor");
1380 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1381 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1382 size_text,"</span>", NULL);
1383 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1385 hildon_helper_set_logical_font (priv->size_tool_button_label, "LargeSystemFont");
1386 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
1387 sizes_menu = gtk_menu_new ();
1388 priv->size_items_group = NULL;
1390 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1391 GtkWidget *size_menu_item;
1393 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1394 size_menu_item = gtk_radio_menu_item_new_with_label (radio_group, size_text);
1395 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (size_menu_item));
1396 gtk_menu_shell_append (GTK_MENU_SHELL (sizes_menu), size_menu_item);
1397 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (size_menu_item), (wp_font_size[size_index] == 12));
1398 gtk_widget_show (size_menu_item);
1400 priv->size_items_group = g_slist_prepend (priv->size_items_group, size_menu_item);
1404 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1405 GtkWidget *item = (GtkWidget *) node->data;
1406 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_size_change),
1410 priv->size_items_group = g_slist_reverse (priv->size_items_group);
1411 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), sizes_menu);
1412 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1413 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1414 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), FALSE);
1415 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), FALSE);
1416 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1417 priv->font_size_toolitem = tool_item;
1420 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1421 priv->font_tool_button_label = gtk_label_new (NULL);
1422 hildon_helper_set_logical_color (GTK_WIDGET (priv->font_tool_button_label), GTK_RC_TEXT,
1423 GTK_STATE_INSENSITIVE, "SecondaryTextColor");
1424 hildon_helper_set_logical_color (GTK_WIDGET (priv->font_tool_button_label), GTK_RC_FG,
1425 GTK_STATE_INSENSITIVE, "SecondaryTextColor");
1426 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1427 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1429 hildon_helper_set_logical_font (priv->font_tool_button_label, "LargeSystemFont");
1430 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
1431 fonts_menu = gtk_menu_new ();
1432 priv->font_items_group = NULL;
1434 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1435 GtkWidget *font_menu_item;
1436 GtkWidget *child_label;
1438 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
1439 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
1440 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
1441 wp_get_font_name (font_index), "</span>", NULL);
1442 gtk_label_set_markup (GTK_LABEL (child_label), markup);
1445 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
1446 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
1447 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
1448 gtk_widget_show (font_menu_item);
1450 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
1453 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1454 GtkWidget *item = (GtkWidget *) node->data;
1455 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
1458 priv->font_items_group = g_slist_reverse (priv->font_items_group);
1459 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
1460 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1461 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1462 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), FALSE);
1463 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), FALSE);
1464 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1465 priv->font_face_toolitem = tool_item;
1467 /* Set expand and homogeneous for remaining items */
1468 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
1469 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1470 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1471 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1472 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1473 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1474 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1475 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1476 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1478 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1479 will not show the tool items added to the placeholders) */
1480 gtk_widget_show_all (parent_priv->toolbar);
1482 /* Set the no show all *after* showing all items. We do not
1483 want the toolbar to be shown with a show all because it
1484 could go agains the gconf setting regarding showing or not
1485 the toolbar of the editor window */
1486 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1492 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, gboolean preserve_is_rich)
1495 ModestWindowPrivate *parent_priv;
1496 ModestMsgEditWindowPrivate *priv;
1497 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1498 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1499 ModestWindowMgr *mgr = NULL;
1501 g_return_val_if_fail (msg, NULL);
1502 g_return_val_if_fail (account_name, NULL);
1504 mgr = modest_runtime_get_window_mgr ();
1506 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1508 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1509 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1511 /* Menubar. Update the state of some toggles */
1512 priv->from_field_protos = get_transports ();
1513 modest_selector_picker_set_pair_list (MODEST_SELECTOR_PICKER (priv->from_field), priv->from_field_protos);
1514 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1515 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1516 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1518 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1519 hildon_touch_selector_get_current_text
1520 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1521 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1522 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1525 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1527 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1529 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1531 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1533 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1534 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1535 /* Add common dimming rules */
1536 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1537 modest_msg_edit_window_toolbar_dimming_entries,
1538 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1539 MODEST_WINDOW (obj));
1540 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_toolitem,
1541 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1542 MODEST_WINDOW (obj));
1543 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1544 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1545 MODEST_WINDOW (obj));
1546 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1547 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1548 MODEST_WINDOW (obj));
1549 /* Insert dimming rules group for this window */
1550 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1551 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1553 /* Setup app menu */
1554 setup_menu (MODEST_MSG_EDIT_WINDOW (obj));
1556 /* Checks the dimming rules */
1557 g_object_unref (toolbar_rules_group);
1558 g_object_unref (clipboard_rules_group);
1559 gtk_widget_hide (priv->priority_icon);
1560 gtk_widget_queue_resize (priv->subject_box);
1561 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1563 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1565 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1566 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1567 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1568 priv->update_caption_visibility = TRUE;
1570 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1572 /* Track account-removed signal, this window should be closed
1573 in the case we're creating a mail associated to the account
1575 priv->account_removed_handler_id =
1576 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1578 G_CALLBACK(on_account_removed),
1581 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1583 return (ModestWindow*) obj;
1587 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1589 GString **string_buffer = (GString **) user_data;
1591 *string_buffer = g_string_append (*string_buffer, buffer);
1597 * @result: A new string which should be freed with g_free().
1600 get_formatted_data (ModestMsgEditWindow *edit_window)
1602 ModestMsgEditWindowPrivate *priv;
1603 GString *string_buffer = g_string_new ("");
1605 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1607 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1609 modest_text_utils_hyperlinkify (string_buffer);
1611 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1613 return g_string_free (string_buffer, FALSE);
1618 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1621 const gchar *account_name;
1622 ModestMsgEditWindowPrivate *priv;
1623 TnyIterator *att_iter;
1625 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1627 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1629 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1630 g_return_val_if_fail (account_name, NULL);
1633 /* don't free these (except from) */
1634 data = g_slice_new0 (MsgData);
1635 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1637 data->account_name = g_strdup (account_name);
1638 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1639 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1640 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1641 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1642 if (priv->draft_msg) {
1643 data->draft_msg = g_object_ref (priv->draft_msg);
1644 } else if (priv->outbox_msg) {
1645 data->draft_msg = g_object_ref (priv->outbox_msg);
1647 data->draft_msg = NULL;
1650 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1652 gtk_text_buffer_get_bounds (buf, &b, &e);
1653 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1655 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1656 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1658 data->html_body = NULL;
1660 /* deep-copy the data */
1661 att_iter = tny_list_create_iterator (priv->attachments);
1662 data->attachments = NULL;
1663 while (!tny_iterator_is_done (att_iter)) {
1664 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1665 if (!(TNY_IS_MIME_PART(part))) {
1666 g_warning ("strange data in attachment list");
1667 g_object_unref (part);
1668 tny_iterator_next (att_iter);
1671 data->attachments = g_list_append (data->attachments,
1673 tny_iterator_next (att_iter);
1675 g_object_unref (att_iter);
1677 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1678 att_iter = tny_list_create_iterator (priv->images);
1679 data->images = NULL;
1680 while (!tny_iterator_is_done (att_iter)) {
1681 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1683 if (!(TNY_IS_MIME_PART(part))) {
1684 g_warning ("strange data in attachment list");
1685 g_object_unref (part);
1686 tny_iterator_next (att_iter);
1689 cid = tny_mime_part_get_content_id (part);
1691 gchar *image_tag_id;
1692 GtkTextTag *image_tag;
1694 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1695 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1696 g_free (image_tag_id);
1698 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1700 ((gtk_text_iter_has_tag (&iter, image_tag))||
1701 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1702 data->images = g_list_append (data->images,
1703 g_object_ref (part));
1705 g_object_unref (part);
1706 tny_iterator_next (att_iter);
1708 g_object_unref (att_iter);
1710 data->priority_flags = priv->priority_flags;
1717 unref_gobject (GObject *obj, gpointer data)
1719 if (!G_IS_OBJECT(obj))
1721 g_object_unref (obj);
1725 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1728 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1736 g_free (data->from);
1737 g_free (data->subject);
1738 g_free (data->plain_body);
1739 g_free (data->html_body);
1740 g_free (data->account_name);
1742 if (data->draft_msg != NULL) {
1743 g_object_unref (data->draft_msg);
1744 data->draft_msg = NULL;
1747 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1748 g_list_free (data->attachments);
1749 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1750 g_list_free (data->images);
1752 g_slice_free (MsgData, data);
1756 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1758 guint64 *parts_size)
1760 ModestMsgEditWindowPrivate *priv;
1762 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1764 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1766 /* TODO: add images */
1767 *parts_size += priv->images_size;
1768 *parts_count += priv->images_count;
1773 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1776 ModestMsgEditWindowPrivate *priv = NULL;
1777 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1779 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1781 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1783 return MODEST_MSG_EDIT_FORMAT_HTML;
1785 return MODEST_MSG_EDIT_FORMAT_TEXT;
1789 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1790 ModestMsgEditFormat format)
1792 ModestMsgEditWindowPrivate *priv;
1794 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1795 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1798 case MODEST_MSG_EDIT_FORMAT_HTML:
1799 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1801 case MODEST_MSG_EDIT_FORMAT_TEXT:
1802 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1805 g_return_if_reached ();
1809 ModestMsgEditFormatState *
1810 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1812 ModestMsgEditFormatState *format_state = NULL;
1813 ModestMsgEditWindowPrivate *priv;
1814 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1816 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1817 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1819 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1821 format_state = g_new0 (ModestMsgEditFormatState, 1);
1822 format_state->bold = buffer_format->bold&0x1;
1823 format_state->italics = buffer_format->italic&0x1;
1824 format_state->bullet = buffer_format->bullet&0x1;
1825 format_state->color = buffer_format->color;
1826 format_state->font_size = buffer_format->font_size;
1827 format_state->font_family = wp_get_font_name (buffer_format->font);
1828 format_state->justification = buffer_format->justification;
1829 g_free (buffer_format);
1831 return format_state;
1836 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1837 const ModestMsgEditFormatState *format_state)
1839 ModestMsgEditWindowPrivate *priv;
1840 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1841 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1842 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1843 g_return_if_fail (format_state != NULL);
1845 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1846 gtk_widget_grab_focus (priv->msg_body);
1847 buffer_format->bold = (format_state->bold != FALSE);
1848 buffer_format->italic = (format_state->italics != FALSE);
1849 buffer_format->color = format_state->color;
1850 buffer_format->font_size = format_state->font_size;
1851 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1852 buffer_format->justification = format_state->justification;
1853 buffer_format->bullet = format_state->bullet;
1855 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1857 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1858 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1859 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1860 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1861 buffer_format->cs.font = (buffer_format->font != current_format->font);
1862 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1863 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1865 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1866 if (buffer_format->cs.bold) {
1867 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
1868 GINT_TO_POINTER (buffer_format->bold&0x1));
1870 if (buffer_format->cs.italic) {
1871 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
1872 GINT_TO_POINTER (buffer_format->italic&0x1));
1874 if (buffer_format->cs.color) {
1875 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1876 GINT_TO_POINTER (&(buffer_format->color)));
1878 if (buffer_format->cs.font_size) {
1879 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1880 GINT_TO_POINTER (buffer_format->font_size));
1882 if (buffer_format->cs.justification) {
1883 switch (buffer_format->justification) {
1884 case GTK_JUSTIFY_LEFT:
1885 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
1886 GINT_TO_POINTER(TRUE));
1888 case GTK_JUSTIFY_CENTER:
1889 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
1890 GINT_TO_POINTER(TRUE));
1892 case GTK_JUSTIFY_RIGHT:
1893 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
1894 GINT_TO_POINTER(TRUE));
1901 if (buffer_format->cs.font) {
1902 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1903 GINT_TO_POINTER (buffer_format->font));
1905 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1906 if (buffer_format->cs.bullet) {
1907 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
1908 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
1910 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1912 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
1914 g_free (buffer_format);
1915 g_free (current_format);
1917 /* Check dimming rules */
1918 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1919 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1923 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1925 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1927 ModestWindowPrivate *parent_priv;
1928 ModestMsgEditWindowPrivate *priv;
1929 GtkWidget *new_size_menuitem;
1930 GtkWidget *new_font_menuitem;
1932 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1933 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1935 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1936 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu");
1937 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1938 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1940 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatPlainTextMenu");
1941 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1942 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1945 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1947 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1948 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1950 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1951 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1953 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
1954 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
1957 switch (buffer_format->justification)
1959 case GTK_JUSTIFY_LEFT:
1960 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
1962 case GTK_JUSTIFY_CENTER:
1963 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
1965 case GTK_JUSTIFY_RIGHT:
1966 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
1973 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
1975 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1976 G_CALLBACK (modest_msg_edit_window_color_button_change),
1978 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1979 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1980 G_CALLBACK (modest_msg_edit_window_color_button_change),
1983 new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group,
1984 buffer_format->font_size))->data);
1985 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1989 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1990 markup = g_strconcat ("<span font_family='Sans'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1991 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1993 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1994 G_CALLBACK (modest_msg_edit_window_size_change),
1996 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
1997 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
1998 G_CALLBACK (modest_msg_edit_window_size_change),
2002 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
2003 buffer_format->font))->data);
2004 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
2008 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
2009 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2010 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2012 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
2013 G_CALLBACK (modest_msg_edit_window_font_change),
2015 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
2016 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
2017 G_CALLBACK (modest_msg_edit_window_font_change),
2021 g_free (buffer_format);
2025 #ifdef MODEST_HILDON_VERSION_0
2027 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2030 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2031 ModestMsgEditWindowPrivate *priv;
2032 GtkWidget *dialog = NULL;
2034 GdkColor *new_color = NULL;
2036 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2037 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2039 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2040 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
2041 g_free (buffer_format);
2043 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2044 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2045 if (new_color != NULL) {
2046 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2047 (gpointer) new_color);
2050 gtk_widget_destroy (dialog);
2055 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2058 ModestMsgEditWindowPrivate *priv;
2059 GtkWidget *dialog = NULL;
2061 GdkColor *old_color = NULL;
2062 const GdkColor *new_color = NULL;
2064 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2065 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2067 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2068 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2070 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2071 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2072 if (new_color != NULL)
2073 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2075 gtk_widget_destroy (dialog);
2081 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2084 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2085 ModestMsgEditWindowPrivate *priv;
2086 GtkWidget *dialog = NULL;
2088 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2089 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2091 dialog = hildon_color_chooser_new ();
2092 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2093 g_free (buffer_format);
2095 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2097 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2098 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2101 gtk_widget_destroy (dialog);
2106 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2109 ModestMsgEditWindowPrivate *priv;
2110 GtkWidget *dialog = NULL;
2111 GdkColor *old_color = NULL;
2113 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2114 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2116 dialog = hildon_color_chooser_new ();
2117 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2119 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2121 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2122 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2124 gtk_widget_destroy (dialog);
2127 #endif /*!MODEST_HILDON_VERSION_0*/
2132 create_stream_for_uri (const gchar* uri)
2137 TnyStream *result = NULL;
2139 GnomeVFSHandle *handle = NULL;
2140 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2141 if (test == GNOME_VFS_OK) {
2142 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2143 /* Streams over OBEX (Bluetooth) are not seekable but
2144 * we expect them to be (we might need to read them
2145 * several times). So if this is a Bluetooth URI just
2146 * read the whole file into memory (this is not a fast
2147 * protocol so we can assume that these files are not
2148 * going to be very big) */
2149 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2150 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2151 TnyStream *memstream = tny_camel_mem_stream_new ();
2152 tny_stream_write_to_stream (vfssstream, memstream);
2153 g_object_unref (vfssstream);
2156 result = vfssstream;
2164 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2167 ModestMsgEditWindowPrivate *priv;
2168 GtkWidget *dialog = NULL;
2170 GSList *uris = NULL;
2171 GSList *uri_node = NULL;
2173 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2175 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2176 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2177 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2179 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2181 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2182 GTK_WINDOW (dialog), GTK_WINDOW (window));
2184 response = gtk_dialog_run (GTK_DIALOG (dialog));
2186 case GTK_RESPONSE_OK:
2187 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2192 gtk_widget_destroy (dialog);
2194 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2196 GnomeVFSHandle *handle = NULL;
2197 GnomeVFSResult result;
2198 GtkTextIter position;
2199 GtkTextMark *insert_mark;
2201 uri = (const gchar *) uri_node->data;
2202 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2203 if (result == GNOME_VFS_OK) {
2205 GnomeVFSFileInfo *info;
2206 gchar *filename, *basename, *escaped_filename;
2207 TnyMimePart *mime_part;
2209 const gchar *mime_type = NULL;
2210 GnomeVFSURI *vfs_uri;
2211 guint64 stream_size;
2213 gnome_vfs_close (handle);
2214 vfs_uri = gnome_vfs_uri_new (uri);
2216 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2217 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2218 g_free (escaped_filename);
2219 gnome_vfs_uri_unref (vfs_uri);
2220 info = gnome_vfs_file_info_new ();
2222 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2223 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2225 mime_type = gnome_vfs_file_info_get_mime_type (info);
2227 mime_part = tny_platform_factory_new_mime_part
2228 (modest_runtime_get_platform_factory ());
2230 TnyStream *stream = create_stream_for_uri (uri);
2232 if (stream == NULL) {
2234 modest_platform_information_banner (NULL, NULL,
2235 _FM("sfil_ib_opening_not_allowed"));
2237 g_object_unref (mime_part);
2238 gnome_vfs_file_info_unref (info);
2242 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2244 content_id = g_strdup_printf ("%d", priv->next_cid);
2245 tny_mime_part_set_content_id (mime_part, content_id);
2246 g_free (content_id);
2249 basename = g_path_get_basename (filename);
2250 tny_mime_part_set_filename (mime_part, basename);
2253 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
2255 if (pixbuf != NULL) {
2256 priv->images_size += stream_size;
2257 priv->images_count ++;
2258 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2259 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2260 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
2261 g_object_unref (pixbuf);
2264 tny_list_prepend (priv->images, (GObject *) mime_part);
2265 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2267 g_object_unref (mime_part);
2268 gnome_vfs_file_info_unref (info);
2277 on_attach_file_response (GtkDialog *dialog,
2281 GSList *uris = NULL;
2283 GnomeVFSFileSize total_size, allowed_size;
2284 ModestMsgEditWindow *window;
2285 ModestMsgEditWindowPrivate *priv;
2290 case GTK_RESPONSE_OK:
2291 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2297 window = MODEST_MSG_EDIT_WINDOW (user_data);
2298 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2300 /* allowed size is the maximum size - what's already there */
2301 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2302 &att_num, &att_size);
2303 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2306 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2308 const gchar *uri = (const gchar *) uri_node->data;
2311 modest_msg_edit_window_attach_file_one (window, uri, allowed_size);
2313 if (total_size > allowed_size) {
2314 g_warning ("%s: total size: %u",
2315 __FUNCTION__, (unsigned int)total_size);
2318 allowed_size -= total_size;
2320 g_slist_foreach (uris, (GFunc) g_free, NULL);
2321 g_slist_free (uris);
2323 gtk_widget_destroy (GTK_WIDGET (dialog));
2327 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2329 GtkWidget *dialog = NULL;
2330 ModestMsgEditWindowPrivate *priv;
2332 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2334 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2336 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2339 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window),
2340 GTK_FILE_CHOOSER_ACTION_OPEN);
2341 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2342 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2343 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2344 GTK_WINDOW (dialog), GTK_WINDOW (window));
2346 /* Connect to response & show */
2347 g_signal_connect (dialog, "response",
2348 G_CALLBACK (on_attach_file_response), window);
2349 gtk_widget_show (dialog);
2354 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2356 GnomeVFSFileSize allowed_size)
2359 GnomeVFSHandle *handle = NULL;
2360 ModestMsgEditWindowPrivate *priv;
2361 GnomeVFSResult result;
2362 GnomeVFSFileSize size = 0;
2363 g_return_val_if_fail (window, 0);
2364 g_return_val_if_fail (uri, 0);
2366 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2368 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2369 if (result == GNOME_VFS_OK) {
2370 TnyMimePart *mime_part;
2372 const gchar *mime_type = NULL;
2374 gchar *escaped_filename;
2377 GnomeVFSFileInfo *info;
2378 GnomeVFSURI *vfs_uri;
2380 gnome_vfs_close (handle);
2381 vfs_uri = gnome_vfs_uri_new (uri);
2384 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2385 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2386 g_free (escaped_filename);
2387 gnome_vfs_uri_unref (vfs_uri);
2389 info = gnome_vfs_file_info_new ();
2391 if (gnome_vfs_get_file_info (uri,
2393 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2395 mime_type = gnome_vfs_file_info_get_mime_type (info);
2396 mime_part = tny_platform_factory_new_mime_part
2397 (modest_runtime_get_platform_factory ());
2399 /* try to get the attachment's size; this may fail for weird
2400 * file systems, like obex, upnp... */
2401 if (allowed_size != 0 &&
2402 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2404 if (size > allowed_size) {
2405 modest_platform_information_banner (NULL, NULL,
2406 _FM("sfil_ib_opening_not_allowed"));
2410 g_warning ("%s: could not get attachment size", __FUNCTION__);
2412 stream = create_stream_for_uri (uri);
2414 if (stream == NULL) {
2416 modest_platform_information_banner (NULL, NULL, _FM("sfil_ib_opening_not_allowed"));
2418 g_object_unref (mime_part);
2419 gnome_vfs_file_info_unref (info);
2423 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2424 g_object_unref (stream);
2426 content_id = g_strdup_printf ("%d", priv->next_cid);
2427 tny_mime_part_set_content_id (mime_part, content_id);
2428 g_free (content_id);
2431 basename = g_path_get_basename (filename);
2432 tny_mime_part_set_filename (mime_part, basename);
2435 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2436 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2438 info->size == 0, info->size);
2439 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2440 gtk_widget_show_all (priv->attachments_caption);
2441 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2443 g_object_unref (mime_part);
2444 gnome_vfs_file_info_unref (info);
2451 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2454 ModestMsgEditWindowPrivate *priv;
2457 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2458 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2460 if (att_list == NULL) {
2461 att_list = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2462 if (!modest_maemo_utils_select_attachments (GTK_WINDOW (window), att_list)) {
2463 g_object_unref (att_list);
2468 g_object_ref (att_list);
2471 if (tny_list_get_length (att_list) == 0) {
2472 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2474 gboolean dialog_response;
2475 gchar *message = NULL;
2476 gchar *filename = NULL;
2478 if (tny_list_get_length (att_list) == 1) {
2480 iter = tny_list_create_iterator (att_list);
2481 part = (TnyMimePart *) tny_iterator_get_current (iter);
2482 g_object_unref (iter);
2483 if (TNY_IS_MSG (part)) {
2484 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2486 filename = tny_header_dup_subject (header);
2487 g_object_unref (header);
2489 if (filename == NULL) {
2490 filename = g_strdup (_("mail_va_no_subject"));
2493 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2495 g_object_unref (part);
2497 filename = g_strdup ("");
2499 message = g_strdup_printf (ngettext("emev_nc_delete_attachment",
2500 "emev_nc_delete_attachments",
2501 tny_list_get_length (att_list)), filename);
2504 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
2508 if (dialog_response != GTK_RESPONSE_OK) {
2509 g_object_unref (att_list);
2513 for (iter = tny_list_create_iterator (att_list);
2514 !tny_iterator_is_done (iter);
2515 tny_iterator_next (iter)) {
2516 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2517 const gchar *att_id;
2518 tny_list_remove (priv->attachments, (GObject *) mime_part);
2520 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2522 if (tny_list_get_length (priv->attachments) == 0)
2523 gtk_widget_hide (priv->attachments_caption);
2524 att_id = tny_mime_part_get_content_id (mime_part);
2526 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2528 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2529 g_object_unref (mime_part);
2531 g_object_unref (iter);
2534 g_object_unref (att_list);
2536 /* if the last attachment has been removed, focus the Subject: field */
2537 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2538 gtk_widget_grab_focus (priv->subject_field);
2542 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2545 ModestMsgEditWindowPrivate *priv;
2546 GdkColor *new_color;
2547 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2549 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2550 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2553 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2555 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2557 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2559 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2564 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
2567 ModestMsgEditWindowPrivate *priv;
2568 gint new_size_index;
2569 ModestMsgEditWindow *window;
2572 window = MODEST_MSG_EDIT_WINDOW (userdata);
2573 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2574 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2576 if (gtk_check_menu_item_get_active (menu_item)) {
2578 WPTextBufferFormat format;
2580 memset (&format, 0, sizeof (format));
2581 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2583 label = gtk_bin_get_child (GTK_BIN (menu_item));
2585 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
2586 format.cs.font_size = TRUE;
2587 format.cs.text_position = TRUE;
2588 format.cs.font = TRUE;
2589 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
2590 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2592 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2593 GINT_TO_POINTER (wp_get_font_size_index (new_size_index, 12))))
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='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
2598 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2604 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
2607 ModestMsgEditWindowPrivate *priv;
2608 gint new_font_index;
2609 ModestMsgEditWindow *window;
2612 window = MODEST_MSG_EDIT_WINDOW (userdata);
2613 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2614 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2616 if (gtk_check_menu_item_get_active (menu_item)) {
2619 label = gtk_bin_get_child (GTK_BIN (menu_item));
2621 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
2623 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2624 GINT_TO_POINTER(new_font_index)))
2625 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2627 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2628 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2629 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2635 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2638 ModestMsgEditWindowPrivate *priv = NULL;
2639 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2641 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2642 if (!priv->update_caption_visibility)
2645 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2647 gtk_widget_show (priv->cc_caption);
2649 gtk_widget_hide (priv->cc_caption);
2651 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2655 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2658 ModestMsgEditWindowPrivate *priv = NULL;
2659 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2661 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2662 if (!priv->update_caption_visibility)
2665 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2667 gtk_widget_show (priv->bcc_caption);
2669 gtk_widget_hide (priv->bcc_caption);
2671 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2675 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2676 ModestRecptEditor *editor)
2678 ModestMsgEditWindowPrivate *priv;
2680 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2681 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2683 /* we check for low-mem; in that case, show a warning, and don't allow
2684 * for the addressbook
2686 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2689 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2691 if (editor == NULL) {
2692 GtkWidget *view_focus;
2693 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2695 /* This code should be kept in sync with ModestRecptEditor. The
2696 textview inside the recpt editor is the one that really gets the
2697 focus. As it's inside a scrolled window, and this one inside the
2698 hbox recpt editor inherits from, we'll need to go up in the
2699 hierarchy to know if the text view is part of the recpt editor
2700 or if it's a different text entry */
2702 if (gtk_widget_get_parent (view_focus)) {
2703 GtkWidget *first_parent;
2705 first_parent = gtk_widget_get_parent (view_focus);
2706 if (gtk_widget_get_parent (first_parent) &&
2707 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2708 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2713 editor = MODEST_RECPT_EDITOR (priv->to_field);
2717 modest_address_book_select_addresses (editor);
2722 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2724 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2726 modest_msg_edit_window_open_addressbook (window, NULL);
2730 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2731 gboolean show_toolbar)
2733 ModestWindowPrivate *parent_priv;
2735 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2736 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2738 /* We can not just use the code of
2739 modest_msg_edit_window_setup_toolbar because it has a
2740 mixture of both initialization and creation code. */
2742 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2744 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2748 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2749 TnyHeaderFlags priority_flags)
2751 ModestMsgEditWindowPrivate *priv;
2752 ModestWindowPrivate *parent_priv;
2754 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2756 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2757 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2759 if (priv->priority_flags != priority_flags) {
2760 GtkAction *priority_action = NULL;
2762 priv->priority_flags = priority_flags;
2764 switch (priority_flags) {
2765 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2766 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2767 MODEST_HEADER_ICON_HIGH,
2768 HILDON_ICON_SIZE_SMALL);
2769 gtk_widget_show (priv->priority_icon);
2770 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2771 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2773 case TNY_HEADER_FLAG_LOW_PRIORITY:
2774 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2775 MODEST_HEADER_ICON_LOW,
2776 HILDON_ICON_SIZE_SMALL);
2777 gtk_widget_show (priv->priority_icon);
2778 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2779 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2782 gtk_widget_hide (priv->priority_icon);
2783 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2784 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2787 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2788 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2790 gtk_widget_queue_resize (priv->subject_box);
2794 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2797 ModestMsgEditWindowPrivate *priv;
2798 ModestWindowPrivate *parent_priv;
2799 gint current_format;
2801 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2803 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2804 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2806 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2807 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2809 if (current_format != file_format) {
2810 switch (file_format) {
2811 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2812 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2813 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
2815 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2819 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2820 response = gtk_dialog_run (GTK_DIALOG (dialog));
2821 gtk_widget_destroy (dialog);
2822 if (response == GTK_RESPONSE_OK) {
2823 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2825 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
2826 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
2831 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2832 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2833 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2838 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2841 ModestMsgEditWindowPrivate *priv;
2842 WPTextBufferFormat oldfmt, fmt;
2843 gint old_position = 0;
2847 GdkColor *color = NULL;
2848 gboolean bold, bold_set, italic, italic_set;
2849 gboolean underline, underline_set;
2850 gboolean strikethrough, strikethrough_set;
2851 gboolean position_set;
2852 gboolean font_size_set, font_set, color_set;
2855 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2856 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2858 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2859 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
2860 GTK_WINDOW(dialog), GTK_WINDOW (window));
2862 /* First we get the currently selected font information */
2863 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2865 switch (oldfmt.text_position) {
2866 case TEXT_POSITION_NORMAL:
2869 case TEXT_POSITION_SUPERSCRIPT:
2877 g_object_set (G_OBJECT (dialog),
2878 "bold", oldfmt.bold != FALSE,
2879 "bold-set", !oldfmt.cs.bold,
2880 "underline", oldfmt.underline != FALSE,
2881 "underline-set", !oldfmt.cs.underline,
2882 "italic", oldfmt.italic != FALSE,
2883 "italic-set", !oldfmt.cs.italic,
2884 "strikethrough", oldfmt.strikethrough != FALSE,
2885 "strikethrough-set", !oldfmt.cs.strikethrough,
2886 "color", &oldfmt.color,
2887 "color-set", !oldfmt.cs.color,
2888 "size", wp_font_size[oldfmt.font_size],
2889 "size-set", !oldfmt.cs.font_size,
2890 "position", old_position,
2891 "position-set", !oldfmt.cs.text_position,
2892 "family", wp_get_font_name (oldfmt.font),
2893 "family-set", !oldfmt.cs.font,
2896 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2897 GTK_WINDOW (dialog), GTK_WINDOW (window));
2898 gtk_widget_show_all (dialog);
2899 priv->font_dialog = dialog;
2900 response = gtk_dialog_run (GTK_DIALOG (dialog));
2901 priv->font_dialog = NULL;
2902 if (response == GTK_RESPONSE_OK) {
2904 g_object_get( dialog,
2906 "bold-set", &bold_set,
2907 "underline", &underline,
2908 "underline-set", &underline_set,
2910 "italic-set", &italic_set,
2911 "strikethrough", &strikethrough,
2912 "strikethrough-set", &strikethrough_set,
2914 "color-set", &color_set,
2916 "size-set", &font_size_set,
2917 "family", &font_name,
2918 "family-set", &font_set,
2919 "position", &position,
2920 "position-set", &position_set,
2925 if (response == GTK_RESPONSE_OK) {
2926 memset(&fmt, 0, sizeof(fmt));
2932 fmt.italic = italic;
2933 fmt.cs.italic = TRUE;
2935 if (underline_set) {
2936 fmt.underline = underline;
2937 fmt.cs.underline = TRUE;
2939 if (strikethrough_set) {
2940 fmt.strikethrough = strikethrough;
2941 fmt.cs.strikethrough = TRUE;
2946 ? TEXT_POSITION_NORMAL
2947 : ( ( position == 1 )
2948 ? TEXT_POSITION_SUPERSCRIPT
2949 : TEXT_POSITION_SUBSCRIPT );
2950 fmt.cs.text_position = TRUE;
2951 fmt.font_size = oldfmt.font_size;
2955 fmt.cs.color = TRUE;
2958 fmt.font = wp_get_font_index(font_name,
2963 if (font_size_set) {
2964 fmt.cs.font_size = TRUE;
2965 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
2967 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2968 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2970 gtk_widget_destroy (dialog);
2972 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2976 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2978 ModestMsgEditWindowPrivate *priv;
2980 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2981 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2983 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2985 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2986 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2990 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
2992 ModestMsgEditWindowPrivate *priv;
2994 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2995 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2997 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
2999 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3000 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3005 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
3007 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3009 priv->can_undo = can_undo;
3013 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
3015 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3017 priv->can_redo = can_redo;
3021 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3023 ModestMsgEditWindowPrivate *priv;
3024 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3025 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3027 return priv->can_undo;
3031 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3033 ModestMsgEditWindowPrivate *priv;
3034 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3035 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3037 return priv->can_redo;
3042 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3045 GtkTextIter match_start, match_end;
3047 if (image_id == NULL)
3050 gtk_text_buffer_get_start_iter (buffer, &iter);
3052 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3053 GSList *tags = gtk_text_iter_get_tags (&match_start);
3055 for (node = tags; node != NULL; node = g_slist_next (node)) {
3056 GtkTextTag *tag = (GtkTextTag *) node->data;
3057 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3058 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3059 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3061 offset = gtk_text_iter_get_offset (&match_start);
3062 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3063 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3067 gtk_text_iter_forward_char (&iter);
3072 message_is_empty (ModestMsgEditWindow *window)
3074 ModestMsgEditWindowPrivate *priv = NULL;
3076 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3077 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3079 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3080 * so we can ignore markup.
3082 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3085 count = gtk_text_buffer_get_char_count (buf);
3091 msg_body_focus (GtkWidget *focus,
3092 GdkEventFocus *event,
3096 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3097 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3098 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3103 recpt_field_changed (GtkTextBuffer *buffer,
3104 ModestMsgEditWindow *editor)
3106 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3107 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3111 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3113 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3114 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3118 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3121 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3122 GtkTextBuffer *buffer;
3124 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3125 gtk_text_buffer_set_modified (buffer, modified);
3126 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3127 gtk_text_buffer_set_modified (buffer, modified);
3128 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3129 gtk_text_buffer_set_modified (buffer, modified);
3130 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3134 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3136 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3137 const char *account_name;
3138 GtkTextBuffer *buffer;
3140 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3141 if (gtk_text_buffer_get_modified (buffer))
3143 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3144 if (gtk_text_buffer_get_modified (buffer))
3146 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3147 if (gtk_text_buffer_get_modified (buffer))
3149 if (gtk_text_buffer_get_modified (priv->text_buffer))
3151 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3152 if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3163 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3165 ModestMsgEditWindowPrivate *priv = NULL;
3167 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3168 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3170 /* check if there's no recipient added */
3171 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3172 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3173 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3174 /* no recipient contents, then select contacts */
3175 modest_msg_edit_window_open_addressbook (window, NULL);
3179 g_object_ref (window);
3180 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3181 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3182 g_object_unref (window);
3185 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3186 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3187 g_object_unref (window);
3190 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3191 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3192 g_object_unref (window);
3196 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3197 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3198 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3199 g_object_unref (window);
3206 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3207 ModestMsgEditWindow *window)
3209 modest_msg_edit_window_offer_attach_file (window);
3213 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3215 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3217 return priv->clipboard_text;
3221 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3223 ModestMsgEditWindow *window)
3225 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3226 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3228 if (!GTK_WIDGET_VISIBLE (window))
3231 g_object_ref (window);
3232 text = gtk_clipboard_wait_for_text (selection_clipboard);
3234 if (priv->clipboard_text != NULL) {
3235 g_free (priv->clipboard_text);
3237 priv->clipboard_text = text;
3239 if (GTK_WIDGET_VISIBLE (window)) {
3240 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3242 g_object_unref (window);
3245 static gboolean clipboard_owner_change_idle (gpointer userdata)
3247 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3248 ModestMsgEditWindowPrivate *priv;
3250 gdk_threads_enter ();
3251 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3252 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3254 priv->clipboard_owner_idle = 0;
3255 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3256 gdk_threads_leave ();
3262 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3264 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3265 if (priv->clipboard_owner_idle == 0) {
3266 priv->clipboard_owner_idle = g_idle_add (clipboard_owner_change_idle, window);
3271 subject_field_move_cursor (GtkEntry *entry,
3272 GtkMovementStep step,
3277 if (!GTK_WIDGET_VISIBLE (window))
3280 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3284 update_window_title (ModestMsgEditWindow *window)
3286 ModestMsgEditWindowPrivate *priv = NULL;
3287 const gchar *subject;
3289 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3290 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3291 if (subject == NULL || subject[0] == '\0')
3292 subject = _("mail_va_new_email");
3294 gtk_window_set_title (GTK_WINDOW (window), subject);
3299 subject_field_changed (GtkEditable *editable,
3300 ModestMsgEditWindow *window)
3302 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3303 update_window_title (window);
3304 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3305 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3306 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3310 subject_field_insert_text (GtkEditable *editable,
3312 gint new_text_length,
3314 ModestMsgEditWindow *window)
3316 GString *result = g_string_new ("");
3318 gint result_len = 0;
3319 const gchar *entry_text = NULL;
3322 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3323 old_length = g_utf8_strlen (entry_text, -1);
3325 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3326 gunichar c = g_utf8_get_char_validated (current, 8);
3327 /* Invalid unichar, stop */
3333 result = g_string_append_unichar (result, c);
3337 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3338 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3341 /* Prevent endless recursion */
3342 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3343 g_signal_emit_by_name (editable, "insert-text",
3344 (gpointer) result->str, (gpointer) result->len,
3345 (gpointer) position, (gpointer) window);
3346 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3350 if (result_len + old_length > 1000) {
3351 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3352 _CS("ckdg_ib_maximum_characters_reached"));
3354 g_string_free (result, TRUE);
3358 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3361 ModestMsgEditWindowPrivate *priv = NULL;
3363 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3364 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3366 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3369 gtk_widget_show_all (priv->find_toolbar);
3370 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3372 gtk_widget_hide_all (priv->find_toolbar);
3373 gtk_widget_grab_focus (priv->msg_body);
3378 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3380 GtkTextIter *match_start,
3381 GtkTextIter *match_end)
3383 GtkTextIter end_iter;
3384 gchar *str_casefold;
3387 gchar *range_casefold;
3390 gboolean result = FALSE;
3397 gtk_text_iter_forward_to_end (&end_iter);
3399 str_casefold = g_utf8_casefold (str, -1);
3400 str_chars_n = strlen (str);
3402 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3403 range_casefold = g_utf8_casefold (range_text, -1);
3404 range_chars_n = strlen (range_casefold);
3406 if (range_chars_n < str_chars_n) {
3407 g_free (str_casefold);
3408 g_free (range_text);
3409 g_free (range_casefold);
3413 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3414 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3415 if (!g_utf8_collate (range_subtext, str_casefold)) {
3416 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3418 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3419 match_start, match_end, NULL);
3420 g_free (found_text);
3422 g_free (range_subtext);
3426 g_free (str_casefold);
3427 g_free (range_text);
3428 g_free (range_casefold);
3435 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3436 ModestMsgEditWindow *window)
3438 gchar *current_search = NULL;
3439 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3441 GtkTextIter selection_start, selection_end;
3442 GtkTextIter match_start, match_end;
3443 gboolean continue_search = FALSE;
3445 if (message_is_empty (window)) {
3446 g_free (priv->last_search);
3447 priv->last_search = NULL;
3448 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3452 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3453 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3454 g_free (current_search);
3455 g_free (priv->last_search);
3456 priv->last_search = NULL;
3457 /* Information banner about empty search */
3458 hildon_banner_show_information (NULL, NULL, _CS("ecdg_ib_find_rep_enter_text"));
3462 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3463 continue_search = TRUE;
3465 g_free (priv->last_search);
3466 priv->last_search = g_strdup (current_search);
3469 if (continue_search) {
3470 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3471 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3472 &match_start, &match_end);
3474 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_search_complete"));
3476 GtkTextIter buffer_start;
3477 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3478 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3479 &match_start, &match_end);
3481 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_no_matches"));
3484 /* Mark as selected the string found in search */
3486 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3487 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3488 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3490 g_free (priv->last_search);
3491 priv->last_search = NULL;
3493 g_free (current_search);
3497 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3499 ModestMsgEditWindowPrivate *priv;
3501 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3506 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3509 ModestMsgEditWindowPrivate *priv;
3511 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3516 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3517 ModestMsgEditWindow *window)
3519 modest_msg_edit_window_toggle_find_toolbar (window, FALSE);
3523 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3526 ModestMsgEditWindowPrivate *priv;
3527 TnyHeader *header = NULL;
3529 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3530 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3532 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3533 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3535 if (priv->draft_msg != NULL) {
3536 g_object_unref (priv->draft_msg);
3539 if (draft != NULL) {
3540 g_object_ref (draft);
3541 header = tny_msg_get_header (draft);
3542 if (priv->msg_uid) {
3543 g_free (priv->msg_uid);
3544 priv->msg_uid = NULL;
3546 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3547 if (GTK_WIDGET_REALIZED (window)) {
3548 if (!modest_window_mgr_register_window (mgr, MODEST_WINDOW (window), NULL)) {
3549 gtk_widget_destroy (GTK_WIDGET (window));
3555 priv->draft_msg = draft;
3559 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3560 GtkTextIter *start, GtkTextIter *end,
3563 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3564 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3567 if (tag == NULL) return;
3568 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3569 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3570 replace_with_images (window, priv->images);
3575 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3578 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3580 g_return_if_fail (TNY_IS_MIME_PART (part));
3581 tny_list_prepend (priv->attachments, (GObject *) part);
3582 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3583 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3584 gtk_widget_show_all (priv->attachments_caption);
3585 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3589 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3591 ModestMsgEditWindowPrivate *priv;
3593 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3594 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3596 return priv->msg_uid;
3600 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3601 ModestMsgEditWindowWidgetType widget_type)
3603 ModestMsgEditWindowPrivate *priv;
3605 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3606 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3608 switch (widget_type) {
3609 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3610 return priv->msg_body;
3612 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3613 return priv->to_field;
3615 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3616 return priv->cc_field;
3618 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3619 return priv->bcc_field;
3621 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3622 return priv->subject_field;
3624 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3625 return priv->attachments_view;
3633 remove_tags (WPTextBuffer *buffer)
3635 GtkTextIter start, end;
3637 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3638 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3640 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3644 on_account_removed (TnyAccountStore *account_store,
3645 TnyAccount *account,
3648 /* Do nothing if it's a store account, because we use the
3649 transport to send the messages */
3650 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3651 const gchar *parent_acc = NULL;
3652 const gchar *our_acc = NULL;
3654 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3655 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3656 /* Close this window if I'm showing a message of the removed account */
3657 if (strcmp (parent_acc, our_acc) == 0)
3658 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3663 from_field_changed (HildonPickerButton *button,
3664 ModestMsgEditWindow *self)
3666 ModestMsgEditWindowPrivate *priv;
3667 gboolean has_old_signature, has_new_signature;
3669 GtkTextIter match_start, match_end;
3670 ModestAccountMgr *mgr;
3672 gchar *full_signature;
3674 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3676 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
3677 mgr = modest_runtime_get_account_mgr ();
3678 signature = modest_account_mgr_get_signature (mgr, priv->last_from_account, &has_old_signature);
3679 if (has_old_signature) {
3680 full_signature = g_strconcat ("\n--\n", signature, NULL);
3681 if (gtk_text_iter_forward_search (&iter, full_signature, 0, &match_start, &match_end, NULL)) {
3682 gtk_text_buffer_delete (priv->text_buffer, &match_start, &match_end);
3684 } else if (gtk_text_iter_forward_search (&iter, _("mcen_ia_editor_original_message"), 0,
3685 &match_start, &match_end, NULL)) {
3688 g_free (full_signature);
3692 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3693 signature = modest_account_mgr_get_signature (mgr, priv->last_from_account, &has_new_signature);
3694 if (has_new_signature) {
3695 full_signature = g_strconcat ("\n--\n", signature, NULL);
3696 gtk_text_buffer_insert (priv->text_buffer, &iter, full_signature, -1);
3697 g_free (full_signature);
3702 typedef struct _MessageSettingsHelper {
3703 ModestMsgEditWindow *window;
3704 GSList *priority_group;
3705 GSList *format_group;
3706 GtkToggleButton *current_priority;
3707 GtkToggleButton *current_format;
3708 } MessageSettingsHelper;
3711 on_priority_toggle (GtkToggleButton *button,
3712 MessageSettingsHelper *helper)
3715 ModestMsgEditWindowPrivate *priv;
3717 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3718 if (gtk_toggle_button_get_active (button)) {
3720 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3721 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3722 if ((node_button != button) &&
3723 gtk_toggle_button_get_active (node_button)) {
3724 gtk_toggle_button_set_active (node_button, FALSE);
3727 helper->current_priority = button;
3729 gboolean found = FALSE;
3730 /* If no one is active, activate it again */
3731 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3732 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3733 if (gtk_toggle_button_get_active (node_button)) {
3739 gtk_toggle_button_set_active (button, TRUE);
3745 on_format_toggle (GtkToggleButton *button,
3746 MessageSettingsHelper *helper)
3749 ModestMsgEditWindowPrivate *priv;
3751 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3752 if (gtk_toggle_button_get_active (button)) {
3754 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
3755 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3756 if ((node_button != button) &&
3757 gtk_toggle_button_get_active (node_button)) {
3758 gtk_toggle_button_set_active (node_button, FALSE);
3761 helper->current_format = button;
3763 gboolean found = FALSE;
3764 /* If no one is active, activate it again */
3765 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
3766 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3767 if (gtk_toggle_button_get_active (node_button)) {
3773 gtk_toggle_button_set_active (button, TRUE);
3780 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
3784 GtkWidget *priority_hbox;
3785 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
3786 GtkWidget *captioned;
3787 GtkSizeGroup *title_sizegroup, *value_sizegroup;
3788 GtkWidget *format_hbox;
3789 GtkWidget *html_toggle, *text_toggle;
3790 ModestMsgEditWindowPrivate *priv;
3791 MessageSettingsHelper helper = {0,};
3793 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3794 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3795 helper.window = window;
3796 helper.priority_group = NULL;
3798 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3799 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3801 dialog = gtk_dialog_new_with_buttons (_("mcen_me_message_settings"), NULL,
3802 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
3803 _HL("wdgt_bd_done"), GTK_RESPONSE_ACCEPT, NULL);
3804 vbox = gtk_vbox_new (FALSE, 0);
3805 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), vbox);
3806 gtk_widget_show (vbox);
3808 /* Priority toggles */
3809 priority_hbox = gtk_hbox_new (TRUE, 0);
3810 high_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3811 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
3812 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
3813 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
3814 medium_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3815 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
3816 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
3817 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
3818 low_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3819 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
3820 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
3821 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
3822 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, TRUE, TRUE, 0);
3823 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, TRUE, TRUE, 0);
3824 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, TRUE, TRUE, 0);
3825 gtk_widget_show_all (priority_hbox);
3826 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
3827 _("mcen_me_editor_message_priority"), FALSE, priority_hbox);
3828 gtk_widget_show (captioned);
3829 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
3831 /* format toggles */
3832 format_hbox = gtk_hbox_new (TRUE, 0);
3833 html_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3834 gtk_button_set_label (GTK_BUTTON (html_toggle), _("mcen_me_editor_formatted_text"));
3835 helper.format_group = g_slist_prepend (helper.format_group, html_toggle);
3836 g_object_set_data (G_OBJECT (html_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_HTML));
3837 g_object_set_data (G_OBJECT (html_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_FORMATTED_TEXT));
3838 text_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3839 gtk_button_set_label (GTK_BUTTON (text_toggle), _("mcen_me_editor_plain_text"));
3840 helper.format_group = g_slist_prepend (helper.format_group, text_toggle);
3841 g_object_set_data (G_OBJECT (text_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_TEXT));
3842 g_object_set_data (G_OBJECT (text_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_PLAIN_TEXT));
3843 gtk_box_pack_start (GTK_BOX (format_hbox), html_toggle, TRUE, TRUE, 0);
3844 gtk_box_pack_start (GTK_BOX (format_hbox), text_toggle, TRUE, TRUE, 0);
3845 gtk_widget_show_all (format_hbox);
3846 gtk_widget_show (format_hbox);
3847 gtk_box_pack_start (GTK_BOX (vbox), format_hbox, FALSE, FALSE, 0);
3850 g_object_unref (title_sizegroup);
3851 g_object_unref (value_sizegroup);
3853 /* Set current values */
3854 switch (priv->priority_flags) {
3855 case TNY_HEADER_FLAG_HIGH_PRIORITY:
3856 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (high_toggle), TRUE);
3857 helper.current_priority = GTK_TOGGLE_BUTTON (high_toggle);
3859 case TNY_HEADER_FLAG_LOW_PRIORITY:
3860 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (low_toggle), TRUE);
3861 helper.current_priority = GTK_TOGGLE_BUTTON (low_toggle);
3864 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (medium_toggle), TRUE);
3865 helper.current_priority = GTK_TOGGLE_BUTTON (medium_toggle);
3869 switch (modest_msg_edit_window_get_format (window)) {
3870 case MODEST_MSG_EDIT_FORMAT_TEXT:
3871 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_toggle), TRUE);
3872 helper.current_format = GTK_TOGGLE_BUTTON (text_toggle);
3874 case MODEST_MSG_EDIT_FORMAT_HTML:
3876 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (html_toggle), TRUE);
3877 helper.current_format = GTK_TOGGLE_BUTTON (html_toggle);
3881 /* Signal connects */
3882 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3883 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3884 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3885 g_signal_connect (G_OBJECT (html_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
3886 g_signal_connect (G_OBJECT (text_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
3888 /* Save settings if the user clicked on done */
3889 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
3890 TnyHeaderFlags flags;
3891 ModestMsgEditFormat old_format, new_format;
3893 /* Set priority flags */
3894 flags = (TnyHeaderFlags) g_object_get_data (G_OBJECT (helper.current_priority), "priority");
3895 if (priv->priority_flags != flags)
3896 modest_msg_edit_window_set_priority_flags (window, flags);
3898 /* Set edit format */
3899 old_format = modest_msg_edit_window_get_format (window);
3900 new_format = (ModestMsgEditFormat) g_object_get_data (G_OBJECT (helper.current_format), "format");
3901 if (old_format != new_format) {
3902 gint file_format = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (helper.current_format), "file-format"));
3903 modest_msg_edit_window_set_file_format (window, file_format);
3907 gtk_widget_destroy (dialog);
3908 g_slist_free (helper.priority_group);
3912 on_message_settings (GtkAction *action,
3913 ModestMsgEditWindow *window)
3915 modest_msg_edit_window_show_msg_settings_dialog (window);
3919 on_cc_button_toggled (HildonCheckButton *button,
3920 ModestMsgEditWindow *window)
3922 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
3924 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
3925 hildon_check_button_get_active (button));
3929 on_bcc_button_toggled (HildonCheckButton *button,
3930 ModestMsgEditWindow *window)
3932 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
3934 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
3935 hildon_check_button_get_active (button));
3939 setup_menu (ModestMsgEditWindow *self)
3941 ModestMsgEditWindowPrivate *priv = NULL;
3943 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
3945 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3947 /* Settings menu buttons */
3948 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_checknames"), NULL,
3949 APP_MENU_CALLBACK (modest_ui_actions_on_check_names),
3951 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_undo"), "<Ctrl>z",
3952 APP_MENU_CALLBACK (modest_ui_actions_on_undo),
3953 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_undo));
3955 priv->cc_button = hildon_check_button_new (0);
3956 gtk_button_set_label (GTK_BUTTON (priv->cc_button), _("mcen_me_editor_showcc"));
3957 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button),
3959 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->cc_button),
3961 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
3962 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
3963 priv->bcc_button = hildon_check_button_new (0);
3964 gtk_button_set_label (GTK_BUTTON (priv->bcc_button), _("mcen_me_editor_showbcc"));
3965 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button),
3967 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->bcc_button),
3969 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
3970 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
3972 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_attach_inlineimage"), NULL,
3973 APP_MENU_CALLBACK (modest_ui_actions_on_insert_image),
3974 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_set_style));
3975 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_remove_attachments"), NULL,
3976 APP_MENU_CALLBACK (modest_ui_actions_on_remove_attachments),
3977 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
3978 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_message_settings"), NULL,
3979 APP_MENU_CALLBACK (on_message_settings),
3981 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_viewer_find"), "<Ctrl>f",
3982 APP_MENU_CALLBACK (modest_ui_actions_on_toggle_find_in_page),