1 /* Copyright (c) 2006, Nokia Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of the Nokia Corporation nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include <glib/gi18n.h>
33 #include <glib/gstdio.h>
35 #include <tny-account-store.h>
36 #include <tny-fs-stream.h>
37 #include <tny-vfs-stream.h>
38 #include <tny-camel-mem-stream.h>
42 #include <modest-account-mgr.h>
43 #include <modest-account-mgr-helpers.h>
45 #include <widgets/modest-msg-edit-window.h>
46 #include <modest-selector-picker.h>
47 #include <widgets/modest-recpt-editor.h>
48 #include <widgets/modest-attachments-view.h>
50 #include <modest-runtime.h>
52 #include "modest-platform.h"
53 #include "modest-icon-names.h"
54 #include "modest-widget-memory.h"
55 #include "modest-window-priv.h"
56 #include "modest-mail-operation.h"
57 #include "modest-tny-platform-factory.h"
58 #include "modest-tny-msg.h"
59 #include "modest-tny-folder.h"
60 #include "modest-tny-account.h"
61 #include "modest-address-book.h"
62 #include "modest-text-utils.h"
63 #include <tny-simple-list.h>
64 #include <wptextview.h>
65 #include <wptextbuffer.h>
66 #include <hildon/hildon-pannable-area.h>
67 #include "modest-msg-edit-window-ui-dimming.h"
69 #include "modest-hildon-includes.h"
70 #ifdef MODEST_HAVE_HILDON0_WIDGETS
71 #include <hildon-widgets/hildon-color-chooser.h>
73 #include "widgets/modest-msg-edit-window-ui.h"
74 #ifdef MODEST_HAVE_HILDON0_WIDGETS
75 #include <libgnomevfs/gnome-vfs-mime-utils.h>
77 #include <libgnomevfs/gnome-vfs-mime.h>
79 #include <modest-utils.h>
80 #include "modest-maemo-utils.h"
81 #include <modest-ui-constants.h>
84 #define DEFAULT_FONT_SIZE 3
85 #define DEFAULT_FONT 2
86 #define DEFAULT_SIZE_BUTTON_FONT_FAMILY "Sans"
87 #define DEFAULT_MAIN_VBOX_SPACING 6
88 #define SUBJECT_MAX_LENGTH 1000
89 #define IMAGE_MAX_WIDTH 560
90 #define DEFAULT_FONT_SCALE 1.5
91 #define ATTACHMENT_BUTTON_WIDTH 118
93 static gboolean is_wp_text_buffer_started = FALSE;
95 static void modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass);
96 static void modest_msg_edit_window_init (ModestMsgEditWindow *obj);
97 static void modest_msg_edit_window_finalize (GObject *obj);
99 static gboolean msg_body_focus (GtkWidget *focus, GdkEventFocus *event, gpointer userdata);
100 static void body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
101 static void recpt_field_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
103 static void text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window);
104 static void text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window);
105 static void text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window);
106 static void text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
107 GtkTextIter *start, GtkTextIter *end,
109 static void text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id);
110 static void subject_field_changed (GtkEditable *editable, ModestMsgEditWindow *window);
111 static void subject_field_insert_text (GtkEditable *editable,
113 gint new_text_length,
115 ModestMsgEditWindow *window);
116 static void modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
118 static void modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
120 static void modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
122 static void modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
124 static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
125 ModestRecptEditor *editor);
126 static void modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
127 ModestMsgEditWindow *window);
129 /* ModestWindow methods implementation */
130 static void modest_msg_edit_window_disconnect_signals (ModestWindow *window);
131 static void modest_msg_edit_window_show_toolbar (ModestWindow *window,
132 gboolean show_toolbar);
133 static void modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
135 ModestMsgEditWindow *window);
136 static void modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window);
137 static void subject_field_move_cursor (GtkEntry *entry,
138 GtkMovementStep step,
142 static void update_window_title (ModestMsgEditWindow *window);
145 static void modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
146 ModestMsgEditWindow *window);
147 static void modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
148 ModestMsgEditWindow *window);
149 static gboolean gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
151 GtkTextIter *match_start,
152 GtkTextIter *match_end);
154 static void remove_tags (WPTextBuffer *buffer);
156 static void on_account_removed (TnyAccountStore *account_store,
160 static void init_window (ModestMsgEditWindow *obj);
162 gboolean scroll_drag_timeout (gpointer userdata);
163 static void correct_scroll (ModestMsgEditWindow *w);
164 static void correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused);
165 static void text_buffer_end_user_action (GtkTextBuffer *buffer,
166 ModestMsgEditWindow *userdata);
167 static void text_buffer_mark_set (GtkTextBuffer *buffer,
170 ModestMsgEditWindow *userdata);
171 static void on_message_settings (GtkAction *action,
172 ModestMsgEditWindow *window);
173 static void setup_menu (ModestMsgEditWindow *self);
175 static void from_field_changed (HildonPickerButton *button,
176 ModestMsgEditWindow *self);
177 static void DEBUG_BUFFER (WPTextBuffer *buffer)
181 g_message ("BEGIN BUFFER OF SIZE %d", gtk_text_buffer_get_char_count (GTK_TEXT_BUFFER (buffer)));
183 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &iter);
184 while (!gtk_text_iter_is_end (&iter)) {
185 GString *output = g_string_new ("");
186 GSList *toggled_tags;
189 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
190 g_string_append_printf (output, "%d: CLOSED [ ", gtk_text_iter_get_offset (&iter));
191 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
192 GtkTextTag *tag = (GtkTextTag *) node->data;
194 g_object_get (G_OBJECT (tag), "name", &name, NULL);
195 output = g_string_append (output, name);
196 g_string_append (output, " ");
198 output = g_string_append (output, "] OPENED [ ");
199 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
200 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
201 GtkTextTag *tag = (GtkTextTag *) node->data;
203 g_object_get (G_OBJECT (tag), "name", &name, NULL);
204 output = g_string_append (output, name);
205 g_string_append (output, " ");
207 output = g_string_append (output, "]\n");
208 g_message ("%s", output->str);
209 g_string_free (output, TRUE);
210 gtk_text_iter_forward_to_tag_toggle (&iter, NULL);
212 g_message ("END BUFFER");
216 static const GtkActionEntry hildon2_msg_edit_action_entries [] = {
217 { "MessageSettings", NULL, N_("mcen_me_message_settings"), NULL, NULL, G_CALLBACK (on_message_settings)},
221 /* static gboolean */
222 /* on_key_pressed (GtkWidget *self, */
223 /* GdkEventKey *event, */
224 /* gpointer user_data); */
226 /* list my signals */
233 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
234 struct _ModestMsgEditWindowPrivate {
237 GtkWidget *header_box;
239 ModestPairList *from_field_protos;
240 GtkWidget *from_field;
241 gchar *last_from_account;
242 gchar *original_account_name;
246 GtkWidget *bcc_field;
247 GtkWidget *subject_field;
248 GtkWidget *attachments_view;
249 GtkWidget *priority_icon;
250 GtkWidget *add_attachment_button;
252 GtkWidget *cc_caption;
253 GtkWidget *bcc_caption;
254 gboolean update_caption_visibility;
255 GtkWidget *attachments_caption;
257 GtkTextBuffer *text_buffer;
259 GtkWidget *font_size_toolitem;
260 GtkWidget *font_face_toolitem;
261 GtkWidget *font_color_button;
262 GtkWidget *font_color_toolitem;
263 GSList *font_items_group;
264 GtkWidget *font_tool_button_label;
265 GSList *size_items_group;
266 GtkWidget *size_tool_button_label;
268 GtkWidget *find_toolbar;
271 GtkWidget *font_dialog;
274 guint correct_scroll_idle;
275 guint scroll_drag_timeout_id;
279 TnyList *attachments;
284 TnyHeaderFlags priority_flags;
286 gboolean can_undo, can_redo;
287 gulong clipboard_change_handler_id;
288 gulong default_clipboard_change_handler_id;
289 gulong account_removed_handler_id;
290 guint clipboard_owner_idle;
291 gchar *clipboard_text;
300 GtkWidget *cc_button;
301 GtkWidget *bcc_button;
304 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
305 MODEST_TYPE_MSG_EDIT_WINDOW, \
306 ModestMsgEditWindowPrivate))
308 static GtkWindowClass *parent_class = NULL;
310 /* uncomment the following if you have defined any signals */
311 /* static guint signals[LAST_SIGNAL] = {0}; */
314 modest_msg_edit_window_get_type (void)
316 static GType my_type = 0;
318 static const GTypeInfo my_info = {
319 sizeof(ModestMsgEditWindowClass),
320 NULL, /* base init */
321 NULL, /* base finalize */
322 (GClassInitFunc) modest_msg_edit_window_class_init,
323 NULL, /* class finalize */
324 NULL, /* class data */
325 sizeof(ModestMsgEditWindow),
327 (GInstanceInitFunc) modest_msg_edit_window_init,
330 my_type = g_type_register_static (MODEST_TYPE_HILDON2_WINDOW,
331 "ModestMsgEditWindow",
339 save_state (ModestWindow *self)
341 modest_widget_memory_save (modest_runtime_get_conf(),
342 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
347 restore_settings (ModestMsgEditWindow *self)
349 ModestConf *conf = NULL;
351 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
353 conf = modest_runtime_get_conf ();
355 /* Dim at start clipboard actions */
356 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
357 gtk_action_set_sensitive (action, FALSE);
358 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
359 gtk_action_set_sensitive (action, FALSE);
360 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
361 gtk_action_set_sensitive (action, FALSE);
363 modest_widget_memory_restore (conf, G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
368 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
370 GObjectClass *gobject_class;
371 ModestWindowClass *modest_window_class;
372 gobject_class = (GObjectClass*) klass;
373 modest_window_class = (ModestWindowClass*) klass;
375 parent_class = g_type_class_peek_parent (klass);
376 gobject_class->finalize = modest_msg_edit_window_finalize;
378 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
379 modest_window_class->save_state_func = save_state;
380 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
382 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
386 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
388 ModestMsgEditWindowPrivate *priv;
389 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
391 priv->msg_body = NULL;
393 priv->from_field = NULL;
394 priv->to_field = NULL;
395 priv->cc_field = NULL;
396 priv->bcc_field = NULL;
397 priv->subject_field = NULL;
398 priv->attachments = TNY_LIST (tny_simple_list_new ());
399 priv->images = TNY_LIST (tny_simple_list_new ());
400 priv->images_size = 0;
401 priv->images_count = 0;
404 priv->cc_caption = NULL;
405 priv->bcc_caption = NULL;
406 priv->update_caption_visibility = FALSE;
408 priv->priority_flags = 0;
410 priv->find_toolbar = NULL;
411 priv->last_search = NULL;
413 priv->draft_msg = NULL;
414 priv->outbox_msg = NULL;
415 priv->msg_uid = NULL;
417 priv->can_undo = FALSE;
418 priv->can_redo = FALSE;
419 priv->clipboard_change_handler_id = 0;
420 priv->default_clipboard_change_handler_id = 0;
421 priv->account_removed_handler_id = 0;
422 priv->clipboard_owner_idle = 0;
423 priv->clipboard_text = NULL;
426 priv->scroll_drag_timeout_id = 0;
427 priv->correct_scroll_idle = 0;
428 priv->last_upper = 0.0;
430 priv->font_dialog = NULL;
431 priv->app_menu = NULL;
433 if (!is_wp_text_buffer_started) {
434 is_wp_text_buffer_started = TRUE;
435 wp_text_buffer_library_init ();
440 hildon_program_add_window (hildon_program_get_instance(),
446 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
448 static ModestPairList*
449 get_transports (void)
451 GSList *transports = NULL;
453 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
454 GSList *accounts = modest_account_mgr_account_names (account_mgr,
455 TRUE /* only enabled accounts. */);
457 GSList *cursor = accounts;
459 gchar *account_name = cursor->data;
460 gchar *from_string = NULL;
462 from_string = modest_account_mgr_get_from_string (account_mgr,
466 if (from_string && account_name) {
467 gchar *name = account_name;
468 ModestPair *pair = modest_pair_new ((gpointer) name,
469 (gpointer) from_string , TRUE);
470 transports = g_slist_prepend (transports, pair);
473 cursor = cursor->next;
475 g_slist_free (accounts); /* only free the accounts, not the elements,
476 * because they are used in the pairlist */
480 static void window_focus (GtkWindow *window,
484 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
488 scroll_drag_timeout (gpointer userdata)
490 ModestMsgEditWindow *win = (ModestMsgEditWindow *) userdata;
491 ModestMsgEditWindowPrivate *priv;
493 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(win);
495 correct_scroll_without_drag_check (win, TRUE);
497 priv->scroll_drag_timeout_id = 0;
503 correct_scroll_without_drag_check_idle (gpointer userdata)
505 ModestMsgEditWindow *w = (ModestMsgEditWindow *) userdata;
506 ModestMsgEditWindowPrivate *priv;
508 GdkRectangle rectangle;
513 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
515 insert = gtk_text_buffer_get_insert (priv->text_buffer);
516 gtk_text_buffer_get_iter_at_mark (priv->text_buffer, &iter, insert);
518 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &iter, &rectangle);
519 offset = priv->msg_body->allocation.y;
521 new_value = (offset + rectangle.y);
523 hildon_pannable_area_jump_to (HILDON_PANNABLE_AREA (priv->pannable), -1, new_value);
525 priv->correct_scroll_idle = 0;
530 correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused)
532 ModestMsgEditWindowPrivate *priv;
534 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
536 if (only_if_focused && !gtk_widget_is_focus (priv->msg_body))
539 if (priv->correct_scroll_idle > 0) {
543 priv->correct_scroll_idle = g_idle_add ((GSourceFunc) correct_scroll_without_drag_check_idle,
548 correct_scroll (ModestMsgEditWindow *w)
550 ModestMsgEditWindowPrivate *priv;
552 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
553 if (gtk_grab_get_current () == priv->msg_body) {
554 if (priv->scroll_drag_timeout_id == 0) {
555 priv->scroll_drag_timeout_id = g_timeout_add (500, (GSourceFunc) scroll_drag_timeout,
561 correct_scroll_without_drag_check (w, TRUE);
565 text_buffer_end_user_action (GtkTextBuffer *buffer,
566 ModestMsgEditWindow *userdata)
569 correct_scroll (userdata);
573 text_buffer_mark_set (GtkTextBuffer *buffer,
576 ModestMsgEditWindow *userdata)
578 gtk_text_buffer_begin_user_action (buffer);
579 gtk_text_buffer_end_user_action (buffer);
583 cut_clipboard_check (GtkTextView *text_view,
586 GtkTextBuffer *buffer;
588 buffer = gtk_text_view_get_buffer (text_view);
589 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
590 g_signal_stop_emission_by_name ((gpointer )text_view, "cut-clipboard");
595 copy_clipboard_check (GtkTextView *text_view,
598 GtkTextBuffer *buffer;
600 buffer = gtk_text_view_get_buffer (text_view);
601 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
602 g_signal_stop_emission_by_name ((gpointer )text_view, "copy-clipboard");
607 attachment_deleted (ModestAttachmentsView *attachments_view,
610 modest_msg_edit_window_remove_attachments (MODEST_MSG_EDIT_WINDOW (user_data),
615 connect_signals (ModestMsgEditWindow *obj)
617 ModestMsgEditWindowPrivate *priv;
619 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
621 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
622 G_CALLBACK (text_buffer_refresh_attributes), obj);
623 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
624 G_CALLBACK (text_buffer_can_undo), obj);
625 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
626 G_CALLBACK (text_buffer_can_redo), obj);
627 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
628 G_CALLBACK (body_changed), obj);
629 g_signal_connect (G_OBJECT (priv->text_buffer), "modified-changed",
630 G_CALLBACK (body_changed), obj);
631 g_signal_connect (G_OBJECT (priv->text_buffer), "end-user-action",
632 G_CALLBACK (text_buffer_end_user_action), obj);
633 g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
634 G_CALLBACK (text_buffer_mark_set), obj);
635 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
636 G_CALLBACK (text_buffer_apply_tag), obj);
637 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
638 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
639 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
640 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
641 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
642 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
644 g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
645 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
646 g_signal_connect (G_OBJECT (priv->from_field), "value-changed",
647 G_CALLBACK (from_field_changed), obj);
649 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
650 G_CALLBACK (msg_body_focus), obj);
651 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
652 G_CALLBACK (msg_body_focus), obj);
653 g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
654 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
655 "changed", G_CALLBACK (recpt_field_changed), obj);
656 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
657 "changed", G_CALLBACK (recpt_field_changed), obj);
658 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
659 "changed", G_CALLBACK (recpt_field_changed), obj);
660 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
661 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
662 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
664 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
665 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
667 priv->clipboard_change_handler_id =
668 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
669 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
670 priv->default_clipboard_change_handler_id =
671 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
672 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
674 g_signal_connect (G_OBJECT (priv->msg_body), "cut-clipboard", G_CALLBACK (cut_clipboard_check), NULL);
675 g_signal_connect (G_OBJECT (priv->msg_body), "copy-clipboard", G_CALLBACK (copy_clipboard_check), NULL);
676 g_signal_connect (G_OBJECT (priv->attachments_view), "delete", G_CALLBACK (attachment_deleted), obj);
680 init_wp_text_view_style ()
682 static gboolean initialized = FALSE;
685 gtk_rc_parse_string ("class \"WPTextView\" style \"fremantle-textview\"");
691 init_window (ModestMsgEditWindow *obj)
693 GtkWidget *to_caption, *subject_caption;
694 GtkWidget *main_vbox;
695 ModestMsgEditWindowPrivate *priv;
696 GtkActionGroup *action_group;
697 ModestWindowPrivate *parent_priv;
698 GdkPixbuf *window_icon = NULL;
699 GError *error = NULL;
701 GtkSizeGroup *title_size_group;
702 GtkSizeGroup *value_size_group;
703 GtkWidget *subject_box;
704 GtkWidget *attachment_icon;
705 GtkWidget *window_box;
706 #if (GTK_MINOR_VERSION >= 10)
707 GdkAtom deserialize_type;
710 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
711 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
713 parent_priv->ui_manager = gtk_ui_manager_new();
714 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
715 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
717 /* Add common actions */
718 gtk_action_group_add_actions (action_group,
719 modest_msg_edit_action_entries,
720 G_N_ELEMENTS (modest_msg_edit_action_entries),
722 gtk_action_group_add_actions (action_group,
723 hildon2_msg_edit_action_entries,
724 G_N_ELEMENTS (hildon2_msg_edit_action_entries),
726 gtk_action_group_add_toggle_actions (action_group,
727 modest_msg_edit_toggle_action_entries,
728 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
730 gtk_action_group_add_radio_actions (action_group,
731 modest_msg_edit_alignment_radio_action_entries,
732 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
734 G_CALLBACK (modest_ui_actions_on_change_justify),
736 gtk_action_group_add_radio_actions (action_group,
737 modest_msg_edit_priority_action_entries,
738 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
740 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
742 gtk_action_group_add_radio_actions (action_group,
743 modest_msg_edit_file_format_action_entries,
744 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
745 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
746 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
748 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
749 g_object_unref (action_group);
751 /* Load the UI definition */
752 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
755 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
756 g_clear_error (&error);
759 /* Add accelerators */
760 gtk_window_add_accel_group (GTK_WINDOW (obj),
761 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
763 parent_priv->menubar = NULL;
765 title_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
766 value_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
768 /* Note: This ModestPairList* must exist for as long as the picker
769 * that uses it, because the ModestSelectorPicker uses the ID opaquely,
770 * so it can't know how to manage its memory. */
771 priv->from_field = modest_selector_picker_new (MODEST_EDITABLE_SIZE,
772 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL,
774 modest_maemo_utils_set_hbutton_layout (title_size_group, value_size_group,
775 _("mail_va_from"), priv->from_field);
777 priv->to_field = modest_recpt_editor_new ();
778 priv->cc_field = modest_recpt_editor_new ();
779 priv->bcc_field = modest_recpt_editor_new ();
780 subject_box = gtk_hbox_new (FALSE, 0);
781 priv->priority_icon = gtk_image_new ();
782 gtk_box_pack_start (GTK_BOX (subject_box), priv->priority_icon, FALSE, FALSE, 0);
783 priv->subject_field = hildon_entry_new (MODEST_EDITABLE_SIZE);
784 gtk_entry_set_max_length (GTK_ENTRY (priv->subject_field) ,SUBJECT_MAX_LENGTH);
785 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
786 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
787 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
788 gtk_box_pack_start (GTK_BOX (subject_box), priv->subject_field, TRUE, TRUE, 0);
789 priv->add_attachment_button = hildon_button_new (MODEST_EDITABLE_SIZE, HILDON_BUTTON_ARRANGEMENT_VERTICAL);
790 gtk_widget_set_size_request (priv->add_attachment_button, ATTACHMENT_BUTTON_WIDTH, -1);
791 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
792 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
793 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, HILDON_ICON_SIZE_FINGER);
794 hildon_button_set_image (HILDON_BUTTON (priv->add_attachment_button), attachment_icon);
795 gtk_box_pack_start (GTK_BOX (subject_box), priv->add_attachment_button, FALSE, FALSE, 0);
796 priv->attachments_view = modest_attachments_view_new (NULL);
798 priv->header_box = gtk_vbox_new (FALSE, 0);
800 to_caption = modest_maemo_utils_create_captioned_with_size_type
801 (title_size_group, value_size_group,
802 _("mail_va_to"), FALSE, priv->to_field,
803 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
804 priv->cc_caption = modest_maemo_utils_create_captioned_with_size_type
805 (title_size_group, value_size_group,
806 _("mail_va_cc"), FALSE, priv->cc_field,
807 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
808 priv->bcc_caption = modest_maemo_utils_create_captioned_with_size_type
809 (title_size_group, value_size_group,
810 _("mail_va_hotfix1"), FALSE, priv->bcc_field,
811 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
812 subject_caption = modest_maemo_utils_create_captioned (title_size_group, value_size_group,
813 _("mail_va_subject"), FALSE, subject_box);
814 priv->attachments_caption = modest_maemo_utils_create_captioned_with_size_type (title_size_group, value_size_group,
815 _("mail_va_attachment"),
817 priv->attachments_view,
818 HILDON_SIZE_AUTO_WIDTH |
819 HILDON_SIZE_AUTO_HEIGHT);
820 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), value_size_group); */
821 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), value_size_group); */
822 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), value_size_group); */
823 g_object_unref (title_size_group);
824 g_object_unref (value_size_group);
826 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->from_field, FALSE, FALSE, 0);
827 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
828 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
829 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
830 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
831 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
832 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
834 init_wp_text_view_style ();
836 priv->msg_body = wp_text_view_new ();
839 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
840 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
841 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
842 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
843 #if (GTK_MINOR_VERSION >= 10)
844 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
845 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
847 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
848 deserialize_type, TRUE);
850 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
852 priv->find_toolbar = hildon_find_toolbar_new (NULL);
853 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
855 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
857 priv->pannable = hildon_pannable_area_new ();
859 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
861 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
862 priv->frame = gtk_frame_new (NULL);
863 gtk_box_pack_start (GTK_BOX(main_vbox), priv->frame, TRUE, TRUE, 0);
865 hildon_pannable_area_add_with_viewport (HILDON_PANNABLE_AREA (priv->pannable), main_vbox);
866 gtk_container_set_focus_vadjustment (GTK_CONTAINER (main_vbox),
867 hildon_pannable_area_get_vadjustment (HILDON_PANNABLE_AREA (priv->pannable)));
868 gtk_widget_show_all (GTK_WIDGET(priv->pannable));
870 window_box = gtk_vbox_new (FALSE, 0);
871 gtk_container_add (GTK_CONTAINER(obj), window_box);
873 gtk_box_pack_start (GTK_BOX (window_box), priv->pannable, TRUE, TRUE, 0);
875 gtk_container_add (GTK_CONTAINER (priv->frame), priv->msg_body);
877 /* Set window icon */
878 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
880 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
881 g_object_unref (window_icon);
886 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
888 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
890 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
891 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
892 priv->clipboard_change_handler_id))
893 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
894 priv->clipboard_change_handler_id);
895 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
896 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
897 priv->default_clipboard_change_handler_id))
898 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
899 priv->default_clipboard_change_handler_id);
901 if (priv->account_removed_handler_id &&
902 g_signal_handler_is_connected (modest_runtime_get_account_store (),
903 priv->account_removed_handler_id))
904 g_signal_handler_disconnect(modest_runtime_get_account_store (),
905 priv->account_removed_handler_id);
909 modest_msg_edit_window_finalize (GObject *obj)
911 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
913 /* Sanity check: shouldn't be needed, the window mgr should
914 call this function before */
915 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
917 if (priv->font_dialog != NULL) {
918 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
921 if (priv->clipboard_text != NULL) {
922 g_free (priv->clipboard_text);
923 priv->clipboard_text = NULL;
926 if (priv->draft_msg != NULL) {
927 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
928 if (TNY_IS_HEADER (header)) {
929 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
930 modest_window_mgr_unregister_header (mgr, header);
932 g_object_unref (priv->draft_msg);
933 priv->draft_msg = NULL;
935 if (priv->outbox_msg != NULL) {
936 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
937 if (TNY_IS_HEADER (header)) {
938 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
939 modest_window_mgr_unregister_header (mgr, header);
941 g_object_unref (priv->outbox_msg);
942 priv->outbox_msg = NULL;
944 if (priv->correct_scroll_idle > 0) {
945 g_source_remove (priv->correct_scroll_idle);
946 priv->correct_scroll_idle = 0;
948 if (priv->scroll_drag_timeout_id > 0) {
949 g_source_remove (priv->scroll_drag_timeout_id);
950 priv->scroll_drag_timeout_id = 0;
952 if (priv->clipboard_owner_idle > 0) {
953 g_source_remove (priv->clipboard_owner_idle);
954 priv->clipboard_owner_idle = 0;
956 if (priv->original_account_name)
957 g_free (priv->original_account_name);
958 g_free (priv->msg_uid);
959 g_free (priv->last_search);
960 g_slist_free (priv->font_items_group);
961 g_slist_free (priv->size_items_group);
962 g_object_unref (priv->attachments);
963 g_object_unref (priv->images);
965 /* This had to stay alive for as long as the picker that used it: */
966 modest_pair_list_free (priv->from_field_protos);
968 G_OBJECT_CLASS(parent_class)->finalize (obj);
972 pixbuf_from_stream (TnyStream *stream, const gchar *mime_type, guint64 *stream_size)
974 GdkPixbufLoader *loader;
980 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
982 if (loader == NULL) {
988 tny_stream_reset (TNY_STREAM (stream));
989 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
990 GError *error = NULL;
991 unsigned char read_buffer[128];
993 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
995 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
997 g_error_free (error);
1002 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1004 g_object_ref (pixbuf);
1005 gdk_pixbuf_loader_close (loader, NULL);
1006 g_object_unref (loader);
1011 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1012 GdkPixbuf *new_pixbuf;
1014 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1015 gdk_pixbuf_get_width (pixbuf);
1016 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1017 g_object_unref (pixbuf);
1018 pixbuf = new_pixbuf;
1022 *stream_size = size;
1028 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1030 ModestMsgEditWindowPrivate *priv;
1033 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1035 for (iter = tny_list_create_iterator (attachments);
1036 !tny_iterator_is_done (iter);
1037 tny_iterator_next (iter)) {
1038 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1039 const gchar *cid = tny_mime_part_get_content_id (part);
1040 const gchar *mime_type = tny_mime_part_get_content_type (part);
1041 if ((cid != NULL)&&(mime_type != NULL)) {
1042 guint64 stream_size;
1043 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1044 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
1047 g_object_unref (stream);
1049 if (pixbuf != NULL) {
1050 priv->images_count ++;
1051 priv->images_size += stream_size;
1052 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1053 g_object_unref (pixbuf);
1056 g_object_unref (part);
1058 g_object_unref (iter);
1062 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1064 TnyMimePart *parent = NULL;
1065 const gchar *content_type = NULL;
1066 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1068 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1070 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1071 parent = g_object_ref (msg);
1072 } else if (content_type && !g_strcasecmp (content_type, "multipart/mixed")) {
1073 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1076 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1077 iter = tny_list_create_iterator (parts);
1078 while (!tny_iterator_is_done (iter)) {
1080 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1081 content_type = tny_mime_part_get_content_type (part);
1082 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1086 g_object_unref (part);
1088 tny_iterator_next (iter);
1090 g_object_unref (iter);
1091 g_object_unref (parts);
1094 if (parent != NULL) {
1095 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1098 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1099 iter = tny_list_create_iterator (parts);
1100 while (!tny_iterator_is_done (iter)) {
1102 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1103 content_type = tny_mime_part_get_content_type (part);
1104 if (content_type && g_str_has_prefix (content_type, "image/")) {
1105 tny_list_prepend (priv->images, (GObject *) part);
1107 g_object_unref (part);
1108 tny_iterator_next (iter);
1110 g_object_unref (iter);
1111 g_object_unref (parts);
1112 g_object_unref (parent);
1117 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1120 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1122 for (iter = tny_list_create_iterator (attachments) ;
1123 !tny_iterator_is_done (iter);
1124 tny_iterator_next (iter)) {
1125 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1126 const gchar *cid = tny_mime_part_get_content_id (part);
1128 char *invalid = NULL;
1129 gint int_cid = strtol (cid, &invalid, 10);
1130 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1131 priv->next_cid = int_cid + 1;
1134 g_object_unref (part);
1136 g_object_unref (iter);
1140 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1143 gchar *to, *cc, *bcc, *subject;
1145 ModestMsgEditWindowPrivate *priv;
1146 ModestWindowPrivate *parent_priv;
1148 TnyHeaderFlags priority_flags;
1149 TnyFolder *msg_folder;
1150 gboolean is_html = FALSE;
1151 gboolean field_view_set;
1153 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1154 g_return_if_fail (TNY_IS_MSG (msg));
1156 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1157 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1159 header = tny_msg_get_header (msg);
1160 to = tny_header_dup_to (header);
1161 cc = tny_header_dup_cc (header);
1162 bcc = tny_header_dup_bcc (header);
1163 subject = tny_header_dup_subject (header);
1164 priority_flags = tny_header_get_priority (header);
1167 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
1169 field_view_set = TRUE;
1171 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
1172 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1173 gtk_widget_show (priv->cc_caption);
1174 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1175 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1176 gtk_widget_hide (priv->cc_caption);
1177 field_view_set = FALSE;
1179 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button), field_view_set);
1181 field_view_set = TRUE;
1183 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
1184 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1185 gtk_widget_show (priv->bcc_caption);
1186 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1187 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1188 gtk_widget_hide (priv->bcc_caption);
1189 field_view_set = FALSE;
1191 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button), field_view_set);
1195 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1196 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1199 update_window_title (self);
1201 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1202 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1204 if ((body == NULL)||(body[0] == '\0')) {
1206 body = modest_text_utils_convert_to_html ("");
1209 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1210 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1213 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1216 /* Add attachments to the view */
1217 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1218 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1219 if (tny_list_get_length (priv->attachments) == 0) {
1220 gtk_widget_hide (priv->attachments_caption);
1222 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1223 gtk_widget_show_all (priv->attachments_caption);
1225 get_related_images (self, msg);
1226 update_next_cid (self, priv->attachments);
1227 update_next_cid (self, priv->images);
1228 replace_with_images (self, priv->images);
1230 if (preserve_is_rich && !is_html) {
1231 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1232 /* Get the default format required from configuration */
1233 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1234 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1237 /* Set the default focus depending on having already a To: field or not */
1238 if ((!to)||(*to == '\0')) {
1239 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1241 gtk_widget_grab_focus (priv->msg_body);
1244 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1246 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1247 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1249 modest_msg_edit_window_set_modified (self, FALSE);
1251 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1252 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1253 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1254 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1256 if (priv->msg_uid) {
1257 g_free (priv->msg_uid);
1258 priv->msg_uid = NULL;
1261 /* we should set a reference to the incoming message if it is a draft */
1262 msg_folder = tny_msg_get_folder (msg);
1264 if (modest_tny_folder_is_local_folder (msg_folder)) {
1265 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1266 if (type == TNY_FOLDER_TYPE_INVALID)
1267 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1269 if (type == TNY_FOLDER_TYPE_DRAFTS)
1270 priv->draft_msg = g_object_ref(msg);
1271 if (type == TNY_FOLDER_TYPE_OUTBOX)
1272 priv->outbox_msg = g_object_ref(msg);
1273 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1275 g_object_unref (msg_folder);
1285 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
1288 GList *item_children, *node;
1289 GtkWidget *bin_child;
1291 bin_child = gtk_bin_get_child (GTK_BIN(item));
1293 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
1295 for (node = item_children; node != NULL; node = g_list_next (node)) {
1296 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
1297 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
1300 g_list_free (item_children);
1304 menu_tool_button_dont_expand (GtkMenuToolButton *item)
1307 GList *item_children, *node;
1309 box = gtk_bin_get_child (GTK_BIN (item));
1310 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
1311 item_children = gtk_container_get_children (GTK_CONTAINER (box));
1313 for (node = item_children; node != NULL; node = g_list_next (node)) {
1314 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
1315 if (GTK_IS_TOGGLE_BUTTON (node->data))
1316 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
1317 else if (GTK_IS_BUTTON (node->data))
1318 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
1320 g_list_free (item_children);
1325 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1327 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1328 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1329 GtkWidget *placeholder;
1330 GtkWidget *tool_item;
1335 GtkWidget *sizes_menu;
1336 GtkWidget *fonts_menu;
1337 GSList *radio_group = NULL;
1338 GSList *node = NULL;
1342 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1343 gtk_toolbar_set_show_arrow (GTK_TOOLBAR (parent_priv->toolbar), FALSE);
1344 gtk_toolbar_set_icon_size (GTK_TOOLBAR (parent_priv->toolbar), HILDON_ICON_SIZE_FINGER);
1345 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1347 /* Font color placeholder */
1348 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1349 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1352 priv->font_color_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1353 priv->font_color_button = hildon_color_button_new ();
1354 gtk_widget_set_size_request (priv->font_color_button, -1, 48);
1355 GTK_WIDGET_UNSET_FLAGS (priv->font_color_toolitem, GTK_CAN_FOCUS);
1356 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1357 gtk_container_add (GTK_CONTAINER (priv->font_color_toolitem), priv->font_color_button);
1358 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1359 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1360 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->font_color_toolitem), insert_index);
1361 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1363 G_CALLBACK (modest_msg_edit_window_color_button_change),
1366 /* Font size and face placeholder */
1367 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1368 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1370 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1371 priv->size_tool_button_label = gtk_label_new (NULL);
1372 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1373 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1374 size_text,"</span>", NULL);
1375 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1377 hildon_helper_set_logical_font (priv->size_tool_button_label, "LargeSystemFont");
1378 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
1379 sizes_menu = gtk_menu_new ();
1380 priv->size_items_group = NULL;
1382 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1383 GtkWidget *size_menu_item;
1385 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1386 size_menu_item = gtk_radio_menu_item_new_with_label (radio_group, size_text);
1387 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (size_menu_item));
1388 gtk_menu_shell_append (GTK_MENU_SHELL (sizes_menu), size_menu_item);
1389 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (size_menu_item), (wp_font_size[size_index] == 12));
1390 gtk_widget_show (size_menu_item);
1392 priv->size_items_group = g_slist_prepend (priv->size_items_group, size_menu_item);
1396 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1397 GtkWidget *item = (GtkWidget *) node->data;
1398 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_size_change),
1402 priv->size_items_group = g_slist_reverse (priv->size_items_group);
1403 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), sizes_menu);
1404 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1405 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1406 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), FALSE);
1407 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), FALSE);
1408 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1409 priv->font_size_toolitem = tool_item;
1412 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1413 priv->font_tool_button_label = gtk_label_new (NULL);
1414 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1415 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1417 hildon_helper_set_logical_font (priv->font_tool_button_label, "LargeSystemFont");
1418 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
1419 fonts_menu = gtk_menu_new ();
1420 priv->font_items_group = NULL;
1422 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1423 GtkWidget *font_menu_item;
1424 GtkWidget *child_label;
1426 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
1427 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
1428 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
1429 wp_get_font_name (font_index), "</span>", NULL);
1430 gtk_label_set_markup (GTK_LABEL (child_label), markup);
1433 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
1434 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
1435 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
1436 gtk_widget_show (font_menu_item);
1438 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
1441 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1442 GtkWidget *item = (GtkWidget *) node->data;
1443 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
1446 priv->font_items_group = g_slist_reverse (priv->font_items_group);
1447 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
1448 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1449 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1450 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), FALSE);
1451 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), FALSE);
1452 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1453 priv->font_face_toolitem = tool_item;
1455 /* Set expand and homogeneous for remaining items */
1456 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
1457 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1458 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1459 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1460 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1461 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1462 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1463 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1464 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1466 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1467 will not show the tool items added to the placeholders) */
1468 gtk_widget_show_all (parent_priv->toolbar);
1470 /* Set the no show all *after* showing all items. We do not
1471 want the toolbar to be shown with a show all because it
1472 could go agains the gconf setting regarding showing or not
1473 the toolbar of the editor window */
1474 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1480 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, gboolean preserve_is_rich)
1483 ModestWindowPrivate *parent_priv;
1484 ModestMsgEditWindowPrivate *priv;
1485 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1486 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1487 ModestWindowMgr *mgr = NULL;
1489 g_return_val_if_fail (msg, NULL);
1490 g_return_val_if_fail (account_name, NULL);
1492 mgr = modest_runtime_get_window_mgr ();
1494 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1496 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1497 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1499 /* Menubar. Update the state of some toggles */
1500 priv->from_field_protos = get_transports ();
1501 modest_selector_picker_set_pair_list (MODEST_SELECTOR_PICKER (priv->from_field), priv->from_field_protos);
1502 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1503 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1504 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1506 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1507 hildon_touch_selector_get_current_text
1508 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1509 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1510 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1513 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1515 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1517 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1519 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1521 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1522 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1523 /* Add common dimming rules */
1524 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1525 modest_msg_edit_window_toolbar_dimming_entries,
1526 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1527 MODEST_WINDOW (obj));
1528 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_toolitem,
1529 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1530 MODEST_WINDOW (obj));
1531 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1532 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1533 MODEST_WINDOW (obj));
1534 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1535 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1536 MODEST_WINDOW (obj));
1537 /* Insert dimming rules group for this window */
1538 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1539 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1541 /* Setup app menu */
1542 setup_menu (MODEST_MSG_EDIT_WINDOW (obj));
1544 /* Checks the dimming rules */
1545 g_object_unref (toolbar_rules_group);
1546 g_object_unref (clipboard_rules_group);
1547 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1549 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1551 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1552 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1553 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1554 priv->update_caption_visibility = TRUE;
1556 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1558 /* Track account-removed signal, this window should be closed
1559 in the case we're creating a mail associated to the account
1561 priv->account_removed_handler_id =
1562 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1564 G_CALLBACK(on_account_removed),
1567 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1569 return (ModestWindow*) obj;
1573 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1575 GString **string_buffer = (GString **) user_data;
1577 *string_buffer = g_string_append (*string_buffer, buffer);
1583 * @result: A new string which should be freed with g_free().
1586 get_formatted_data (ModestMsgEditWindow *edit_window)
1588 ModestMsgEditWindowPrivate *priv;
1589 GString *string_buffer = g_string_new ("");
1591 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1593 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1595 modest_text_utils_hyperlinkify (string_buffer);
1597 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1599 return g_string_free (string_buffer, FALSE);
1604 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1607 const gchar *account_name;
1608 ModestMsgEditWindowPrivate *priv;
1609 TnyIterator *att_iter;
1611 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1613 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1615 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1616 g_return_val_if_fail (account_name, NULL);
1619 /* don't free these (except from) */
1620 data = g_slice_new0 (MsgData);
1621 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1623 data->account_name = g_strdup (account_name);
1624 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1625 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1626 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1627 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1628 if (priv->draft_msg) {
1629 data->draft_msg = g_object_ref (priv->draft_msg);
1630 } else if (priv->outbox_msg) {
1631 data->draft_msg = g_object_ref (priv->outbox_msg);
1633 data->draft_msg = NULL;
1636 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1638 gtk_text_buffer_get_bounds (buf, &b, &e);
1639 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1641 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1642 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1644 data->html_body = NULL;
1646 /* deep-copy the data */
1647 att_iter = tny_list_create_iterator (priv->attachments);
1648 data->attachments = NULL;
1649 while (!tny_iterator_is_done (att_iter)) {
1650 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1651 if (!(TNY_IS_MIME_PART(part))) {
1652 g_warning ("strange data in attachment list");
1653 g_object_unref (part);
1654 tny_iterator_next (att_iter);
1657 data->attachments = g_list_append (data->attachments,
1659 tny_iterator_next (att_iter);
1661 g_object_unref (att_iter);
1663 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1664 att_iter = tny_list_create_iterator (priv->images);
1665 data->images = NULL;
1666 while (!tny_iterator_is_done (att_iter)) {
1667 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1669 if (!(TNY_IS_MIME_PART(part))) {
1670 g_warning ("strange data in attachment list");
1671 g_object_unref (part);
1672 tny_iterator_next (att_iter);
1675 cid = tny_mime_part_get_content_id (part);
1677 gchar *image_tag_id;
1678 GtkTextTag *image_tag;
1680 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1681 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1682 g_free (image_tag_id);
1684 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1686 ((gtk_text_iter_has_tag (&iter, image_tag))||
1687 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1688 data->images = g_list_append (data->images,
1689 g_object_ref (part));
1691 g_object_unref (part);
1692 tny_iterator_next (att_iter);
1694 g_object_unref (att_iter);
1696 data->priority_flags = priv->priority_flags;
1703 unref_gobject (GObject *obj, gpointer data)
1705 if (!G_IS_OBJECT(obj))
1707 g_object_unref (obj);
1711 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1714 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1722 g_free (data->from);
1723 g_free (data->subject);
1724 g_free (data->plain_body);
1725 g_free (data->html_body);
1726 g_free (data->account_name);
1728 if (data->draft_msg != NULL) {
1729 g_object_unref (data->draft_msg);
1730 data->draft_msg = NULL;
1733 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1734 g_list_free (data->attachments);
1735 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1736 g_list_free (data->images);
1738 g_slice_free (MsgData, data);
1742 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1744 guint64 *parts_size)
1746 ModestMsgEditWindowPrivate *priv;
1748 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1750 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1752 /* TODO: add images */
1753 *parts_size += priv->images_size;
1754 *parts_count += priv->images_count;
1759 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1762 ModestMsgEditWindowPrivate *priv = NULL;
1763 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1765 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1767 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1769 return MODEST_MSG_EDIT_FORMAT_HTML;
1771 return MODEST_MSG_EDIT_FORMAT_TEXT;
1775 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1776 ModestMsgEditFormat format)
1778 ModestMsgEditWindowPrivate *priv;
1780 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1781 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1784 case MODEST_MSG_EDIT_FORMAT_HTML:
1785 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1787 case MODEST_MSG_EDIT_FORMAT_TEXT:
1788 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1791 g_return_if_reached ();
1795 ModestMsgEditFormatState *
1796 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1798 ModestMsgEditFormatState *format_state = NULL;
1799 ModestMsgEditWindowPrivate *priv;
1800 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1802 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1803 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1805 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1807 format_state = g_new0 (ModestMsgEditFormatState, 1);
1808 format_state->bold = buffer_format->bold&0x1;
1809 format_state->italics = buffer_format->italic&0x1;
1810 format_state->bullet = buffer_format->bullet&0x1;
1811 format_state->color = buffer_format->color;
1812 format_state->font_size = buffer_format->font_size;
1813 format_state->font_family = wp_get_font_name (buffer_format->font);
1814 format_state->justification = buffer_format->justification;
1815 g_free (buffer_format);
1817 return format_state;
1822 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1823 const ModestMsgEditFormatState *format_state)
1825 ModestMsgEditWindowPrivate *priv;
1826 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1827 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1828 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1829 g_return_if_fail (format_state != NULL);
1831 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1832 gtk_widget_grab_focus (priv->msg_body);
1833 buffer_format->bold = (format_state->bold != FALSE);
1834 buffer_format->italic = (format_state->italics != FALSE);
1835 buffer_format->color = format_state->color;
1836 buffer_format->font_size = format_state->font_size;
1837 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1838 buffer_format->justification = format_state->justification;
1839 buffer_format->bullet = format_state->bullet;
1841 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1843 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1844 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1845 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1846 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1847 buffer_format->cs.font = (buffer_format->font != current_format->font);
1848 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1849 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1851 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1852 if (buffer_format->cs.bold) {
1853 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
1854 GINT_TO_POINTER (buffer_format->bold&0x1));
1856 if (buffer_format->cs.italic) {
1857 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
1858 GINT_TO_POINTER (buffer_format->italic&0x1));
1860 if (buffer_format->cs.color) {
1861 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1862 GINT_TO_POINTER (&(buffer_format->color)));
1864 if (buffer_format->cs.font_size) {
1865 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1866 GINT_TO_POINTER (buffer_format->font_size));
1868 if (buffer_format->cs.justification) {
1869 switch (buffer_format->justification) {
1870 case GTK_JUSTIFY_LEFT:
1871 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
1872 GINT_TO_POINTER(TRUE));
1874 case GTK_JUSTIFY_CENTER:
1875 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
1876 GINT_TO_POINTER(TRUE));
1878 case GTK_JUSTIFY_RIGHT:
1879 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
1880 GINT_TO_POINTER(TRUE));
1887 if (buffer_format->cs.font) {
1888 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1889 GINT_TO_POINTER (buffer_format->font));
1891 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1892 if (buffer_format->cs.bullet) {
1893 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
1894 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
1896 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1898 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
1900 g_free (buffer_format);
1901 g_free (current_format);
1903 /* Check dimming rules */
1904 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1905 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1909 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1911 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1913 ModestWindowPrivate *parent_priv;
1914 ModestMsgEditWindowPrivate *priv;
1915 GtkWidget *new_size_menuitem;
1916 GtkWidget *new_font_menuitem;
1918 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1919 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1921 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1922 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu");
1923 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1924 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1926 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatPlainTextMenu");
1927 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1928 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1931 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1933 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1934 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1936 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1937 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1939 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
1940 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
1943 switch (buffer_format->justification)
1945 case GTK_JUSTIFY_LEFT:
1946 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
1948 case GTK_JUSTIFY_CENTER:
1949 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
1951 case GTK_JUSTIFY_RIGHT:
1952 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
1959 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
1961 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1962 G_CALLBACK (modest_msg_edit_window_color_button_change),
1964 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1965 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1966 G_CALLBACK (modest_msg_edit_window_color_button_change),
1969 new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group,
1970 buffer_format->font_size))->data);
1971 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1975 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1976 markup = g_strconcat ("<span font_family='Sans'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1977 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1979 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1980 G_CALLBACK (modest_msg_edit_window_size_change),
1982 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
1983 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
1984 G_CALLBACK (modest_msg_edit_window_size_change),
1988 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
1989 buffer_format->font))->data);
1990 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
1994 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
1995 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1996 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1998 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
1999 G_CALLBACK (modest_msg_edit_window_font_change),
2001 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
2002 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
2003 G_CALLBACK (modest_msg_edit_window_font_change),
2007 g_free (buffer_format);
2011 #ifdef MODEST_HILDON_VERSION_0
2013 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2016 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2017 ModestMsgEditWindowPrivate *priv;
2018 GtkWidget *dialog = NULL;
2020 GdkColor *new_color = NULL;
2022 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2023 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2025 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2026 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
2027 g_free (buffer_format);
2029 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2030 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2031 if (new_color != NULL) {
2032 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2033 (gpointer) new_color);
2036 gtk_widget_destroy (dialog);
2041 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2044 ModestMsgEditWindowPrivate *priv;
2045 GtkWidget *dialog = NULL;
2047 GdkColor *old_color = NULL;
2048 const GdkColor *new_color = NULL;
2050 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2051 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2053 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2054 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2056 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2057 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2058 if (new_color != NULL)
2059 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2061 gtk_widget_destroy (dialog);
2067 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2070 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2071 ModestMsgEditWindowPrivate *priv;
2072 GtkWidget *dialog = NULL;
2074 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2075 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2077 dialog = hildon_color_chooser_new ();
2078 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2079 g_free (buffer_format);
2081 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2083 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2084 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2087 gtk_widget_destroy (dialog);
2092 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2095 ModestMsgEditWindowPrivate *priv;
2096 GtkWidget *dialog = NULL;
2097 GdkColor *old_color = NULL;
2099 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2100 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2102 dialog = hildon_color_chooser_new ();
2103 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2105 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2107 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2108 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2110 gtk_widget_destroy (dialog);
2113 #endif /*!MODEST_HILDON_VERSION_0*/
2118 create_stream_for_uri (const gchar* uri)
2123 TnyStream *result = NULL;
2125 GnomeVFSHandle *handle = NULL;
2126 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2127 if (test == GNOME_VFS_OK) {
2128 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2129 /* Streams over OBEX (Bluetooth) are not seekable but
2130 * we expect them to be (we might need to read them
2131 * several times). So if this is a Bluetooth URI just
2132 * read the whole file into memory (this is not a fast
2133 * protocol so we can assume that these files are not
2134 * going to be very big) */
2135 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2136 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2137 TnyStream *memstream = tny_camel_mem_stream_new ();
2138 tny_stream_write_to_stream (vfssstream, memstream);
2139 g_object_unref (vfssstream);
2142 result = vfssstream;
2150 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2153 ModestMsgEditWindowPrivate *priv;
2154 GtkWidget *dialog = NULL;
2156 GSList *uris = NULL;
2157 GSList *uri_node = NULL;
2159 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2161 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2162 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2163 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2165 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2167 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2168 GTK_WINDOW (dialog), GTK_WINDOW (window));
2170 response = gtk_dialog_run (GTK_DIALOG (dialog));
2172 case GTK_RESPONSE_OK:
2173 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2178 gtk_widget_destroy (dialog);
2180 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2182 GnomeVFSHandle *handle = NULL;
2183 GnomeVFSResult result;
2184 GtkTextIter position;
2185 GtkTextMark *insert_mark;
2187 uri = (const gchar *) uri_node->data;
2188 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2189 if (result == GNOME_VFS_OK) {
2191 GnomeVFSFileInfo *info;
2192 gchar *filename, *basename, *escaped_filename;
2193 TnyMimePart *mime_part;
2195 const gchar *mime_type = NULL;
2196 GnomeVFSURI *vfs_uri;
2197 guint64 stream_size;
2199 gnome_vfs_close (handle);
2200 vfs_uri = gnome_vfs_uri_new (uri);
2202 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2203 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2204 g_free (escaped_filename);
2205 gnome_vfs_uri_unref (vfs_uri);
2206 info = gnome_vfs_file_info_new ();
2208 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2209 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2211 mime_type = gnome_vfs_file_info_get_mime_type (info);
2213 mime_part = tny_platform_factory_new_mime_part
2214 (modest_runtime_get_platform_factory ());
2216 TnyStream *stream = create_stream_for_uri (uri);
2218 if (stream == NULL) {
2220 modest_platform_information_banner (NULL, NULL,
2221 _FM("sfil_ib_opening_not_allowed"));
2223 g_object_unref (mime_part);
2224 gnome_vfs_file_info_unref (info);
2228 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2230 content_id = g_strdup_printf ("%d", priv->next_cid);
2231 tny_mime_part_set_content_id (mime_part, content_id);
2232 g_free (content_id);
2235 basename = g_path_get_basename (filename);
2236 tny_mime_part_set_filename (mime_part, basename);
2239 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
2241 if (pixbuf != NULL) {
2242 priv->images_size += stream_size;
2243 priv->images_count ++;
2244 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2245 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2246 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
2247 g_object_unref (pixbuf);
2250 tny_list_prepend (priv->images, (GObject *) mime_part);
2251 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2253 g_object_unref (mime_part);
2254 gnome_vfs_file_info_unref (info);
2263 on_attach_file_response (GtkDialog *dialog,
2267 GSList *uris = NULL;
2269 GnomeVFSFileSize total_size, allowed_size;
2270 ModestMsgEditWindow *window;
2271 ModestMsgEditWindowPrivate *priv;
2276 case GTK_RESPONSE_OK:
2277 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2283 window = MODEST_MSG_EDIT_WINDOW (user_data);
2284 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2286 /* allowed size is the maximum size - what's already there */
2287 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2288 &att_num, &att_size);
2289 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2292 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2294 const gchar *uri = (const gchar *) uri_node->data;
2297 modest_msg_edit_window_attach_file_one (window, uri, allowed_size);
2299 if (total_size > allowed_size) {
2300 g_warning ("%s: total size: %u",
2301 __FUNCTION__, (unsigned int)total_size);
2304 allowed_size -= total_size;
2306 g_slist_foreach (uris, (GFunc) g_free, NULL);
2307 g_slist_free (uris);
2309 gtk_widget_destroy (GTK_WIDGET (dialog));
2313 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2315 GtkWidget *dialog = NULL;
2316 ModestMsgEditWindowPrivate *priv;
2318 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2320 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2322 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2325 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window),
2326 GTK_FILE_CHOOSER_ACTION_OPEN);
2327 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2328 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2329 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2330 GTK_WINDOW (dialog), GTK_WINDOW (window));
2332 /* Connect to response & show */
2333 g_signal_connect (dialog, "response",
2334 G_CALLBACK (on_attach_file_response), window);
2335 gtk_widget_show (dialog);
2340 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2342 GnomeVFSFileSize allowed_size)
2345 GnomeVFSHandle *handle = NULL;
2346 ModestMsgEditWindowPrivate *priv;
2347 GnomeVFSResult result;
2348 GnomeVFSFileSize size = 0;
2349 g_return_val_if_fail (window, 0);
2350 g_return_val_if_fail (uri, 0);
2352 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2354 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2355 if (result == GNOME_VFS_OK) {
2356 TnyMimePart *mime_part;
2358 const gchar *mime_type = NULL;
2360 gchar *escaped_filename;
2363 GnomeVFSFileInfo *info;
2364 GnomeVFSURI *vfs_uri;
2366 gnome_vfs_close (handle);
2367 vfs_uri = gnome_vfs_uri_new (uri);
2370 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2371 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2372 g_free (escaped_filename);
2373 gnome_vfs_uri_unref (vfs_uri);
2375 info = gnome_vfs_file_info_new ();
2377 if (gnome_vfs_get_file_info (uri,
2379 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2381 mime_type = gnome_vfs_file_info_get_mime_type (info);
2382 mime_part = tny_platform_factory_new_mime_part
2383 (modest_runtime_get_platform_factory ());
2385 /* try to get the attachment's size; this may fail for weird
2386 * file systems, like obex, upnp... */
2387 if (allowed_size != 0 &&
2388 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2390 if (size > allowed_size) {
2391 modest_platform_information_banner (NULL, NULL,
2392 _FM("sfil_ib_opening_not_allowed"));
2396 g_warning ("%s: could not get attachment size", __FUNCTION__);
2398 stream = create_stream_for_uri (uri);
2400 if (stream == NULL) {
2402 modest_platform_information_banner (NULL, NULL, _FM("sfil_ib_opening_not_allowed"));
2404 g_object_unref (mime_part);
2405 gnome_vfs_file_info_unref (info);
2409 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2410 g_object_unref (stream);
2412 content_id = g_strdup_printf ("%d", priv->next_cid);
2413 tny_mime_part_set_content_id (mime_part, content_id);
2414 g_free (content_id);
2417 basename = g_path_get_basename (filename);
2418 tny_mime_part_set_filename (mime_part, basename);
2421 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2422 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2424 info->size == 0, info->size);
2425 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2426 gtk_widget_show_all (priv->attachments_caption);
2427 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2429 g_object_unref (mime_part);
2430 gnome_vfs_file_info_unref (info);
2437 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2440 ModestMsgEditWindowPrivate *priv;
2443 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2444 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2446 if (att_list == NULL) {
2447 att_list = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2448 if (!modest_maemo_utils_select_attachments (GTK_WINDOW (window), att_list)) {
2449 g_object_unref (att_list);
2454 g_object_ref (att_list);
2457 if (tny_list_get_length (att_list) == 0) {
2458 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2460 gboolean dialog_response;
2461 gchar *message = NULL;
2462 gchar *filename = NULL;
2464 if (tny_list_get_length (att_list) == 1) {
2466 iter = tny_list_create_iterator (att_list);
2467 part = (TnyMimePart *) tny_iterator_get_current (iter);
2468 g_object_unref (iter);
2469 if (TNY_IS_MSG (part)) {
2470 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2472 filename = tny_header_dup_subject (header);
2473 g_object_unref (header);
2475 if (filename == NULL) {
2476 filename = g_strdup (_("mail_va_no_subject"));
2479 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2481 g_object_unref (part);
2483 filename = g_strdup ("");
2485 message = g_strdup_printf (ngettext("emev_nc_delete_attachment",
2486 "emev_nc_delete_attachments",
2487 tny_list_get_length (att_list)), filename);
2490 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
2494 if (dialog_response != GTK_RESPONSE_OK) {
2495 g_object_unref (att_list);
2499 for (iter = tny_list_create_iterator (att_list);
2500 !tny_iterator_is_done (iter);
2501 tny_iterator_next (iter)) {
2502 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2503 const gchar *att_id;
2504 tny_list_remove (priv->attachments, (GObject *) mime_part);
2506 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2508 if (tny_list_get_length (priv->attachments) == 0)
2509 gtk_widget_hide (priv->attachments_caption);
2510 att_id = tny_mime_part_get_content_id (mime_part);
2512 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2514 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2515 g_object_unref (mime_part);
2517 g_object_unref (iter);
2520 g_object_unref (att_list);
2522 /* if the last attachment has been removed, focus the Subject: field */
2523 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2524 gtk_widget_grab_focus (priv->subject_field);
2528 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2531 ModestMsgEditWindowPrivate *priv;
2532 GdkColor *new_color;
2533 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2535 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2536 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2539 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2541 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2543 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2545 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2550 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
2553 ModestMsgEditWindowPrivate *priv;
2554 gint new_size_index;
2555 ModestMsgEditWindow *window;
2558 window = MODEST_MSG_EDIT_WINDOW (userdata);
2559 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2560 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2562 if (gtk_check_menu_item_get_active (menu_item)) {
2564 WPTextBufferFormat format;
2566 memset (&format, 0, sizeof (format));
2567 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2569 label = gtk_bin_get_child (GTK_BIN (menu_item));
2571 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
2572 format.cs.font_size = TRUE;
2573 format.cs.text_position = TRUE;
2574 format.cs.font = TRUE;
2575 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
2576 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2578 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2579 GINT_TO_POINTER (wp_get_font_size_index (new_size_index, 12))))
2580 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2582 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2583 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
2584 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2590 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
2593 ModestMsgEditWindowPrivate *priv;
2594 gint new_font_index;
2595 ModestMsgEditWindow *window;
2598 window = MODEST_MSG_EDIT_WINDOW (userdata);
2599 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2600 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2602 if (gtk_check_menu_item_get_active (menu_item)) {
2605 label = gtk_bin_get_child (GTK_BIN (menu_item));
2607 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
2609 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2610 GINT_TO_POINTER(new_font_index)))
2611 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2613 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2614 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2615 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2621 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2624 ModestMsgEditWindowPrivate *priv = NULL;
2625 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2627 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2628 if (!priv->update_caption_visibility)
2631 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2633 gtk_widget_show (priv->cc_caption);
2635 gtk_widget_hide (priv->cc_caption);
2637 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2641 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2644 ModestMsgEditWindowPrivate *priv = NULL;
2645 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2647 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2648 if (!priv->update_caption_visibility)
2651 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2653 gtk_widget_show (priv->bcc_caption);
2655 gtk_widget_hide (priv->bcc_caption);
2657 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2661 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2662 ModestRecptEditor *editor)
2664 ModestMsgEditWindowPrivate *priv;
2666 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2667 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2669 /* we check for low-mem; in that case, show a warning, and don't allow
2670 * for the addressbook
2672 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2675 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2677 if (editor == NULL) {
2678 GtkWidget *view_focus;
2679 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2681 /* This code should be kept in sync with ModestRecptEditor. The
2682 textview inside the recpt editor is the one that really gets the
2683 focus. As it's inside a scrolled window, and this one inside the
2684 hbox recpt editor inherits from, we'll need to go up in the
2685 hierarchy to know if the text view is part of the recpt editor
2686 or if it's a different text entry */
2688 if (gtk_widget_get_parent (view_focus)) {
2689 GtkWidget *first_parent;
2691 first_parent = gtk_widget_get_parent (view_focus);
2692 if (gtk_widget_get_parent (first_parent) &&
2693 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2694 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2699 editor = MODEST_RECPT_EDITOR (priv->to_field);
2703 modest_address_book_select_addresses (editor);
2708 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2710 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2712 modest_msg_edit_window_open_addressbook (window, NULL);
2716 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2717 gboolean show_toolbar)
2719 ModestWindowPrivate *parent_priv;
2721 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2722 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2724 /* We can not just use the code of
2725 modest_msg_edit_window_setup_toolbar because it has a
2726 mixture of both initialization and creation code. */
2728 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2730 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2734 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2735 TnyHeaderFlags priority_flags)
2737 ModestMsgEditWindowPrivate *priv;
2738 ModestWindowPrivate *parent_priv;
2740 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2742 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2743 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2745 if (priv->priority_flags != priority_flags) {
2746 GtkAction *priority_action = NULL;
2748 priv->priority_flags = priority_flags;
2750 switch (priority_flags) {
2751 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2752 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2753 MODEST_HEADER_ICON_HIGH,
2754 HILDON_ICON_SIZE_XSMALL);
2755 gtk_widget_show (priv->priority_icon);
2756 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2757 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2759 case TNY_HEADER_FLAG_LOW_PRIORITY:
2760 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2761 MODEST_HEADER_ICON_LOW,
2762 HILDON_ICON_SIZE_XSMALL);
2763 gtk_widget_show (priv->priority_icon);
2764 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2765 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2768 gtk_widget_hide (priv->priority_icon);
2769 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2770 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2773 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2774 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2779 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2782 ModestMsgEditWindowPrivate *priv;
2783 ModestWindowPrivate *parent_priv;
2784 gint current_format;
2786 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2788 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2789 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2791 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2792 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2794 if (current_format != file_format) {
2795 switch (file_format) {
2796 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2797 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2798 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
2800 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2804 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2805 response = gtk_dialog_run (GTK_DIALOG (dialog));
2806 gtk_widget_destroy (dialog);
2807 if (response == GTK_RESPONSE_OK) {
2808 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2810 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
2811 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
2816 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2817 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2818 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2823 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2826 ModestMsgEditWindowPrivate *priv;
2827 WPTextBufferFormat oldfmt, fmt;
2828 gint old_position = 0;
2832 GdkColor *color = NULL;
2833 gboolean bold, bold_set, italic, italic_set;
2834 gboolean underline, underline_set;
2835 gboolean strikethrough, strikethrough_set;
2836 gboolean position_set;
2837 gboolean font_size_set, font_set, color_set;
2840 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2841 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2843 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2844 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
2845 GTK_WINDOW(dialog), GTK_WINDOW (window));
2847 /* First we get the currently selected font information */
2848 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2850 switch (oldfmt.text_position) {
2851 case TEXT_POSITION_NORMAL:
2854 case TEXT_POSITION_SUPERSCRIPT:
2862 g_object_set (G_OBJECT (dialog),
2863 "bold", oldfmt.bold != FALSE,
2864 "bold-set", !oldfmt.cs.bold,
2865 "underline", oldfmt.underline != FALSE,
2866 "underline-set", !oldfmt.cs.underline,
2867 "italic", oldfmt.italic != FALSE,
2868 "italic-set", !oldfmt.cs.italic,
2869 "strikethrough", oldfmt.strikethrough != FALSE,
2870 "strikethrough-set", !oldfmt.cs.strikethrough,
2871 "color", &oldfmt.color,
2872 "color-set", !oldfmt.cs.color,
2873 "size", wp_font_size[oldfmt.font_size],
2874 "size-set", !oldfmt.cs.font_size,
2875 "position", old_position,
2876 "position-set", !oldfmt.cs.text_position,
2877 "family", wp_get_font_name (oldfmt.font),
2878 "family-set", !oldfmt.cs.font,
2881 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2882 GTK_WINDOW (dialog), GTK_WINDOW (window));
2883 gtk_widget_show_all (dialog);
2884 priv->font_dialog = dialog;
2885 response = gtk_dialog_run (GTK_DIALOG (dialog));
2886 priv->font_dialog = NULL;
2887 if (response == GTK_RESPONSE_OK) {
2889 g_object_get( dialog,
2891 "bold-set", &bold_set,
2892 "underline", &underline,
2893 "underline-set", &underline_set,
2895 "italic-set", &italic_set,
2896 "strikethrough", &strikethrough,
2897 "strikethrough-set", &strikethrough_set,
2899 "color-set", &color_set,
2901 "size-set", &font_size_set,
2902 "family", &font_name,
2903 "family-set", &font_set,
2904 "position", &position,
2905 "position-set", &position_set,
2910 if (response == GTK_RESPONSE_OK) {
2911 memset(&fmt, 0, sizeof(fmt));
2917 fmt.italic = italic;
2918 fmt.cs.italic = TRUE;
2920 if (underline_set) {
2921 fmt.underline = underline;
2922 fmt.cs.underline = TRUE;
2924 if (strikethrough_set) {
2925 fmt.strikethrough = strikethrough;
2926 fmt.cs.strikethrough = TRUE;
2931 ? TEXT_POSITION_NORMAL
2932 : ( ( position == 1 )
2933 ? TEXT_POSITION_SUPERSCRIPT
2934 : TEXT_POSITION_SUBSCRIPT );
2935 fmt.cs.text_position = TRUE;
2936 fmt.font_size = oldfmt.font_size;
2940 fmt.cs.color = TRUE;
2943 fmt.font = wp_get_font_index(font_name,
2948 if (font_size_set) {
2949 fmt.cs.font_size = TRUE;
2950 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
2952 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2953 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2955 gtk_widget_destroy (dialog);
2957 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2961 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2963 ModestMsgEditWindowPrivate *priv;
2965 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2966 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2968 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2970 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2971 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2975 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
2977 ModestMsgEditWindowPrivate *priv;
2979 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2980 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2982 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
2984 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2985 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2990 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
2992 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2994 priv->can_undo = can_undo;
2998 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
3000 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3002 priv->can_redo = can_redo;
3006 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3008 ModestMsgEditWindowPrivate *priv;
3009 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3010 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3012 return priv->can_undo;
3016 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3018 ModestMsgEditWindowPrivate *priv;
3019 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3020 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3022 return priv->can_redo;
3027 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3030 GtkTextIter match_start, match_end;
3032 if (image_id == NULL)
3035 gtk_text_buffer_get_start_iter (buffer, &iter);
3037 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3038 GSList *tags = gtk_text_iter_get_tags (&match_start);
3040 for (node = tags; node != NULL; node = g_slist_next (node)) {
3041 GtkTextTag *tag = (GtkTextTag *) node->data;
3042 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3043 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3044 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3046 offset = gtk_text_iter_get_offset (&match_start);
3047 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3048 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3052 gtk_text_iter_forward_char (&iter);
3057 message_is_empty (ModestMsgEditWindow *window)
3059 ModestMsgEditWindowPrivate *priv = NULL;
3061 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3062 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3064 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3065 * so we can ignore markup.
3067 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3070 count = gtk_text_buffer_get_char_count (buf);
3076 msg_body_focus (GtkWidget *focus,
3077 GdkEventFocus *event,
3081 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3082 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3083 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3088 recpt_field_changed (GtkTextBuffer *buffer,
3089 ModestMsgEditWindow *editor)
3091 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3092 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3096 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3098 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3099 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3103 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3106 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3107 GtkTextBuffer *buffer;
3109 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3110 gtk_text_buffer_set_modified (buffer, modified);
3111 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3112 gtk_text_buffer_set_modified (buffer, modified);
3113 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3114 gtk_text_buffer_set_modified (buffer, modified);
3115 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3119 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3121 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3122 const char *account_name;
3123 GtkTextBuffer *buffer;
3125 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3126 if (gtk_text_buffer_get_modified (buffer))
3128 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3129 if (gtk_text_buffer_get_modified (buffer))
3131 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3132 if (gtk_text_buffer_get_modified (buffer))
3134 if (gtk_text_buffer_get_modified (priv->text_buffer))
3136 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3137 if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3148 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3150 ModestMsgEditWindowPrivate *priv = NULL;
3152 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3153 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3155 /* check if there's no recipient added */
3156 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3157 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3158 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3159 /* no recipient contents, then select contacts */
3160 modest_msg_edit_window_open_addressbook (window, NULL);
3164 g_object_ref (window);
3165 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3166 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3167 g_object_unref (window);
3170 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3171 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3172 g_object_unref (window);
3175 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3176 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3177 g_object_unref (window);
3181 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3182 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3183 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3184 g_object_unref (window);
3191 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3192 ModestMsgEditWindow *window)
3194 modest_msg_edit_window_offer_attach_file (window);
3198 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3200 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3202 return priv->clipboard_text;
3206 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3208 ModestMsgEditWindow *window)
3210 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3211 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3213 if (!GTK_WIDGET_VISIBLE (window))
3216 g_object_ref (window);
3217 text = gtk_clipboard_wait_for_text (selection_clipboard);
3219 if (priv->clipboard_text != NULL) {
3220 g_free (priv->clipboard_text);
3222 priv->clipboard_text = text;
3224 if (GTK_WIDGET_VISIBLE (window)) {
3225 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3227 g_object_unref (window);
3230 static gboolean clipboard_owner_change_idle (gpointer userdata)
3232 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3233 ModestMsgEditWindowPrivate *priv;
3235 gdk_threads_enter ();
3236 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3237 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3239 priv->clipboard_owner_idle = 0;
3240 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3241 gdk_threads_leave ();
3247 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3249 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3250 if (priv->clipboard_owner_idle == 0) {
3251 priv->clipboard_owner_idle = g_idle_add (clipboard_owner_change_idle, window);
3256 subject_field_move_cursor (GtkEntry *entry,
3257 GtkMovementStep step,
3262 if (!GTK_WIDGET_VISIBLE (window))
3265 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3269 update_window_title (ModestMsgEditWindow *window)
3271 ModestMsgEditWindowPrivate *priv = NULL;
3272 const gchar *subject;
3274 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3275 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3276 if (subject == NULL || subject[0] == '\0')
3277 subject = _("mail_va_new_email");
3279 gtk_window_set_title (GTK_WINDOW (window), subject);
3284 subject_field_changed (GtkEditable *editable,
3285 ModestMsgEditWindow *window)
3287 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3288 update_window_title (window);
3289 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3290 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3291 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3295 subject_field_insert_text (GtkEditable *editable,
3297 gint new_text_length,
3299 ModestMsgEditWindow *window)
3301 GString *result = g_string_new ("");
3303 gint result_len = 0;
3304 const gchar *entry_text = NULL;
3307 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3308 old_length = g_utf8_strlen (entry_text, -1);
3310 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3311 gunichar c = g_utf8_get_char_validated (current, 8);
3312 /* Invalid unichar, stop */
3318 result = g_string_append_unichar (result, c);
3322 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3323 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3326 /* Prevent endless recursion */
3327 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3328 g_signal_emit_by_name (editable, "insert-text",
3329 (gpointer) result->str, (gpointer) result->len,
3330 (gpointer) position, (gpointer) window);
3331 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3335 if (result_len + old_length > 1000) {
3336 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3337 _CS("ckdg_ib_maximum_characters_reached"));
3339 g_string_free (result, TRUE);
3343 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3346 ModestMsgEditWindowPrivate *priv = NULL;
3348 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3349 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3351 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3354 gtk_widget_show_all (priv->find_toolbar);
3355 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3357 gtk_widget_hide_all (priv->find_toolbar);
3358 gtk_widget_grab_focus (priv->msg_body);
3363 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3365 GtkTextIter *match_start,
3366 GtkTextIter *match_end)
3368 GtkTextIter end_iter;
3369 gchar *str_casefold;
3372 gchar *range_casefold;
3375 gboolean result = FALSE;
3382 gtk_text_iter_forward_to_end (&end_iter);
3384 str_casefold = g_utf8_casefold (str, -1);
3385 str_chars_n = strlen (str);
3387 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3388 range_casefold = g_utf8_casefold (range_text, -1);
3389 range_chars_n = strlen (range_casefold);
3391 if (range_chars_n < str_chars_n) {
3392 g_free (str_casefold);
3393 g_free (range_text);
3394 g_free (range_casefold);
3398 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3399 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3400 if (!g_utf8_collate (range_subtext, str_casefold)) {
3401 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3403 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3404 match_start, match_end, NULL);
3405 g_free (found_text);
3407 g_free (range_subtext);
3411 g_free (str_casefold);
3412 g_free (range_text);
3413 g_free (range_casefold);
3420 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3421 ModestMsgEditWindow *window)
3423 gchar *current_search = NULL;
3424 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3426 GtkTextIter selection_start, selection_end;
3427 GtkTextIter match_start, match_end;
3428 gboolean continue_search = FALSE;
3430 if (message_is_empty (window)) {
3431 g_free (priv->last_search);
3432 priv->last_search = NULL;
3433 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3437 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3438 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3439 g_free (current_search);
3440 g_free (priv->last_search);
3441 priv->last_search = NULL;
3442 /* Information banner about empty search */
3443 hildon_banner_show_information (NULL, NULL, _CS("ecdg_ib_find_rep_enter_text"));
3447 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3448 continue_search = TRUE;
3450 g_free (priv->last_search);
3451 priv->last_search = g_strdup (current_search);
3454 if (continue_search) {
3455 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3456 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3457 &match_start, &match_end);
3459 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_search_complete"));
3461 GtkTextIter buffer_start;
3462 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3463 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3464 &match_start, &match_end);
3466 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_no_matches"));
3469 /* Mark as selected the string found in search */
3471 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3472 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3473 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3475 g_free (priv->last_search);
3476 priv->last_search = NULL;
3478 g_free (current_search);
3482 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3484 ModestMsgEditWindowPrivate *priv;
3486 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3491 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3494 ModestMsgEditWindowPrivate *priv;
3496 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3501 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3502 ModestMsgEditWindow *window)
3504 modest_msg_edit_window_toggle_find_toolbar (window, FALSE);
3508 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3511 ModestMsgEditWindowPrivate *priv;
3512 TnyHeader *header = NULL;
3514 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3515 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3517 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3518 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3520 if (priv->draft_msg != NULL) {
3521 g_object_unref (priv->draft_msg);
3524 if (draft != NULL) {
3525 g_object_ref (draft);
3526 header = tny_msg_get_header (draft);
3527 if (priv->msg_uid) {
3528 g_free (priv->msg_uid);
3529 priv->msg_uid = NULL;
3531 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3532 if (GTK_WIDGET_REALIZED (window)) {
3533 if (!modest_window_mgr_register_window (mgr, MODEST_WINDOW (window), NULL)) {
3534 gtk_widget_destroy (GTK_WIDGET (window));
3540 priv->draft_msg = draft;
3544 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3545 GtkTextIter *start, GtkTextIter *end,
3548 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3549 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3552 if (tag == NULL) return;
3553 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3554 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3555 replace_with_images (window, priv->images);
3560 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3563 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3565 g_return_if_fail (TNY_IS_MIME_PART (part));
3566 tny_list_prepend (priv->attachments, (GObject *) part);
3567 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3568 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3569 gtk_widget_show_all (priv->attachments_caption);
3570 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3574 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3576 ModestMsgEditWindowPrivate *priv;
3578 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3579 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3581 return priv->msg_uid;
3585 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3586 ModestMsgEditWindowWidgetType widget_type)
3588 ModestMsgEditWindowPrivate *priv;
3590 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3591 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3593 switch (widget_type) {
3594 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3595 return priv->msg_body;
3597 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3598 return priv->to_field;
3600 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3601 return priv->cc_field;
3603 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3604 return priv->bcc_field;
3606 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3607 return priv->subject_field;
3609 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3610 return priv->attachments_view;
3618 remove_tags (WPTextBuffer *buffer)
3620 GtkTextIter start, end;
3622 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3623 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3625 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3629 on_account_removed (TnyAccountStore *account_store,
3630 TnyAccount *account,
3633 /* Do nothing if it's a store account, because we use the
3634 transport to send the messages */
3635 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3636 const gchar *parent_acc = NULL;
3637 const gchar *our_acc = NULL;
3639 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3640 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3641 /* Close this window if I'm showing a message of the removed account */
3642 if (strcmp (parent_acc, our_acc) == 0)
3643 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3648 from_field_changed (HildonPickerButton *button,
3649 ModestMsgEditWindow *self)
3651 ModestMsgEditWindowPrivate *priv;
3652 gboolean has_old_signature, has_new_signature;
3654 GtkTextIter match_start, match_end;
3655 ModestAccountMgr *mgr;
3657 gchar *full_signature;
3659 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3661 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
3662 mgr = modest_runtime_get_account_mgr ();
3663 signature = modest_account_mgr_get_signature (mgr, priv->last_from_account, &has_old_signature);
3664 if (has_old_signature) {
3665 full_signature = g_strconcat ("--\n", signature, NULL);
3666 if (gtk_text_iter_forward_search (&iter, full_signature, 0, &match_start, &match_end, NULL)) {
3667 gtk_text_buffer_delete (priv->text_buffer, &match_start, &match_end);
3669 } else if (gtk_text_iter_forward_search (&iter, _("mcen_ia_editor_original_message"), 0,
3670 &match_start, &match_end, NULL)) {
3673 g_free (full_signature);
3677 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3678 signature = modest_account_mgr_get_signature (mgr, priv->last_from_account, &has_new_signature);
3679 if (has_new_signature) {
3680 full_signature = g_strconcat ("--\n", signature, NULL);
3681 gtk_text_buffer_insert (priv->text_buffer, &iter, full_signature, -1);
3682 g_free (full_signature);
3687 typedef struct _MessageSettingsHelper {
3688 ModestMsgEditWindow *window;
3689 GSList *priority_group;
3690 GSList *format_group;
3691 GtkToggleButton *current_priority;
3692 GtkToggleButton *current_format;
3693 } MessageSettingsHelper;
3696 on_priority_toggle (GtkToggleButton *button,
3697 MessageSettingsHelper *helper)
3700 ModestMsgEditWindowPrivate *priv;
3702 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3703 if (gtk_toggle_button_get_active (button)) {
3705 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3706 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3707 if ((node_button != button) &&
3708 gtk_toggle_button_get_active (node_button)) {
3709 gtk_toggle_button_set_active (node_button, FALSE);
3712 helper->current_priority = button;
3714 gboolean found = FALSE;
3715 /* If no one is active, activate it again */
3716 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3717 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3718 if (gtk_toggle_button_get_active (node_button)) {
3724 gtk_toggle_button_set_active (button, TRUE);
3730 on_format_toggle (GtkToggleButton *button,
3731 MessageSettingsHelper *helper)
3734 ModestMsgEditWindowPrivate *priv;
3736 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3737 if (gtk_toggle_button_get_active (button)) {
3739 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
3740 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3741 if ((node_button != button) &&
3742 gtk_toggle_button_get_active (node_button)) {
3743 gtk_toggle_button_set_active (node_button, FALSE);
3746 helper->current_format = button;
3748 gboolean found = FALSE;
3749 /* If no one is active, activate it again */
3750 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
3751 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3752 if (gtk_toggle_button_get_active (node_button)) {
3758 gtk_toggle_button_set_active (button, TRUE);
3765 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
3769 GtkWidget *priority_hbox;
3770 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
3771 GtkWidget *captioned;
3772 GtkSizeGroup *title_sizegroup, *value_sizegroup;
3773 GtkWidget *format_hbox;
3774 GtkWidget *html_toggle, *text_toggle;
3775 ModestMsgEditWindowPrivate *priv;
3776 MessageSettingsHelper helper = {0,};
3778 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3779 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3780 helper.window = window;
3781 helper.priority_group = NULL;
3783 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3784 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3786 dialog = gtk_dialog_new_with_buttons (_("mcen_me_message_settings"), NULL,
3787 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
3788 _HL("wdgt_bd_done"), GTK_RESPONSE_ACCEPT, NULL);
3789 vbox = gtk_vbox_new (FALSE, 0);
3790 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), vbox);
3791 gtk_widget_show (vbox);
3793 /* Priority toggles */
3794 priority_hbox = gtk_hbox_new (TRUE, 0);
3795 high_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3796 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
3797 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
3798 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
3799 medium_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3800 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
3801 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
3802 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
3803 low_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3804 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
3805 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
3806 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
3807 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, TRUE, TRUE, 0);
3808 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, TRUE, TRUE, 0);
3809 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, TRUE, TRUE, 0);
3810 gtk_widget_show_all (priority_hbox);
3811 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
3812 _("mcen_me_editor_message_priority"), FALSE, priority_hbox);
3813 gtk_widget_show (captioned);
3814 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
3816 /* format toggles */
3817 format_hbox = gtk_hbox_new (TRUE, 0);
3818 html_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3819 gtk_button_set_label (GTK_BUTTON (html_toggle), _("mcen_me_editor_formatted_text"));
3820 helper.format_group = g_slist_prepend (helper.format_group, html_toggle);
3821 g_object_set_data (G_OBJECT (html_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_HTML));
3822 g_object_set_data (G_OBJECT (html_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_FORMATTED_TEXT));
3823 text_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3824 gtk_button_set_label (GTK_BUTTON (text_toggle), _("mcen_me_editor_plain_text"));
3825 helper.format_group = g_slist_prepend (helper.format_group, text_toggle);
3826 g_object_set_data (G_OBJECT (text_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_TEXT));
3827 g_object_set_data (G_OBJECT (text_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_PLAIN_TEXT));
3828 gtk_box_pack_start (GTK_BOX (format_hbox), html_toggle, TRUE, TRUE, 0);
3829 gtk_box_pack_start (GTK_BOX (format_hbox), text_toggle, TRUE, TRUE, 0);
3830 gtk_widget_show_all (format_hbox);
3831 gtk_widget_show (format_hbox);
3832 gtk_box_pack_start (GTK_BOX (vbox), format_hbox, FALSE, FALSE, 0);
3835 g_object_unref (title_sizegroup);
3836 g_object_unref (value_sizegroup);
3838 /* Set current values */
3839 switch (priv->priority_flags) {
3840 case TNY_HEADER_FLAG_HIGH_PRIORITY:
3841 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (high_toggle), TRUE);
3842 helper.current_priority = GTK_TOGGLE_BUTTON (high_toggle);
3844 case TNY_HEADER_FLAG_LOW_PRIORITY:
3845 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (low_toggle), TRUE);
3846 helper.current_priority = GTK_TOGGLE_BUTTON (low_toggle);
3849 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (medium_toggle), TRUE);
3850 helper.current_priority = GTK_TOGGLE_BUTTON (medium_toggle);
3854 switch (modest_msg_edit_window_get_format (window)) {
3855 case MODEST_MSG_EDIT_FORMAT_TEXT:
3856 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_toggle), TRUE);
3857 helper.current_format = GTK_TOGGLE_BUTTON (text_toggle);
3859 case MODEST_MSG_EDIT_FORMAT_HTML:
3861 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (html_toggle), TRUE);
3862 helper.current_format = GTK_TOGGLE_BUTTON (html_toggle);
3866 /* Signal connects */
3867 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3868 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3869 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3870 g_signal_connect (G_OBJECT (html_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
3871 g_signal_connect (G_OBJECT (text_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
3873 /* Save settings if the user clicked on done */
3874 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
3875 TnyHeaderFlags flags;
3876 ModestMsgEditFormat old_format, new_format;
3878 /* Set priority flags */
3879 flags = (TnyHeaderFlags) g_object_get_data (G_OBJECT (helper.current_priority), "priority");
3880 if (priv->priority_flags != flags)
3881 modest_msg_edit_window_set_priority_flags (window, flags);
3883 /* Set edit format */
3884 old_format = modest_msg_edit_window_get_format (window);
3885 new_format = (ModestMsgEditFormat) g_object_get_data (G_OBJECT (helper.current_format), "format");
3886 if (old_format != new_format) {
3887 gint file_format = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (helper.current_format), "file-format"));
3888 modest_msg_edit_window_set_file_format (window, file_format);
3892 gtk_widget_destroy (dialog);
3893 g_slist_free (helper.priority_group);
3897 on_message_settings (GtkAction *action,
3898 ModestMsgEditWindow *window)
3900 modest_msg_edit_window_show_msg_settings_dialog (window);
3904 on_cc_button_toggled (HildonCheckButton *button,
3905 ModestMsgEditWindow *window)
3907 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
3909 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
3910 hildon_check_button_get_active (button));
3914 on_bcc_button_toggled (HildonCheckButton *button,
3915 ModestMsgEditWindow *window)
3917 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
3919 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
3920 hildon_check_button_get_active (button));
3924 setup_menu (ModestMsgEditWindow *self)
3926 ModestMsgEditWindowPrivate *priv = NULL;
3928 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
3930 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3932 /* Settings menu buttons */
3933 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_checknames"), NULL,
3934 APP_MENU_CALLBACK (modest_ui_actions_on_check_names),
3936 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_undo"), "<Ctrl>z",
3937 APP_MENU_CALLBACK (modest_ui_actions_on_undo),
3938 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_undo));
3940 priv->cc_button = hildon_check_button_new (0);
3941 gtk_button_set_label (GTK_BUTTON (priv->cc_button), _("mcen_me_editor_showcc"));
3942 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button),
3944 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->cc_button),
3946 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
3947 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
3948 priv->bcc_button = hildon_check_button_new (0);
3949 gtk_button_set_label (GTK_BUTTON (priv->bcc_button), _("mcen_me_editor_showbcc"));
3950 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button),
3952 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->bcc_button),
3954 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
3955 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
3957 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_attach_inlineimage"), NULL,
3958 APP_MENU_CALLBACK (modest_ui_actions_on_insert_image),
3959 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_set_style));
3960 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_remove_attachments"), NULL,
3961 APP_MENU_CALLBACK (modest_ui_actions_on_remove_attachments),
3962 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
3963 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_message_settings"), NULL,
3964 APP_MENU_CALLBACK (on_message_settings),
3966 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_viewer_find"), "<Ctrl>f",
3967 APP_MENU_CALLBACK (modest_ui_actions_on_toggle_find_in_page),