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);
797 modest_attachments_view_set_style (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
798 MODEST_ATTACHMENTS_VIEW_STYLE_NO_FOCUS);
800 priv->header_box = gtk_vbox_new (FALSE, 0);
802 to_caption = modest_maemo_utils_create_captioned_with_size_type
803 (title_size_group, value_size_group,
804 _("mail_va_to"), FALSE, priv->to_field,
805 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
806 priv->cc_caption = modest_maemo_utils_create_captioned_with_size_type
807 (title_size_group, value_size_group,
808 _("mail_va_cc"), FALSE, priv->cc_field,
809 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
810 priv->bcc_caption = modest_maemo_utils_create_captioned_with_size_type
811 (title_size_group, value_size_group,
812 _("mail_va_hotfix1"), FALSE, priv->bcc_field,
813 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
814 subject_caption = modest_maemo_utils_create_captioned (title_size_group, value_size_group,
815 _("mail_va_subject"), FALSE, subject_box);
816 priv->attachments_caption = modest_maemo_utils_create_captioned_with_size_type (title_size_group, value_size_group,
817 _("mail_va_attachment"),
819 priv->attachments_view,
820 HILDON_SIZE_AUTO_WIDTH |
821 HILDON_SIZE_AUTO_HEIGHT);
822 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), value_size_group); */
823 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), value_size_group); */
824 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), value_size_group); */
825 g_object_unref (title_size_group);
826 g_object_unref (value_size_group);
828 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->from_field, FALSE, FALSE, 0);
829 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
830 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
831 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
832 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
833 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
834 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
836 init_wp_text_view_style ();
838 priv->msg_body = wp_text_view_new ();
841 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
842 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
843 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
844 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
845 #if (GTK_MINOR_VERSION >= 10)
846 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
847 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
849 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
850 deserialize_type, TRUE);
852 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
854 priv->find_toolbar = hildon_find_toolbar_new (NULL);
855 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
857 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
859 priv->pannable = hildon_pannable_area_new ();
861 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
863 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
864 priv->frame = gtk_frame_new (NULL);
865 gtk_box_pack_start (GTK_BOX(main_vbox), priv->frame, TRUE, TRUE, 0);
867 hildon_pannable_area_add_with_viewport (HILDON_PANNABLE_AREA (priv->pannable), main_vbox);
868 gtk_container_set_focus_vadjustment (GTK_CONTAINER (main_vbox),
869 hildon_pannable_area_get_vadjustment (HILDON_PANNABLE_AREA (priv->pannable)));
870 gtk_widget_show_all (GTK_WIDGET(priv->pannable));
872 window_box = gtk_vbox_new (FALSE, 0);
873 gtk_container_add (GTK_CONTAINER(obj), window_box);
875 gtk_box_pack_start (GTK_BOX (window_box), priv->pannable, TRUE, TRUE, 0);
877 gtk_container_add (GTK_CONTAINER (priv->frame), priv->msg_body);
879 /* Set window icon */
880 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
882 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
883 g_object_unref (window_icon);
888 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
890 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
892 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
893 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
894 priv->clipboard_change_handler_id))
895 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
896 priv->clipboard_change_handler_id);
897 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
898 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
899 priv->default_clipboard_change_handler_id))
900 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
901 priv->default_clipboard_change_handler_id);
903 if (priv->account_removed_handler_id &&
904 g_signal_handler_is_connected (modest_runtime_get_account_store (),
905 priv->account_removed_handler_id))
906 g_signal_handler_disconnect(modest_runtime_get_account_store (),
907 priv->account_removed_handler_id);
911 modest_msg_edit_window_finalize (GObject *obj)
913 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
915 /* Sanity check: shouldn't be needed, the window mgr should
916 call this function before */
917 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
919 if (priv->font_dialog != NULL) {
920 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
923 if (priv->clipboard_text != NULL) {
924 g_free (priv->clipboard_text);
925 priv->clipboard_text = NULL;
928 if (priv->draft_msg != NULL) {
929 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
930 if (TNY_IS_HEADER (header)) {
931 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
932 modest_window_mgr_unregister_header (mgr, header);
934 g_object_unref (priv->draft_msg);
935 priv->draft_msg = NULL;
937 if (priv->outbox_msg != NULL) {
938 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
939 if (TNY_IS_HEADER (header)) {
940 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
941 modest_window_mgr_unregister_header (mgr, header);
943 g_object_unref (priv->outbox_msg);
944 priv->outbox_msg = NULL;
946 if (priv->correct_scroll_idle > 0) {
947 g_source_remove (priv->correct_scroll_idle);
948 priv->correct_scroll_idle = 0;
950 if (priv->scroll_drag_timeout_id > 0) {
951 g_source_remove (priv->scroll_drag_timeout_id);
952 priv->scroll_drag_timeout_id = 0;
954 if (priv->clipboard_owner_idle > 0) {
955 g_source_remove (priv->clipboard_owner_idle);
956 priv->clipboard_owner_idle = 0;
958 if (priv->original_account_name)
959 g_free (priv->original_account_name);
960 g_free (priv->msg_uid);
961 g_free (priv->last_search);
962 g_slist_free (priv->font_items_group);
963 g_slist_free (priv->size_items_group);
964 g_object_unref (priv->attachments);
965 g_object_unref (priv->images);
967 /* This had to stay alive for as long as the picker that used it: */
968 modest_pair_list_free (priv->from_field_protos);
970 G_OBJECT_CLASS(parent_class)->finalize (obj);
974 pixbuf_from_stream (TnyStream *stream, const gchar *mime_type, guint64 *stream_size)
976 GdkPixbufLoader *loader;
982 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
984 if (loader == NULL) {
990 tny_stream_reset (TNY_STREAM (stream));
991 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
992 GError *error = NULL;
993 unsigned char read_buffer[128];
995 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
997 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
999 g_error_free (error);
1004 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1006 g_object_ref (pixbuf);
1007 gdk_pixbuf_loader_close (loader, NULL);
1008 g_object_unref (loader);
1013 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1014 GdkPixbuf *new_pixbuf;
1016 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1017 gdk_pixbuf_get_width (pixbuf);
1018 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1019 g_object_unref (pixbuf);
1020 pixbuf = new_pixbuf;
1024 *stream_size = size;
1030 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1032 ModestMsgEditWindowPrivate *priv;
1035 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1037 for (iter = tny_list_create_iterator (attachments);
1038 !tny_iterator_is_done (iter);
1039 tny_iterator_next (iter)) {
1040 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1041 const gchar *cid = tny_mime_part_get_content_id (part);
1042 const gchar *mime_type = tny_mime_part_get_content_type (part);
1043 if ((cid != NULL)&&(mime_type != NULL)) {
1044 guint64 stream_size;
1045 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1046 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
1049 g_object_unref (stream);
1051 if (pixbuf != NULL) {
1052 priv->images_count ++;
1053 priv->images_size += stream_size;
1054 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1055 g_object_unref (pixbuf);
1058 g_object_unref (part);
1060 g_object_unref (iter);
1064 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1066 TnyMimePart *parent = NULL;
1067 const gchar *content_type = NULL;
1068 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1070 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1072 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1073 parent = g_object_ref (msg);
1074 } else if (content_type && !g_strcasecmp (content_type, "multipart/mixed")) {
1075 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1078 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1079 iter = tny_list_create_iterator (parts);
1080 while (!tny_iterator_is_done (iter)) {
1082 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1083 content_type = tny_mime_part_get_content_type (part);
1084 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1088 g_object_unref (part);
1090 tny_iterator_next (iter);
1092 g_object_unref (iter);
1093 g_object_unref (parts);
1096 if (parent != NULL) {
1097 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1100 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1101 iter = tny_list_create_iterator (parts);
1102 while (!tny_iterator_is_done (iter)) {
1104 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1105 content_type = tny_mime_part_get_content_type (part);
1106 if (content_type && g_str_has_prefix (content_type, "image/")) {
1107 tny_list_prepend (priv->images, (GObject *) part);
1109 g_object_unref (part);
1110 tny_iterator_next (iter);
1112 g_object_unref (iter);
1113 g_object_unref (parts);
1114 g_object_unref (parent);
1119 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1122 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1124 for (iter = tny_list_create_iterator (attachments) ;
1125 !tny_iterator_is_done (iter);
1126 tny_iterator_next (iter)) {
1127 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1128 const gchar *cid = tny_mime_part_get_content_id (part);
1130 char *invalid = NULL;
1131 gint int_cid = strtol (cid, &invalid, 10);
1132 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1133 priv->next_cid = int_cid + 1;
1136 g_object_unref (part);
1138 g_object_unref (iter);
1142 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1145 gchar *to, *cc, *bcc, *subject;
1147 ModestMsgEditWindowPrivate *priv;
1148 ModestWindowPrivate *parent_priv;
1150 TnyHeaderFlags priority_flags;
1151 TnyFolder *msg_folder;
1152 gboolean is_html = FALSE;
1153 gboolean field_view_set;
1155 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1156 g_return_if_fail (TNY_IS_MSG (msg));
1158 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1159 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1161 header = tny_msg_get_header (msg);
1162 to = tny_header_dup_to (header);
1163 cc = tny_header_dup_cc (header);
1164 bcc = tny_header_dup_bcc (header);
1165 subject = tny_header_dup_subject (header);
1166 priority_flags = tny_header_get_priority (header);
1169 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
1171 field_view_set = TRUE;
1173 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
1174 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1175 gtk_widget_show (priv->cc_caption);
1176 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1177 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1178 gtk_widget_hide (priv->cc_caption);
1179 field_view_set = FALSE;
1181 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button), field_view_set);
1183 field_view_set = TRUE;
1185 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
1186 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1187 gtk_widget_show (priv->bcc_caption);
1188 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1189 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1190 gtk_widget_hide (priv->bcc_caption);
1191 field_view_set = FALSE;
1193 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button), field_view_set);
1197 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1198 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1201 update_window_title (self);
1203 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1204 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1206 if ((body == NULL)||(body[0] == '\0')) {
1208 body = modest_text_utils_convert_to_html ("");
1211 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1212 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1215 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1218 /* Add attachments to the view */
1219 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1220 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1221 if (tny_list_get_length (priv->attachments) == 0) {
1222 gtk_widget_hide (priv->attachments_caption);
1224 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1225 gtk_widget_show_all (priv->attachments_caption);
1227 get_related_images (self, msg);
1228 update_next_cid (self, priv->attachments);
1229 update_next_cid (self, priv->images);
1230 replace_with_images (self, priv->images);
1232 if (preserve_is_rich && !is_html) {
1233 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1234 /* Get the default format required from configuration */
1235 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1236 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1239 /* Set the default focus depending on having already a To: field or not */
1240 if ((!to)||(*to == '\0')) {
1241 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1243 gtk_widget_grab_focus (priv->msg_body);
1246 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1248 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1249 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1251 modest_msg_edit_window_set_modified (self, FALSE);
1253 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1254 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1255 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1256 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1258 if (priv->msg_uid) {
1259 g_free (priv->msg_uid);
1260 priv->msg_uid = NULL;
1263 /* we should set a reference to the incoming message if it is a draft */
1264 msg_folder = tny_msg_get_folder (msg);
1266 if (modest_tny_folder_is_local_folder (msg_folder)) {
1267 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1268 if (type == TNY_FOLDER_TYPE_INVALID)
1269 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1271 if (type == TNY_FOLDER_TYPE_DRAFTS)
1272 priv->draft_msg = g_object_ref(msg);
1273 if (type == TNY_FOLDER_TYPE_OUTBOX)
1274 priv->outbox_msg = g_object_ref(msg);
1275 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1277 g_object_unref (msg_folder);
1287 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
1290 GList *item_children, *node;
1291 GtkWidget *bin_child;
1293 bin_child = gtk_bin_get_child (GTK_BIN(item));
1295 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
1297 for (node = item_children; node != NULL; node = g_list_next (node)) {
1298 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
1299 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
1302 g_list_free (item_children);
1306 menu_tool_button_dont_expand (GtkMenuToolButton *item)
1309 GList *item_children, *node;
1311 box = gtk_bin_get_child (GTK_BIN (item));
1312 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
1313 item_children = gtk_container_get_children (GTK_CONTAINER (box));
1315 for (node = item_children; node != NULL; node = g_list_next (node)) {
1316 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
1317 if (GTK_IS_TOGGLE_BUTTON (node->data))
1318 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
1319 else if (GTK_IS_BUTTON (node->data))
1320 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
1322 g_list_free (item_children);
1327 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1329 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1330 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1331 GtkWidget *placeholder;
1332 GtkWidget *tool_item;
1337 GtkWidget *sizes_menu;
1338 GtkWidget *fonts_menu;
1339 GSList *radio_group = NULL;
1340 GSList *node = NULL;
1344 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1345 gtk_toolbar_set_show_arrow (GTK_TOOLBAR (parent_priv->toolbar), FALSE);
1346 gtk_toolbar_set_icon_size (GTK_TOOLBAR (parent_priv->toolbar), HILDON_ICON_SIZE_FINGER);
1347 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1349 /* Font color placeholder */
1350 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1351 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1354 priv->font_color_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1355 priv->font_color_button = hildon_color_button_new ();
1356 gtk_widget_set_size_request (priv->font_color_button, -1, 48);
1357 GTK_WIDGET_UNSET_FLAGS (priv->font_color_toolitem, GTK_CAN_FOCUS);
1358 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1359 gtk_container_add (GTK_CONTAINER (priv->font_color_toolitem), priv->font_color_button);
1360 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1361 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1362 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->font_color_toolitem), insert_index);
1363 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1365 G_CALLBACK (modest_msg_edit_window_color_button_change),
1368 /* Font size and face placeholder */
1369 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1370 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1372 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1373 priv->size_tool_button_label = gtk_label_new (NULL);
1374 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1375 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1376 size_text,"</span>", NULL);
1377 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1379 hildon_helper_set_logical_font (priv->size_tool_button_label, "LargeSystemFont");
1380 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
1381 sizes_menu = gtk_menu_new ();
1382 priv->size_items_group = NULL;
1384 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1385 GtkWidget *size_menu_item;
1387 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1388 size_menu_item = gtk_radio_menu_item_new_with_label (radio_group, size_text);
1389 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (size_menu_item));
1390 gtk_menu_shell_append (GTK_MENU_SHELL (sizes_menu), size_menu_item);
1391 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (size_menu_item), (wp_font_size[size_index] == 12));
1392 gtk_widget_show (size_menu_item);
1394 priv->size_items_group = g_slist_prepend (priv->size_items_group, size_menu_item);
1398 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1399 GtkWidget *item = (GtkWidget *) node->data;
1400 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_size_change),
1404 priv->size_items_group = g_slist_reverse (priv->size_items_group);
1405 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), sizes_menu);
1406 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1407 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1408 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), FALSE);
1409 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), FALSE);
1410 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1411 priv->font_size_toolitem = tool_item;
1414 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1415 priv->font_tool_button_label = gtk_label_new (NULL);
1416 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1417 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1419 hildon_helper_set_logical_font (priv->font_tool_button_label, "LargeSystemFont");
1420 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
1421 fonts_menu = gtk_menu_new ();
1422 priv->font_items_group = NULL;
1424 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1425 GtkWidget *font_menu_item;
1426 GtkWidget *child_label;
1428 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
1429 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
1430 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
1431 wp_get_font_name (font_index), "</span>", NULL);
1432 gtk_label_set_markup (GTK_LABEL (child_label), markup);
1435 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
1436 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
1437 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
1438 gtk_widget_show (font_menu_item);
1440 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
1443 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1444 GtkWidget *item = (GtkWidget *) node->data;
1445 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
1448 priv->font_items_group = g_slist_reverse (priv->font_items_group);
1449 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
1450 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1451 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1452 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), FALSE);
1453 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), FALSE);
1454 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1455 priv->font_face_toolitem = tool_item;
1457 /* Set expand and homogeneous for remaining items */
1458 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
1459 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1460 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1461 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1462 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1463 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1464 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1465 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1466 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1468 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1469 will not show the tool items added to the placeholders) */
1470 gtk_widget_show_all (parent_priv->toolbar);
1472 /* Set the no show all *after* showing all items. We do not
1473 want the toolbar to be shown with a show all because it
1474 could go agains the gconf setting regarding showing or not
1475 the toolbar of the editor window */
1476 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1482 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, gboolean preserve_is_rich)
1485 ModestWindowPrivate *parent_priv;
1486 ModestMsgEditWindowPrivate *priv;
1487 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1488 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1489 ModestWindowMgr *mgr = NULL;
1491 g_return_val_if_fail (msg, NULL);
1492 g_return_val_if_fail (account_name, NULL);
1494 mgr = modest_runtime_get_window_mgr ();
1496 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1498 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1499 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1501 /* Menubar. Update the state of some toggles */
1502 priv->from_field_protos = get_transports ();
1503 modest_selector_picker_set_pair_list (MODEST_SELECTOR_PICKER (priv->from_field), priv->from_field_protos);
1504 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1505 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1506 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1508 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1509 hildon_touch_selector_get_current_text
1510 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1511 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1512 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1515 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1517 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1519 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1521 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1523 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1524 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1525 /* Add common dimming rules */
1526 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1527 modest_msg_edit_window_toolbar_dimming_entries,
1528 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1529 MODEST_WINDOW (obj));
1530 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_toolitem,
1531 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1532 MODEST_WINDOW (obj));
1533 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1534 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1535 MODEST_WINDOW (obj));
1536 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1537 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1538 MODEST_WINDOW (obj));
1539 /* Insert dimming rules group for this window */
1540 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1541 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1543 /* Setup app menu */
1544 setup_menu (MODEST_MSG_EDIT_WINDOW (obj));
1546 /* Checks the dimming rules */
1547 g_object_unref (toolbar_rules_group);
1548 g_object_unref (clipboard_rules_group);
1549 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1551 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1553 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1554 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1555 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1556 priv->update_caption_visibility = TRUE;
1558 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1560 /* Track account-removed signal, this window should be closed
1561 in the case we're creating a mail associated to the account
1563 priv->account_removed_handler_id =
1564 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1566 G_CALLBACK(on_account_removed),
1569 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1571 return (ModestWindow*) obj;
1575 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1577 GString **string_buffer = (GString **) user_data;
1579 *string_buffer = g_string_append (*string_buffer, buffer);
1585 * @result: A new string which should be freed with g_free().
1588 get_formatted_data (ModestMsgEditWindow *edit_window)
1590 ModestMsgEditWindowPrivate *priv;
1591 GString *string_buffer = g_string_new ("");
1593 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1595 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1597 modest_text_utils_hyperlinkify (string_buffer);
1599 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1601 return g_string_free (string_buffer, FALSE);
1606 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1609 const gchar *account_name;
1610 ModestMsgEditWindowPrivate *priv;
1611 TnyIterator *att_iter;
1613 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1615 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1617 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1618 g_return_val_if_fail (account_name, NULL);
1621 /* don't free these (except from) */
1622 data = g_slice_new0 (MsgData);
1623 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1625 data->account_name = g_strdup (account_name);
1626 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1627 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1628 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1629 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1630 if (priv->draft_msg) {
1631 data->draft_msg = g_object_ref (priv->draft_msg);
1632 } else if (priv->outbox_msg) {
1633 data->draft_msg = g_object_ref (priv->outbox_msg);
1635 data->draft_msg = NULL;
1638 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1640 gtk_text_buffer_get_bounds (buf, &b, &e);
1641 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1643 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1644 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1646 data->html_body = NULL;
1648 /* deep-copy the data */
1649 att_iter = tny_list_create_iterator (priv->attachments);
1650 data->attachments = NULL;
1651 while (!tny_iterator_is_done (att_iter)) {
1652 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1653 if (!(TNY_IS_MIME_PART(part))) {
1654 g_warning ("strange data in attachment list");
1655 g_object_unref (part);
1656 tny_iterator_next (att_iter);
1659 data->attachments = g_list_append (data->attachments,
1661 tny_iterator_next (att_iter);
1663 g_object_unref (att_iter);
1665 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1666 att_iter = tny_list_create_iterator (priv->images);
1667 data->images = NULL;
1668 while (!tny_iterator_is_done (att_iter)) {
1669 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1671 if (!(TNY_IS_MIME_PART(part))) {
1672 g_warning ("strange data in attachment list");
1673 g_object_unref (part);
1674 tny_iterator_next (att_iter);
1677 cid = tny_mime_part_get_content_id (part);
1679 gchar *image_tag_id;
1680 GtkTextTag *image_tag;
1682 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1683 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1684 g_free (image_tag_id);
1686 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1688 ((gtk_text_iter_has_tag (&iter, image_tag))||
1689 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1690 data->images = g_list_append (data->images,
1691 g_object_ref (part));
1693 g_object_unref (part);
1694 tny_iterator_next (att_iter);
1696 g_object_unref (att_iter);
1698 data->priority_flags = priv->priority_flags;
1705 unref_gobject (GObject *obj, gpointer data)
1707 if (!G_IS_OBJECT(obj))
1709 g_object_unref (obj);
1713 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1716 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1724 g_free (data->from);
1725 g_free (data->subject);
1726 g_free (data->plain_body);
1727 g_free (data->html_body);
1728 g_free (data->account_name);
1730 if (data->draft_msg != NULL) {
1731 g_object_unref (data->draft_msg);
1732 data->draft_msg = NULL;
1735 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1736 g_list_free (data->attachments);
1737 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1738 g_list_free (data->images);
1740 g_slice_free (MsgData, data);
1744 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1746 guint64 *parts_size)
1748 ModestMsgEditWindowPrivate *priv;
1750 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1752 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1754 /* TODO: add images */
1755 *parts_size += priv->images_size;
1756 *parts_count += priv->images_count;
1761 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1764 ModestMsgEditWindowPrivate *priv = NULL;
1765 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1767 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1769 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1771 return MODEST_MSG_EDIT_FORMAT_HTML;
1773 return MODEST_MSG_EDIT_FORMAT_TEXT;
1777 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1778 ModestMsgEditFormat format)
1780 ModestMsgEditWindowPrivate *priv;
1782 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1783 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1786 case MODEST_MSG_EDIT_FORMAT_HTML:
1787 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1789 case MODEST_MSG_EDIT_FORMAT_TEXT:
1790 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1793 g_return_if_reached ();
1797 ModestMsgEditFormatState *
1798 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1800 ModestMsgEditFormatState *format_state = NULL;
1801 ModestMsgEditWindowPrivate *priv;
1802 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1804 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1805 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1807 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1809 format_state = g_new0 (ModestMsgEditFormatState, 1);
1810 format_state->bold = buffer_format->bold&0x1;
1811 format_state->italics = buffer_format->italic&0x1;
1812 format_state->bullet = buffer_format->bullet&0x1;
1813 format_state->color = buffer_format->color;
1814 format_state->font_size = buffer_format->font_size;
1815 format_state->font_family = wp_get_font_name (buffer_format->font);
1816 format_state->justification = buffer_format->justification;
1817 g_free (buffer_format);
1819 return format_state;
1824 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1825 const ModestMsgEditFormatState *format_state)
1827 ModestMsgEditWindowPrivate *priv;
1828 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1829 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1830 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1831 g_return_if_fail (format_state != NULL);
1833 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1834 gtk_widget_grab_focus (priv->msg_body);
1835 buffer_format->bold = (format_state->bold != FALSE);
1836 buffer_format->italic = (format_state->italics != FALSE);
1837 buffer_format->color = format_state->color;
1838 buffer_format->font_size = format_state->font_size;
1839 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1840 buffer_format->justification = format_state->justification;
1841 buffer_format->bullet = format_state->bullet;
1843 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1845 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1846 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1847 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1848 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1849 buffer_format->cs.font = (buffer_format->font != current_format->font);
1850 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1851 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1853 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1854 if (buffer_format->cs.bold) {
1855 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
1856 GINT_TO_POINTER (buffer_format->bold&0x1));
1858 if (buffer_format->cs.italic) {
1859 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
1860 GINT_TO_POINTER (buffer_format->italic&0x1));
1862 if (buffer_format->cs.color) {
1863 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1864 GINT_TO_POINTER (&(buffer_format->color)));
1866 if (buffer_format->cs.font_size) {
1867 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1868 GINT_TO_POINTER (buffer_format->font_size));
1870 if (buffer_format->cs.justification) {
1871 switch (buffer_format->justification) {
1872 case GTK_JUSTIFY_LEFT:
1873 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
1874 GINT_TO_POINTER(TRUE));
1876 case GTK_JUSTIFY_CENTER:
1877 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
1878 GINT_TO_POINTER(TRUE));
1880 case GTK_JUSTIFY_RIGHT:
1881 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
1882 GINT_TO_POINTER(TRUE));
1889 if (buffer_format->cs.font) {
1890 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1891 GINT_TO_POINTER (buffer_format->font));
1893 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1894 if (buffer_format->cs.bullet) {
1895 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
1896 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
1898 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1900 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
1902 g_free (buffer_format);
1903 g_free (current_format);
1905 /* Check dimming rules */
1906 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1907 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1911 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1913 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1915 ModestWindowPrivate *parent_priv;
1916 ModestMsgEditWindowPrivate *priv;
1917 GtkWidget *new_size_menuitem;
1918 GtkWidget *new_font_menuitem;
1920 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1921 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1923 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1924 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu");
1925 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1926 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1928 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatPlainTextMenu");
1929 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1930 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1933 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1935 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1936 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1938 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1939 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1941 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
1942 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
1945 switch (buffer_format->justification)
1947 case GTK_JUSTIFY_LEFT:
1948 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
1950 case GTK_JUSTIFY_CENTER:
1951 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
1953 case GTK_JUSTIFY_RIGHT:
1954 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
1961 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
1963 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1964 G_CALLBACK (modest_msg_edit_window_color_button_change),
1966 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1967 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1968 G_CALLBACK (modest_msg_edit_window_color_button_change),
1971 new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group,
1972 buffer_format->font_size))->data);
1973 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1977 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1978 markup = g_strconcat ("<span font_family='Sans'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1979 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1981 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1982 G_CALLBACK (modest_msg_edit_window_size_change),
1984 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
1985 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
1986 G_CALLBACK (modest_msg_edit_window_size_change),
1990 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
1991 buffer_format->font))->data);
1992 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
1996 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
1997 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1998 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2000 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
2001 G_CALLBACK (modest_msg_edit_window_font_change),
2003 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
2004 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
2005 G_CALLBACK (modest_msg_edit_window_font_change),
2009 g_free (buffer_format);
2013 #ifdef MODEST_HILDON_VERSION_0
2015 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2018 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2019 ModestMsgEditWindowPrivate *priv;
2020 GtkWidget *dialog = NULL;
2022 GdkColor *new_color = NULL;
2024 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2025 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2027 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2028 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
2029 g_free (buffer_format);
2031 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2032 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2033 if (new_color != NULL) {
2034 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2035 (gpointer) new_color);
2038 gtk_widget_destroy (dialog);
2043 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2046 ModestMsgEditWindowPrivate *priv;
2047 GtkWidget *dialog = NULL;
2049 GdkColor *old_color = NULL;
2050 const GdkColor *new_color = NULL;
2052 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2053 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2055 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2056 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2058 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2059 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2060 if (new_color != NULL)
2061 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2063 gtk_widget_destroy (dialog);
2069 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2072 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2073 ModestMsgEditWindowPrivate *priv;
2074 GtkWidget *dialog = NULL;
2076 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2077 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2079 dialog = hildon_color_chooser_new ();
2080 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2081 g_free (buffer_format);
2083 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2085 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2086 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2089 gtk_widget_destroy (dialog);
2094 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2097 ModestMsgEditWindowPrivate *priv;
2098 GtkWidget *dialog = NULL;
2099 GdkColor *old_color = NULL;
2101 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2102 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2104 dialog = hildon_color_chooser_new ();
2105 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2107 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2109 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2110 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2112 gtk_widget_destroy (dialog);
2115 #endif /*!MODEST_HILDON_VERSION_0*/
2120 create_stream_for_uri (const gchar* uri)
2125 TnyStream *result = NULL;
2127 GnomeVFSHandle *handle = NULL;
2128 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2129 if (test == GNOME_VFS_OK) {
2130 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2131 /* Streams over OBEX (Bluetooth) are not seekable but
2132 * we expect them to be (we might need to read them
2133 * several times). So if this is a Bluetooth URI just
2134 * read the whole file into memory (this is not a fast
2135 * protocol so we can assume that these files are not
2136 * going to be very big) */
2137 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2138 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2139 TnyStream *memstream = tny_camel_mem_stream_new ();
2140 tny_stream_write_to_stream (vfssstream, memstream);
2141 g_object_unref (vfssstream);
2144 result = vfssstream;
2152 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2155 ModestMsgEditWindowPrivate *priv;
2156 GtkWidget *dialog = NULL;
2158 GSList *uris = NULL;
2159 GSList *uri_node = NULL;
2161 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2163 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2164 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2165 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2167 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2169 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2170 GTK_WINDOW (dialog), GTK_WINDOW (window));
2172 response = gtk_dialog_run (GTK_DIALOG (dialog));
2174 case GTK_RESPONSE_OK:
2175 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2180 gtk_widget_destroy (dialog);
2182 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2184 GnomeVFSHandle *handle = NULL;
2185 GnomeVFSResult result;
2186 GtkTextIter position;
2187 GtkTextMark *insert_mark;
2189 uri = (const gchar *) uri_node->data;
2190 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2191 if (result == GNOME_VFS_OK) {
2193 GnomeVFSFileInfo *info;
2194 gchar *filename, *basename, *escaped_filename;
2195 TnyMimePart *mime_part;
2197 const gchar *mime_type = NULL;
2198 GnomeVFSURI *vfs_uri;
2199 guint64 stream_size;
2201 gnome_vfs_close (handle);
2202 vfs_uri = gnome_vfs_uri_new (uri);
2204 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2205 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2206 g_free (escaped_filename);
2207 gnome_vfs_uri_unref (vfs_uri);
2208 info = gnome_vfs_file_info_new ();
2210 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2211 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2213 mime_type = gnome_vfs_file_info_get_mime_type (info);
2215 mime_part = tny_platform_factory_new_mime_part
2216 (modest_runtime_get_platform_factory ());
2218 TnyStream *stream = create_stream_for_uri (uri);
2220 if (stream == NULL) {
2222 modest_platform_information_banner (NULL, NULL,
2223 _FM("sfil_ib_opening_not_allowed"));
2225 g_object_unref (mime_part);
2226 gnome_vfs_file_info_unref (info);
2230 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2232 content_id = g_strdup_printf ("%d", priv->next_cid);
2233 tny_mime_part_set_content_id (mime_part, content_id);
2234 g_free (content_id);
2237 basename = g_path_get_basename (filename);
2238 tny_mime_part_set_filename (mime_part, basename);
2241 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
2243 if (pixbuf != NULL) {
2244 priv->images_size += stream_size;
2245 priv->images_count ++;
2246 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2247 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2248 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
2249 g_object_unref (pixbuf);
2252 tny_list_prepend (priv->images, (GObject *) mime_part);
2253 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2255 g_object_unref (mime_part);
2256 gnome_vfs_file_info_unref (info);
2265 on_attach_file_response (GtkDialog *dialog,
2269 GSList *uris = NULL;
2271 GnomeVFSFileSize total_size, allowed_size;
2272 ModestMsgEditWindow *window;
2273 ModestMsgEditWindowPrivate *priv;
2278 case GTK_RESPONSE_OK:
2279 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2285 window = MODEST_MSG_EDIT_WINDOW (user_data);
2286 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2288 /* allowed size is the maximum size - what's already there */
2289 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2290 &att_num, &att_size);
2291 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2294 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2296 const gchar *uri = (const gchar *) uri_node->data;
2299 modest_msg_edit_window_attach_file_one (window, uri, allowed_size);
2301 if (total_size > allowed_size) {
2302 g_warning ("%s: total size: %u",
2303 __FUNCTION__, (unsigned int)total_size);
2306 allowed_size -= total_size;
2308 g_slist_foreach (uris, (GFunc) g_free, NULL);
2309 g_slist_free (uris);
2311 gtk_widget_destroy (GTK_WIDGET (dialog));
2315 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2317 GtkWidget *dialog = NULL;
2318 ModestMsgEditWindowPrivate *priv;
2320 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2322 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2324 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2327 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window),
2328 GTK_FILE_CHOOSER_ACTION_OPEN);
2329 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2330 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2331 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2332 GTK_WINDOW (dialog), GTK_WINDOW (window));
2334 /* Connect to response & show */
2335 g_signal_connect (dialog, "response",
2336 G_CALLBACK (on_attach_file_response), window);
2337 gtk_widget_show (dialog);
2342 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2344 GnomeVFSFileSize allowed_size)
2347 GnomeVFSHandle *handle = NULL;
2348 ModestMsgEditWindowPrivate *priv;
2349 GnomeVFSResult result;
2350 GnomeVFSFileSize size = 0;
2351 g_return_val_if_fail (window, 0);
2352 g_return_val_if_fail (uri, 0);
2354 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2356 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2357 if (result == GNOME_VFS_OK) {
2358 TnyMimePart *mime_part;
2360 const gchar *mime_type = NULL;
2362 gchar *escaped_filename;
2365 GnomeVFSFileInfo *info;
2366 GnomeVFSURI *vfs_uri;
2368 gnome_vfs_close (handle);
2369 vfs_uri = gnome_vfs_uri_new (uri);
2372 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2373 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2374 g_free (escaped_filename);
2375 gnome_vfs_uri_unref (vfs_uri);
2377 info = gnome_vfs_file_info_new ();
2379 if (gnome_vfs_get_file_info (uri,
2381 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2383 mime_type = gnome_vfs_file_info_get_mime_type (info);
2384 mime_part = tny_platform_factory_new_mime_part
2385 (modest_runtime_get_platform_factory ());
2387 /* try to get the attachment's size; this may fail for weird
2388 * file systems, like obex, upnp... */
2389 if (allowed_size != 0 &&
2390 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2392 if (size > allowed_size) {
2393 modest_platform_information_banner (NULL, NULL,
2394 _FM("sfil_ib_opening_not_allowed"));
2398 g_warning ("%s: could not get attachment size", __FUNCTION__);
2400 stream = create_stream_for_uri (uri);
2402 if (stream == NULL) {
2404 modest_platform_information_banner (NULL, NULL, _FM("sfil_ib_opening_not_allowed"));
2406 g_object_unref (mime_part);
2407 gnome_vfs_file_info_unref (info);
2411 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2412 g_object_unref (stream);
2414 content_id = g_strdup_printf ("%d", priv->next_cid);
2415 tny_mime_part_set_content_id (mime_part, content_id);
2416 g_free (content_id);
2419 basename = g_path_get_basename (filename);
2420 tny_mime_part_set_filename (mime_part, basename);
2423 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2424 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2426 info->size == 0, info->size);
2427 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2428 gtk_widget_show_all (priv->attachments_caption);
2429 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2431 g_object_unref (mime_part);
2432 gnome_vfs_file_info_unref (info);
2439 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2442 ModestMsgEditWindowPrivate *priv;
2445 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2446 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2448 if (att_list == NULL) {
2449 att_list = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2450 if (!modest_maemo_utils_select_attachments (GTK_WINDOW (window), att_list)) {
2451 g_object_unref (att_list);
2456 g_object_ref (att_list);
2459 if (tny_list_get_length (att_list) == 0) {
2460 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2462 gboolean dialog_response;
2463 gchar *message = NULL;
2464 gchar *filename = NULL;
2466 if (tny_list_get_length (att_list) == 1) {
2468 iter = tny_list_create_iterator (att_list);
2469 part = (TnyMimePart *) tny_iterator_get_current (iter);
2470 g_object_unref (iter);
2471 if (TNY_IS_MSG (part)) {
2472 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2474 filename = tny_header_dup_subject (header);
2475 g_object_unref (header);
2477 if (filename == NULL) {
2478 filename = g_strdup (_("mail_va_no_subject"));
2481 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2483 g_object_unref (part);
2485 filename = g_strdup ("");
2487 message = g_strdup_printf (ngettext("emev_nc_delete_attachment",
2488 "emev_nc_delete_attachments",
2489 tny_list_get_length (att_list)), filename);
2492 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
2496 if (dialog_response != GTK_RESPONSE_OK) {
2497 g_object_unref (att_list);
2501 for (iter = tny_list_create_iterator (att_list);
2502 !tny_iterator_is_done (iter);
2503 tny_iterator_next (iter)) {
2504 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2505 const gchar *att_id;
2506 tny_list_remove (priv->attachments, (GObject *) mime_part);
2508 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2510 if (tny_list_get_length (priv->attachments) == 0)
2511 gtk_widget_hide (priv->attachments_caption);
2512 att_id = tny_mime_part_get_content_id (mime_part);
2514 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2516 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2517 g_object_unref (mime_part);
2519 g_object_unref (iter);
2522 g_object_unref (att_list);
2524 /* if the last attachment has been removed, focus the Subject: field */
2525 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2526 gtk_widget_grab_focus (priv->subject_field);
2530 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2533 ModestMsgEditWindowPrivate *priv;
2534 GdkColor *new_color;
2535 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2537 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2538 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2541 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2543 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2545 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2547 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2552 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
2555 ModestMsgEditWindowPrivate *priv;
2556 gint new_size_index;
2557 ModestMsgEditWindow *window;
2560 window = MODEST_MSG_EDIT_WINDOW (userdata);
2561 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2562 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2564 if (gtk_check_menu_item_get_active (menu_item)) {
2566 WPTextBufferFormat format;
2568 memset (&format, 0, sizeof (format));
2569 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2571 label = gtk_bin_get_child (GTK_BIN (menu_item));
2573 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
2574 format.cs.font_size = TRUE;
2575 format.cs.text_position = TRUE;
2576 format.cs.font = TRUE;
2577 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
2578 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2580 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2581 GINT_TO_POINTER (wp_get_font_size_index (new_size_index, 12))))
2582 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2584 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2585 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
2586 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2592 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
2595 ModestMsgEditWindowPrivate *priv;
2596 gint new_font_index;
2597 ModestMsgEditWindow *window;
2600 window = MODEST_MSG_EDIT_WINDOW (userdata);
2601 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2602 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2604 if (gtk_check_menu_item_get_active (menu_item)) {
2607 label = gtk_bin_get_child (GTK_BIN (menu_item));
2609 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
2611 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2612 GINT_TO_POINTER(new_font_index)))
2613 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2615 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2616 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2617 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2623 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2626 ModestMsgEditWindowPrivate *priv = NULL;
2627 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2629 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2630 if (!priv->update_caption_visibility)
2633 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2635 gtk_widget_show (priv->cc_caption);
2637 gtk_widget_hide (priv->cc_caption);
2639 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2643 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2646 ModestMsgEditWindowPrivate *priv = NULL;
2647 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2649 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2650 if (!priv->update_caption_visibility)
2653 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2655 gtk_widget_show (priv->bcc_caption);
2657 gtk_widget_hide (priv->bcc_caption);
2659 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2663 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2664 ModestRecptEditor *editor)
2666 ModestMsgEditWindowPrivate *priv;
2668 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2669 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2671 /* we check for low-mem; in that case, show a warning, and don't allow
2672 * for the addressbook
2674 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2677 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2679 if (editor == NULL) {
2680 GtkWidget *view_focus;
2681 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2683 /* This code should be kept in sync with ModestRecptEditor. The
2684 textview inside the recpt editor is the one that really gets the
2685 focus. As it's inside a scrolled window, and this one inside the
2686 hbox recpt editor inherits from, we'll need to go up in the
2687 hierarchy to know if the text view is part of the recpt editor
2688 or if it's a different text entry */
2690 if (gtk_widget_get_parent (view_focus)) {
2691 GtkWidget *first_parent;
2693 first_parent = gtk_widget_get_parent (view_focus);
2694 if (gtk_widget_get_parent (first_parent) &&
2695 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2696 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2701 editor = MODEST_RECPT_EDITOR (priv->to_field);
2705 modest_address_book_select_addresses (editor);
2710 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2712 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2714 modest_msg_edit_window_open_addressbook (window, NULL);
2718 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2719 gboolean show_toolbar)
2721 ModestWindowPrivate *parent_priv;
2723 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2724 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2726 /* We can not just use the code of
2727 modest_msg_edit_window_setup_toolbar because it has a
2728 mixture of both initialization and creation code. */
2730 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2732 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2736 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2737 TnyHeaderFlags priority_flags)
2739 ModestMsgEditWindowPrivate *priv;
2740 ModestWindowPrivate *parent_priv;
2742 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2744 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2745 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2747 if (priv->priority_flags != priority_flags) {
2748 GtkAction *priority_action = NULL;
2750 priv->priority_flags = priority_flags;
2752 switch (priority_flags) {
2753 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2754 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2755 MODEST_HEADER_ICON_HIGH,
2756 HILDON_ICON_SIZE_XSMALL);
2757 gtk_widget_show (priv->priority_icon);
2758 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2759 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2761 case TNY_HEADER_FLAG_LOW_PRIORITY:
2762 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2763 MODEST_HEADER_ICON_LOW,
2764 HILDON_ICON_SIZE_XSMALL);
2765 gtk_widget_show (priv->priority_icon);
2766 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2767 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2770 gtk_widget_hide (priv->priority_icon);
2771 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2772 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2775 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2776 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2781 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2784 ModestMsgEditWindowPrivate *priv;
2785 ModestWindowPrivate *parent_priv;
2786 gint current_format;
2788 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2790 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2791 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2793 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2794 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2796 if (current_format != file_format) {
2797 switch (file_format) {
2798 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2799 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2800 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
2802 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2806 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2807 response = gtk_dialog_run (GTK_DIALOG (dialog));
2808 gtk_widget_destroy (dialog);
2809 if (response == GTK_RESPONSE_OK) {
2810 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2812 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
2813 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
2818 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2819 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2820 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2825 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2828 ModestMsgEditWindowPrivate *priv;
2829 WPTextBufferFormat oldfmt, fmt;
2830 gint old_position = 0;
2834 GdkColor *color = NULL;
2835 gboolean bold, bold_set, italic, italic_set;
2836 gboolean underline, underline_set;
2837 gboolean strikethrough, strikethrough_set;
2838 gboolean position_set;
2839 gboolean font_size_set, font_set, color_set;
2842 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2843 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2845 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2846 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
2847 GTK_WINDOW(dialog), GTK_WINDOW (window));
2849 /* First we get the currently selected font information */
2850 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2852 switch (oldfmt.text_position) {
2853 case TEXT_POSITION_NORMAL:
2856 case TEXT_POSITION_SUPERSCRIPT:
2864 g_object_set (G_OBJECT (dialog),
2865 "bold", oldfmt.bold != FALSE,
2866 "bold-set", !oldfmt.cs.bold,
2867 "underline", oldfmt.underline != FALSE,
2868 "underline-set", !oldfmt.cs.underline,
2869 "italic", oldfmt.italic != FALSE,
2870 "italic-set", !oldfmt.cs.italic,
2871 "strikethrough", oldfmt.strikethrough != FALSE,
2872 "strikethrough-set", !oldfmt.cs.strikethrough,
2873 "color", &oldfmt.color,
2874 "color-set", !oldfmt.cs.color,
2875 "size", wp_font_size[oldfmt.font_size],
2876 "size-set", !oldfmt.cs.font_size,
2877 "position", old_position,
2878 "position-set", !oldfmt.cs.text_position,
2879 "family", wp_get_font_name (oldfmt.font),
2880 "family-set", !oldfmt.cs.font,
2883 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2884 GTK_WINDOW (dialog), GTK_WINDOW (window));
2885 gtk_widget_show_all (dialog);
2886 priv->font_dialog = dialog;
2887 response = gtk_dialog_run (GTK_DIALOG (dialog));
2888 priv->font_dialog = NULL;
2889 if (response == GTK_RESPONSE_OK) {
2891 g_object_get( dialog,
2893 "bold-set", &bold_set,
2894 "underline", &underline,
2895 "underline-set", &underline_set,
2897 "italic-set", &italic_set,
2898 "strikethrough", &strikethrough,
2899 "strikethrough-set", &strikethrough_set,
2901 "color-set", &color_set,
2903 "size-set", &font_size_set,
2904 "family", &font_name,
2905 "family-set", &font_set,
2906 "position", &position,
2907 "position-set", &position_set,
2912 if (response == GTK_RESPONSE_OK) {
2913 memset(&fmt, 0, sizeof(fmt));
2919 fmt.italic = italic;
2920 fmt.cs.italic = TRUE;
2922 if (underline_set) {
2923 fmt.underline = underline;
2924 fmt.cs.underline = TRUE;
2926 if (strikethrough_set) {
2927 fmt.strikethrough = strikethrough;
2928 fmt.cs.strikethrough = TRUE;
2933 ? TEXT_POSITION_NORMAL
2934 : ( ( position == 1 )
2935 ? TEXT_POSITION_SUPERSCRIPT
2936 : TEXT_POSITION_SUBSCRIPT );
2937 fmt.cs.text_position = TRUE;
2938 fmt.font_size = oldfmt.font_size;
2942 fmt.cs.color = TRUE;
2945 fmt.font = wp_get_font_index(font_name,
2950 if (font_size_set) {
2951 fmt.cs.font_size = TRUE;
2952 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
2954 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2955 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2957 gtk_widget_destroy (dialog);
2959 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2963 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2965 ModestMsgEditWindowPrivate *priv;
2967 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2968 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2970 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2972 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2973 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2977 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
2979 ModestMsgEditWindowPrivate *priv;
2981 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2982 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2984 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
2986 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2987 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2992 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
2994 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2996 priv->can_undo = can_undo;
3000 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
3002 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3004 priv->can_redo = can_redo;
3008 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3010 ModestMsgEditWindowPrivate *priv;
3011 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3012 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3014 return priv->can_undo;
3018 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3020 ModestMsgEditWindowPrivate *priv;
3021 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3022 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3024 return priv->can_redo;
3029 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3032 GtkTextIter match_start, match_end;
3034 if (image_id == NULL)
3037 gtk_text_buffer_get_start_iter (buffer, &iter);
3039 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3040 GSList *tags = gtk_text_iter_get_tags (&match_start);
3042 for (node = tags; node != NULL; node = g_slist_next (node)) {
3043 GtkTextTag *tag = (GtkTextTag *) node->data;
3044 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3045 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3046 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3048 offset = gtk_text_iter_get_offset (&match_start);
3049 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3050 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3054 gtk_text_iter_forward_char (&iter);
3059 message_is_empty (ModestMsgEditWindow *window)
3061 ModestMsgEditWindowPrivate *priv = NULL;
3063 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3064 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3066 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3067 * so we can ignore markup.
3069 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3072 count = gtk_text_buffer_get_char_count (buf);
3078 msg_body_focus (GtkWidget *focus,
3079 GdkEventFocus *event,
3083 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3084 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3085 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3090 recpt_field_changed (GtkTextBuffer *buffer,
3091 ModestMsgEditWindow *editor)
3093 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3094 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3098 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3100 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3101 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3105 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3108 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3109 GtkTextBuffer *buffer;
3111 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3112 gtk_text_buffer_set_modified (buffer, modified);
3113 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3114 gtk_text_buffer_set_modified (buffer, modified);
3115 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3116 gtk_text_buffer_set_modified (buffer, modified);
3117 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3121 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3123 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3124 const char *account_name;
3125 GtkTextBuffer *buffer;
3127 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3128 if (gtk_text_buffer_get_modified (buffer))
3130 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3131 if (gtk_text_buffer_get_modified (buffer))
3133 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3134 if (gtk_text_buffer_get_modified (buffer))
3136 if (gtk_text_buffer_get_modified (priv->text_buffer))
3138 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3139 if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3150 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3152 ModestMsgEditWindowPrivate *priv = NULL;
3154 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3155 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3157 /* check if there's no recipient added */
3158 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3159 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3160 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3161 /* no recipient contents, then select contacts */
3162 modest_msg_edit_window_open_addressbook (window, NULL);
3166 g_object_ref (window);
3167 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3168 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3169 g_object_unref (window);
3172 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3173 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3174 g_object_unref (window);
3177 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3178 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3179 g_object_unref (window);
3183 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3184 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3185 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3186 g_object_unref (window);
3193 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3194 ModestMsgEditWindow *window)
3196 modest_msg_edit_window_offer_attach_file (window);
3200 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3202 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3204 return priv->clipboard_text;
3208 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3210 ModestMsgEditWindow *window)
3212 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3213 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3215 if (!GTK_WIDGET_VISIBLE (window))
3218 g_object_ref (window);
3219 text = gtk_clipboard_wait_for_text (selection_clipboard);
3221 if (priv->clipboard_text != NULL) {
3222 g_free (priv->clipboard_text);
3224 priv->clipboard_text = text;
3226 if (GTK_WIDGET_VISIBLE (window)) {
3227 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3229 g_object_unref (window);
3232 static gboolean clipboard_owner_change_idle (gpointer userdata)
3234 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3235 ModestMsgEditWindowPrivate *priv;
3237 gdk_threads_enter ();
3238 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3239 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3241 priv->clipboard_owner_idle = 0;
3242 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3243 gdk_threads_leave ();
3249 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3251 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3252 if (priv->clipboard_owner_idle == 0) {
3253 priv->clipboard_owner_idle = g_idle_add (clipboard_owner_change_idle, window);
3258 subject_field_move_cursor (GtkEntry *entry,
3259 GtkMovementStep step,
3264 if (!GTK_WIDGET_VISIBLE (window))
3267 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3271 update_window_title (ModestMsgEditWindow *window)
3273 ModestMsgEditWindowPrivate *priv = NULL;
3274 const gchar *subject;
3276 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3277 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3278 if (subject == NULL || subject[0] == '\0')
3279 subject = _("mail_va_new_email");
3281 gtk_window_set_title (GTK_WINDOW (window), subject);
3286 subject_field_changed (GtkEditable *editable,
3287 ModestMsgEditWindow *window)
3289 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3290 update_window_title (window);
3291 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3292 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3293 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3297 subject_field_insert_text (GtkEditable *editable,
3299 gint new_text_length,
3301 ModestMsgEditWindow *window)
3303 GString *result = g_string_new ("");
3305 gint result_len = 0;
3306 const gchar *entry_text = NULL;
3309 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3310 old_length = g_utf8_strlen (entry_text, -1);
3312 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3313 gunichar c = g_utf8_get_char_validated (current, 8);
3314 /* Invalid unichar, stop */
3320 result = g_string_append_unichar (result, c);
3324 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3325 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3328 /* Prevent endless recursion */
3329 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3330 g_signal_emit_by_name (editable, "insert-text",
3331 (gpointer) result->str, (gpointer) result->len,
3332 (gpointer) position, (gpointer) window);
3333 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3337 if (result_len + old_length > 1000) {
3338 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3339 _CS("ckdg_ib_maximum_characters_reached"));
3341 g_string_free (result, TRUE);
3345 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3348 ModestMsgEditWindowPrivate *priv = NULL;
3350 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3351 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3353 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3356 gtk_widget_show_all (priv->find_toolbar);
3357 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3359 gtk_widget_hide_all (priv->find_toolbar);
3360 gtk_widget_grab_focus (priv->msg_body);
3365 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3367 GtkTextIter *match_start,
3368 GtkTextIter *match_end)
3370 GtkTextIter end_iter;
3371 gchar *str_casefold;
3374 gchar *range_casefold;
3377 gboolean result = FALSE;
3384 gtk_text_iter_forward_to_end (&end_iter);
3386 str_casefold = g_utf8_casefold (str, -1);
3387 str_chars_n = strlen (str);
3389 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3390 range_casefold = g_utf8_casefold (range_text, -1);
3391 range_chars_n = strlen (range_casefold);
3393 if (range_chars_n < str_chars_n) {
3394 g_free (str_casefold);
3395 g_free (range_text);
3396 g_free (range_casefold);
3400 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3401 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3402 if (!g_utf8_collate (range_subtext, str_casefold)) {
3403 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3405 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3406 match_start, match_end, NULL);
3407 g_free (found_text);
3409 g_free (range_subtext);
3413 g_free (str_casefold);
3414 g_free (range_text);
3415 g_free (range_casefold);
3422 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3423 ModestMsgEditWindow *window)
3425 gchar *current_search = NULL;
3426 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3428 GtkTextIter selection_start, selection_end;
3429 GtkTextIter match_start, match_end;
3430 gboolean continue_search = FALSE;
3432 if (message_is_empty (window)) {
3433 g_free (priv->last_search);
3434 priv->last_search = NULL;
3435 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3439 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3440 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3441 g_free (current_search);
3442 g_free (priv->last_search);
3443 priv->last_search = NULL;
3444 /* Information banner about empty search */
3445 hildon_banner_show_information (NULL, NULL, _CS("ecdg_ib_find_rep_enter_text"));
3449 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3450 continue_search = TRUE;
3452 g_free (priv->last_search);
3453 priv->last_search = g_strdup (current_search);
3456 if (continue_search) {
3457 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3458 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3459 &match_start, &match_end);
3461 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_search_complete"));
3463 GtkTextIter buffer_start;
3464 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3465 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3466 &match_start, &match_end);
3468 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_no_matches"));
3471 /* Mark as selected the string found in search */
3473 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3474 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3475 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3477 g_free (priv->last_search);
3478 priv->last_search = NULL;
3480 g_free (current_search);
3484 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3486 ModestMsgEditWindowPrivate *priv;
3488 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3493 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3496 ModestMsgEditWindowPrivate *priv;
3498 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3503 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3504 ModestMsgEditWindow *window)
3506 modest_msg_edit_window_toggle_find_toolbar (window, FALSE);
3510 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3513 ModestMsgEditWindowPrivate *priv;
3514 TnyHeader *header = NULL;
3516 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3517 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3519 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3520 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3522 if (priv->draft_msg != NULL) {
3523 g_object_unref (priv->draft_msg);
3526 if (draft != NULL) {
3527 g_object_ref (draft);
3528 header = tny_msg_get_header (draft);
3529 if (priv->msg_uid) {
3530 g_free (priv->msg_uid);
3531 priv->msg_uid = NULL;
3533 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3534 if (GTK_WIDGET_REALIZED (window)) {
3535 if (!modest_window_mgr_register_window (mgr, MODEST_WINDOW (window), NULL)) {
3536 gtk_widget_destroy (GTK_WIDGET (window));
3542 priv->draft_msg = draft;
3546 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3547 GtkTextIter *start, GtkTextIter *end,
3550 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3551 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3554 if (tag == NULL) return;
3555 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3556 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3557 replace_with_images (window, priv->images);
3562 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3565 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3567 g_return_if_fail (TNY_IS_MIME_PART (part));
3568 tny_list_prepend (priv->attachments, (GObject *) part);
3569 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3570 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3571 gtk_widget_show_all (priv->attachments_caption);
3572 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3576 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3578 ModestMsgEditWindowPrivate *priv;
3580 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3581 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3583 return priv->msg_uid;
3587 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3588 ModestMsgEditWindowWidgetType widget_type)
3590 ModestMsgEditWindowPrivate *priv;
3592 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3593 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3595 switch (widget_type) {
3596 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3597 return priv->msg_body;
3599 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3600 return priv->to_field;
3602 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3603 return priv->cc_field;
3605 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3606 return priv->bcc_field;
3608 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3609 return priv->subject_field;
3611 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3612 return priv->attachments_view;
3620 remove_tags (WPTextBuffer *buffer)
3622 GtkTextIter start, end;
3624 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3625 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3627 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3631 on_account_removed (TnyAccountStore *account_store,
3632 TnyAccount *account,
3635 /* Do nothing if it's a store account, because we use the
3636 transport to send the messages */
3637 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3638 const gchar *parent_acc = NULL;
3639 const gchar *our_acc = NULL;
3641 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3642 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3643 /* Close this window if I'm showing a message of the removed account */
3644 if (strcmp (parent_acc, our_acc) == 0)
3645 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3650 from_field_changed (HildonPickerButton *button,
3651 ModestMsgEditWindow *self)
3653 ModestMsgEditWindowPrivate *priv;
3654 gboolean has_old_signature, has_new_signature;
3656 GtkTextIter match_start, match_end;
3657 ModestAccountMgr *mgr;
3659 gchar *full_signature;
3661 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3663 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
3664 mgr = modest_runtime_get_account_mgr ();
3665 signature = modest_account_mgr_get_signature (mgr, priv->last_from_account, &has_old_signature);
3666 if (has_old_signature) {
3667 full_signature = g_strconcat ("\n--\n", signature, NULL);
3668 if (gtk_text_iter_forward_search (&iter, full_signature, 0, &match_start, &match_end, NULL)) {
3669 gtk_text_buffer_delete (priv->text_buffer, &match_start, &match_end);
3671 } else if (gtk_text_iter_forward_search (&iter, _("mcen_ia_editor_original_message"), 0,
3672 &match_start, &match_end, NULL)) {
3675 g_free (full_signature);
3679 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3680 signature = modest_account_mgr_get_signature (mgr, priv->last_from_account, &has_new_signature);
3681 if (has_new_signature) {
3682 full_signature = g_strconcat ("\n--\n", signature, NULL);
3683 gtk_text_buffer_insert (priv->text_buffer, &iter, full_signature, -1);
3684 g_free (full_signature);
3689 typedef struct _MessageSettingsHelper {
3690 ModestMsgEditWindow *window;
3691 GSList *priority_group;
3692 GSList *format_group;
3693 GtkToggleButton *current_priority;
3694 GtkToggleButton *current_format;
3695 } MessageSettingsHelper;
3698 on_priority_toggle (GtkToggleButton *button,
3699 MessageSettingsHelper *helper)
3702 ModestMsgEditWindowPrivate *priv;
3704 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3705 if (gtk_toggle_button_get_active (button)) {
3707 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3708 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3709 if ((node_button != button) &&
3710 gtk_toggle_button_get_active (node_button)) {
3711 gtk_toggle_button_set_active (node_button, FALSE);
3714 helper->current_priority = button;
3716 gboolean found = FALSE;
3717 /* If no one is active, activate it again */
3718 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3719 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3720 if (gtk_toggle_button_get_active (node_button)) {
3726 gtk_toggle_button_set_active (button, TRUE);
3732 on_format_toggle (GtkToggleButton *button,
3733 MessageSettingsHelper *helper)
3736 ModestMsgEditWindowPrivate *priv;
3738 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3739 if (gtk_toggle_button_get_active (button)) {
3741 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
3742 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3743 if ((node_button != button) &&
3744 gtk_toggle_button_get_active (node_button)) {
3745 gtk_toggle_button_set_active (node_button, FALSE);
3748 helper->current_format = button;
3750 gboolean found = FALSE;
3751 /* If no one is active, activate it again */
3752 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
3753 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3754 if (gtk_toggle_button_get_active (node_button)) {
3760 gtk_toggle_button_set_active (button, TRUE);
3767 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
3771 GtkWidget *priority_hbox;
3772 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
3773 GtkWidget *captioned;
3774 GtkSizeGroup *title_sizegroup, *value_sizegroup;
3775 GtkWidget *format_hbox;
3776 GtkWidget *html_toggle, *text_toggle;
3777 ModestMsgEditWindowPrivate *priv;
3778 MessageSettingsHelper helper = {0,};
3780 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3781 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3782 helper.window = window;
3783 helper.priority_group = NULL;
3785 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3786 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3788 dialog = gtk_dialog_new_with_buttons (_("mcen_me_message_settings"), NULL,
3789 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
3790 _HL("wdgt_bd_done"), GTK_RESPONSE_ACCEPT, NULL);
3791 vbox = gtk_vbox_new (FALSE, 0);
3792 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), vbox);
3793 gtk_widget_show (vbox);
3795 /* Priority toggles */
3796 priority_hbox = gtk_hbox_new (TRUE, 0);
3797 high_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3798 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
3799 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
3800 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
3801 medium_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3802 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
3803 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
3804 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
3805 low_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3806 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
3807 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
3808 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
3809 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, TRUE, TRUE, 0);
3810 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, TRUE, TRUE, 0);
3811 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, TRUE, TRUE, 0);
3812 gtk_widget_show_all (priority_hbox);
3813 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
3814 _("mcen_me_editor_message_priority"), FALSE, priority_hbox);
3815 gtk_widget_show (captioned);
3816 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
3818 /* format toggles */
3819 format_hbox = gtk_hbox_new (TRUE, 0);
3820 html_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3821 gtk_button_set_label (GTK_BUTTON (html_toggle), _("mcen_me_editor_formatted_text"));
3822 helper.format_group = g_slist_prepend (helper.format_group, html_toggle);
3823 g_object_set_data (G_OBJECT (html_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_HTML));
3824 g_object_set_data (G_OBJECT (html_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_FORMATTED_TEXT));
3825 text_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3826 gtk_button_set_label (GTK_BUTTON (text_toggle), _("mcen_me_editor_plain_text"));
3827 helper.format_group = g_slist_prepend (helper.format_group, text_toggle);
3828 g_object_set_data (G_OBJECT (text_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_TEXT));
3829 g_object_set_data (G_OBJECT (text_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_PLAIN_TEXT));
3830 gtk_box_pack_start (GTK_BOX (format_hbox), html_toggle, TRUE, TRUE, 0);
3831 gtk_box_pack_start (GTK_BOX (format_hbox), text_toggle, TRUE, TRUE, 0);
3832 gtk_widget_show_all (format_hbox);
3833 gtk_widget_show (format_hbox);
3834 gtk_box_pack_start (GTK_BOX (vbox), format_hbox, FALSE, FALSE, 0);
3837 g_object_unref (title_sizegroup);
3838 g_object_unref (value_sizegroup);
3840 /* Set current values */
3841 switch (priv->priority_flags) {
3842 case TNY_HEADER_FLAG_HIGH_PRIORITY:
3843 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (high_toggle), TRUE);
3844 helper.current_priority = GTK_TOGGLE_BUTTON (high_toggle);
3846 case TNY_HEADER_FLAG_LOW_PRIORITY:
3847 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (low_toggle), TRUE);
3848 helper.current_priority = GTK_TOGGLE_BUTTON (low_toggle);
3851 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (medium_toggle), TRUE);
3852 helper.current_priority = GTK_TOGGLE_BUTTON (medium_toggle);
3856 switch (modest_msg_edit_window_get_format (window)) {
3857 case MODEST_MSG_EDIT_FORMAT_TEXT:
3858 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_toggle), TRUE);
3859 helper.current_format = GTK_TOGGLE_BUTTON (text_toggle);
3861 case MODEST_MSG_EDIT_FORMAT_HTML:
3863 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (html_toggle), TRUE);
3864 helper.current_format = GTK_TOGGLE_BUTTON (html_toggle);
3868 /* Signal connects */
3869 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3870 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3871 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3872 g_signal_connect (G_OBJECT (html_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
3873 g_signal_connect (G_OBJECT (text_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
3875 /* Save settings if the user clicked on done */
3876 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
3877 TnyHeaderFlags flags;
3878 ModestMsgEditFormat old_format, new_format;
3880 /* Set priority flags */
3881 flags = (TnyHeaderFlags) g_object_get_data (G_OBJECT (helper.current_priority), "priority");
3882 if (priv->priority_flags != flags)
3883 modest_msg_edit_window_set_priority_flags (window, flags);
3885 /* Set edit format */
3886 old_format = modest_msg_edit_window_get_format (window);
3887 new_format = (ModestMsgEditFormat) g_object_get_data (G_OBJECT (helper.current_format), "format");
3888 if (old_format != new_format) {
3889 gint file_format = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (helper.current_format), "file-format"));
3890 modest_msg_edit_window_set_file_format (window, file_format);
3894 gtk_widget_destroy (dialog);
3895 g_slist_free (helper.priority_group);
3899 on_message_settings (GtkAction *action,
3900 ModestMsgEditWindow *window)
3902 modest_msg_edit_window_show_msg_settings_dialog (window);
3906 on_cc_button_toggled (HildonCheckButton *button,
3907 ModestMsgEditWindow *window)
3909 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
3911 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
3912 hildon_check_button_get_active (button));
3916 on_bcc_button_toggled (HildonCheckButton *button,
3917 ModestMsgEditWindow *window)
3919 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
3921 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
3922 hildon_check_button_get_active (button));
3926 setup_menu (ModestMsgEditWindow *self)
3928 ModestMsgEditWindowPrivate *priv = NULL;
3930 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
3932 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3934 /* Settings menu buttons */
3935 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_checknames"), NULL,
3936 APP_MENU_CALLBACK (modest_ui_actions_on_check_names),
3938 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_undo"), "<Ctrl>z",
3939 APP_MENU_CALLBACK (modest_ui_actions_on_undo),
3940 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_undo));
3942 priv->cc_button = hildon_check_button_new (0);
3943 gtk_button_set_label (GTK_BUTTON (priv->cc_button), _("mcen_me_editor_showcc"));
3944 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button),
3946 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->cc_button),
3948 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
3949 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
3950 priv->bcc_button = hildon_check_button_new (0);
3951 gtk_button_set_label (GTK_BUTTON (priv->bcc_button), _("mcen_me_editor_showbcc"));
3952 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button),
3954 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->bcc_button),
3956 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
3957 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
3959 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_attach_inlineimage"), NULL,
3960 APP_MENU_CALLBACK (modest_ui_actions_on_insert_image),
3961 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_set_style));
3962 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_remove_attachments"), NULL,
3963 APP_MENU_CALLBACK (modest_ui_actions_on_remove_attachments),
3964 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
3965 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_message_settings"), NULL,
3966 APP_MENU_CALLBACK (on_message_settings),
3968 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_viewer_find"), "<Ctrl>f",
3969 APP_MENU_CALLBACK (modest_ui_actions_on_toggle_find_in_page),