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 *subject_box;
251 GtkWidget *add_attachment_button;
253 GtkWidget *cc_caption;
254 GtkWidget *bcc_caption;
255 gboolean update_caption_visibility;
256 GtkWidget *attachments_caption;
258 GtkTextBuffer *text_buffer;
260 GtkWidget *font_size_toolitem;
261 GtkWidget *font_face_toolitem;
262 GtkWidget *font_color_button;
263 GtkWidget *font_color_toolitem;
264 GSList *font_items_group;
265 GtkWidget *font_tool_button_label;
266 GSList *size_items_group;
267 GtkWidget *size_tool_button_label;
269 GtkWidget *find_toolbar;
272 GtkWidget *font_dialog;
275 guint correct_scroll_idle;
276 guint scroll_drag_timeout_id;
280 TnyList *attachments;
285 TnyHeaderFlags priority_flags;
287 gboolean can_undo, can_redo;
288 gulong clipboard_change_handler_id;
289 gulong default_clipboard_change_handler_id;
290 gulong account_removed_handler_id;
291 guint clipboard_owner_idle;
292 gchar *clipboard_text;
301 GtkWidget *cc_button;
302 GtkWidget *bcc_button;
305 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
306 MODEST_TYPE_MSG_EDIT_WINDOW, \
307 ModestMsgEditWindowPrivate))
309 static GtkWindowClass *parent_class = NULL;
311 /* uncomment the following if you have defined any signals */
312 /* static guint signals[LAST_SIGNAL] = {0}; */
315 modest_msg_edit_window_get_type (void)
317 static GType my_type = 0;
319 static const GTypeInfo my_info = {
320 sizeof(ModestMsgEditWindowClass),
321 NULL, /* base init */
322 NULL, /* base finalize */
323 (GClassInitFunc) modest_msg_edit_window_class_init,
324 NULL, /* class finalize */
325 NULL, /* class data */
326 sizeof(ModestMsgEditWindow),
328 (GInstanceInitFunc) modest_msg_edit_window_init,
331 my_type = g_type_register_static (MODEST_TYPE_HILDON2_WINDOW,
332 "ModestMsgEditWindow",
340 save_state (ModestWindow *self)
342 modest_widget_memory_save (modest_runtime_get_conf(),
343 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
348 restore_settings (ModestMsgEditWindow *self)
350 ModestConf *conf = NULL;
352 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
354 conf = modest_runtime_get_conf ();
356 /* Dim at start clipboard actions */
357 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
358 gtk_action_set_sensitive (action, FALSE);
359 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
360 gtk_action_set_sensitive (action, FALSE);
361 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
362 gtk_action_set_sensitive (action, FALSE);
364 modest_widget_memory_restore (conf, G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
369 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
371 GObjectClass *gobject_class;
372 ModestWindowClass *modest_window_class;
373 gobject_class = (GObjectClass*) klass;
374 modest_window_class = (ModestWindowClass*) klass;
376 parent_class = g_type_class_peek_parent (klass);
377 gobject_class->finalize = modest_msg_edit_window_finalize;
379 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
380 modest_window_class->save_state_func = save_state;
381 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
383 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
387 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
389 ModestMsgEditWindowPrivate *priv;
390 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
392 priv->msg_body = NULL;
394 priv->from_field = NULL;
395 priv->to_field = NULL;
396 priv->cc_field = NULL;
397 priv->bcc_field = NULL;
398 priv->subject_field = NULL;
399 priv->attachments = TNY_LIST (tny_simple_list_new ());
400 priv->images = TNY_LIST (tny_simple_list_new ());
401 priv->images_size = 0;
402 priv->images_count = 0;
405 priv->cc_caption = NULL;
406 priv->bcc_caption = NULL;
407 priv->update_caption_visibility = FALSE;
409 priv->priority_flags = 0;
411 priv->find_toolbar = NULL;
412 priv->last_search = NULL;
414 priv->draft_msg = NULL;
415 priv->outbox_msg = NULL;
416 priv->msg_uid = NULL;
418 priv->can_undo = FALSE;
419 priv->can_redo = FALSE;
420 priv->clipboard_change_handler_id = 0;
421 priv->default_clipboard_change_handler_id = 0;
422 priv->account_removed_handler_id = 0;
423 priv->clipboard_owner_idle = 0;
424 priv->clipboard_text = NULL;
427 priv->scroll_drag_timeout_id = 0;
428 priv->correct_scroll_idle = 0;
429 priv->last_upper = 0.0;
431 priv->font_dialog = NULL;
432 priv->app_menu = NULL;
434 if (!is_wp_text_buffer_started) {
435 is_wp_text_buffer_started = TRUE;
436 wp_text_buffer_library_init ();
441 hildon_program_add_window (hildon_program_get_instance(),
447 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
449 static ModestPairList*
450 get_transports (void)
452 GSList *transports = NULL;
454 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
455 GSList *accounts = modest_account_mgr_account_names (account_mgr,
456 TRUE /* only enabled accounts. */);
458 GSList *cursor = accounts;
460 gchar *account_name = cursor->data;
461 gchar *from_string = NULL;
463 from_string = modest_account_mgr_get_from_string (account_mgr,
467 if (from_string && account_name) {
468 gchar *name = account_name;
469 ModestPair *pair = modest_pair_new ((gpointer) name,
470 (gpointer) from_string , TRUE);
471 transports = g_slist_prepend (transports, pair);
474 cursor = cursor->next;
476 g_slist_free (accounts); /* only free the accounts, not the elements,
477 * because they are used in the pairlist */
481 static void window_focus (GtkWindow *window,
485 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
489 scroll_drag_timeout (gpointer userdata)
491 ModestMsgEditWindow *win = (ModestMsgEditWindow *) userdata;
492 ModestMsgEditWindowPrivate *priv;
494 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(win);
496 correct_scroll_without_drag_check (win, TRUE);
498 priv->scroll_drag_timeout_id = 0;
504 correct_scroll_without_drag_check_idle (gpointer userdata)
506 ModestMsgEditWindow *w = (ModestMsgEditWindow *) userdata;
507 ModestMsgEditWindowPrivate *priv;
509 GdkRectangle rectangle;
514 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
516 if (!gtk_widget_is_focus (priv->msg_body))
519 insert = gtk_text_buffer_get_insert (priv->text_buffer);
520 gtk_text_buffer_get_iter_at_mark (priv->text_buffer, &iter, insert);
522 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &iter, &rectangle);
523 offset = priv->msg_body->allocation.y;
525 new_value = (offset + rectangle.y);
527 hildon_pannable_area_jump_to (HILDON_PANNABLE_AREA (priv->pannable), -1, new_value);
529 priv->correct_scroll_idle = 0;
534 correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused)
536 ModestMsgEditWindowPrivate *priv;
538 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
540 if (only_if_focused && !gtk_widget_is_focus (priv->msg_body))
543 if (priv->correct_scroll_idle > 0) {
547 priv->correct_scroll_idle = g_idle_add ((GSourceFunc) correct_scroll_without_drag_check_idle,
552 correct_scroll (ModestMsgEditWindow *w)
554 ModestMsgEditWindowPrivate *priv;
556 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
557 if (gtk_grab_get_current () == priv->msg_body) {
558 if (priv->scroll_drag_timeout_id == 0) {
559 priv->scroll_drag_timeout_id = g_timeout_add (500, (GSourceFunc) scroll_drag_timeout,
565 correct_scroll_without_drag_check (w, TRUE);
569 text_buffer_end_user_action (GtkTextBuffer *buffer,
570 ModestMsgEditWindow *userdata)
573 correct_scroll (userdata);
577 text_buffer_mark_set (GtkTextBuffer *buffer,
580 ModestMsgEditWindow *userdata)
582 gtk_text_buffer_begin_user_action (buffer);
583 gtk_text_buffer_end_user_action (buffer);
587 cut_clipboard_check (GtkTextView *text_view,
590 GtkTextBuffer *buffer;
592 buffer = gtk_text_view_get_buffer (text_view);
593 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
594 g_signal_stop_emission_by_name ((gpointer )text_view, "cut-clipboard");
599 copy_clipboard_check (GtkTextView *text_view,
602 GtkTextBuffer *buffer;
604 buffer = gtk_text_view_get_buffer (text_view);
605 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
606 g_signal_stop_emission_by_name ((gpointer )text_view, "copy-clipboard");
611 attachment_deleted (ModestAttachmentsView *attachments_view,
614 modest_msg_edit_window_remove_attachments (MODEST_MSG_EDIT_WINDOW (user_data),
619 connect_signals (ModestMsgEditWindow *obj)
621 ModestMsgEditWindowPrivate *priv;
623 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
625 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
626 G_CALLBACK (text_buffer_refresh_attributes), obj);
627 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
628 G_CALLBACK (text_buffer_can_undo), obj);
629 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
630 G_CALLBACK (text_buffer_can_redo), obj);
631 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
632 G_CALLBACK (body_changed), obj);
633 g_signal_connect (G_OBJECT (priv->text_buffer), "modified-changed",
634 G_CALLBACK (body_changed), obj);
635 g_signal_connect (G_OBJECT (priv->text_buffer), "end-user-action",
636 G_CALLBACK (text_buffer_end_user_action), obj);
637 g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
638 G_CALLBACK (text_buffer_mark_set), obj);
639 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
640 G_CALLBACK (text_buffer_apply_tag), obj);
641 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
642 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
643 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
644 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
645 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
646 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
648 g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
649 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
650 g_signal_connect (G_OBJECT (priv->from_field), "value-changed",
651 G_CALLBACK (from_field_changed), obj);
653 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
654 G_CALLBACK (msg_body_focus), obj);
655 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
656 G_CALLBACK (msg_body_focus), obj);
657 g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
658 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
659 "changed", G_CALLBACK (recpt_field_changed), obj);
660 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
661 "changed", G_CALLBACK (recpt_field_changed), obj);
662 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
663 "changed", G_CALLBACK (recpt_field_changed), obj);
664 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
665 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
666 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
668 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
669 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
671 priv->clipboard_change_handler_id =
672 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
673 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
674 priv->default_clipboard_change_handler_id =
675 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
676 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
678 g_signal_connect (G_OBJECT (priv->msg_body), "cut-clipboard", G_CALLBACK (cut_clipboard_check), NULL);
679 g_signal_connect (G_OBJECT (priv->msg_body), "copy-clipboard", G_CALLBACK (copy_clipboard_check), NULL);
680 g_signal_connect (G_OBJECT (priv->attachments_view), "delete", G_CALLBACK (attachment_deleted), obj);
684 init_wp_text_view_style ()
686 static gboolean initialized = FALSE;
689 gtk_rc_parse_string ("class \"WPTextView\" style \"fremantle-textview\"");
695 init_window (ModestMsgEditWindow *obj)
697 GtkWidget *to_caption, *subject_caption;
698 GtkWidget *main_vbox;
699 GtkWidget *add_attachment_align;
700 ModestMsgEditWindowPrivate *priv;
701 GtkActionGroup *action_group;
702 ModestWindowPrivate *parent_priv;
703 GdkPixbuf *window_icon = NULL;
704 GError *error = NULL;
706 GtkSizeGroup *title_size_group;
707 GtkSizeGroup *value_size_group;
708 GtkWidget *attachment_icon;
709 GtkWidget *window_box;
710 #if (GTK_MINOR_VERSION >= 10)
711 GdkAtom deserialize_type;
714 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
715 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
717 parent_priv->ui_manager = gtk_ui_manager_new();
718 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
719 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
721 /* Add common actions */
722 gtk_action_group_add_actions (action_group,
723 modest_msg_edit_action_entries,
724 G_N_ELEMENTS (modest_msg_edit_action_entries),
726 gtk_action_group_add_actions (action_group,
727 hildon2_msg_edit_action_entries,
728 G_N_ELEMENTS (hildon2_msg_edit_action_entries),
730 gtk_action_group_add_toggle_actions (action_group,
731 modest_msg_edit_toggle_action_entries,
732 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
734 gtk_action_group_add_radio_actions (action_group,
735 modest_msg_edit_alignment_radio_action_entries,
736 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
738 G_CALLBACK (modest_ui_actions_on_change_justify),
740 gtk_action_group_add_radio_actions (action_group,
741 modest_msg_edit_priority_action_entries,
742 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
744 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
746 gtk_action_group_add_radio_actions (action_group,
747 modest_msg_edit_file_format_action_entries,
748 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
749 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
750 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
752 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
753 g_object_unref (action_group);
755 /* Load the UI definition */
756 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
759 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
760 g_clear_error (&error);
763 /* Add accelerators */
764 gtk_window_add_accel_group (GTK_WINDOW (obj),
765 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
767 parent_priv->menubar = NULL;
769 title_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
770 value_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
772 /* Note: This ModestPairList* must exist for as long as the picker
773 * that uses it, because the ModestSelectorPicker uses the ID opaquely,
774 * so it can't know how to manage its memory. */
775 priv->from_field = modest_selector_picker_new (MODEST_EDITABLE_SIZE,
776 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL,
778 modest_maemo_utils_set_hbutton_layout (title_size_group, value_size_group,
779 _("mail_va_from"), priv->from_field);
781 priv->to_field = modest_recpt_editor_new ();
782 priv->cc_field = modest_recpt_editor_new ();
783 priv->bcc_field = modest_recpt_editor_new ();
784 priv->subject_box = gtk_hbox_new (FALSE, MODEST_MARGIN_NONE);
785 priv->priority_icon = gtk_image_new ();
786 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->priority_icon, FALSE, FALSE, 0);
787 priv->subject_field = hildon_entry_new (MODEST_EDITABLE_SIZE);
788 gtk_entry_set_max_length (GTK_ENTRY (priv->subject_field) ,SUBJECT_MAX_LENGTH);
789 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
790 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
791 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
792 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->subject_field, TRUE, TRUE, 0);
793 priv->add_attachment_button = hildon_button_new (MODEST_EDITABLE_SIZE, HILDON_BUTTON_ARRANGEMENT_VERTICAL);
794 gtk_widget_set_size_request (priv->add_attachment_button, ATTACHMENT_BUTTON_WIDTH, -1);
795 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
796 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
797 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, HILDON_ICON_SIZE_FINGER);
798 hildon_button_set_image (HILDON_BUTTON (priv->add_attachment_button), attachment_icon);
799 add_attachment_align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
800 gtk_alignment_set_padding (GTK_ALIGNMENT (add_attachment_align), 0, 0, MODEST_MARGIN_DEFAULT, 0);
801 gtk_container_add (GTK_CONTAINER (add_attachment_align), priv->add_attachment_button);
802 gtk_box_pack_start (GTK_BOX (priv->subject_box), add_attachment_align, FALSE, FALSE, 0);
803 priv->attachments_view = modest_attachments_view_new (NULL);
804 modest_attachments_view_set_style (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
805 MODEST_ATTACHMENTS_VIEW_STYLE_NO_FOCUS);
807 priv->header_box = gtk_vbox_new (FALSE, 0);
809 to_caption = modest_maemo_utils_create_captioned_with_size_type
810 (title_size_group, value_size_group,
811 _("mail_va_to"), FALSE, priv->to_field,
812 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
813 priv->cc_caption = modest_maemo_utils_create_captioned_with_size_type
814 (title_size_group, value_size_group,
815 _("mail_va_cc"), FALSE, priv->cc_field,
816 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
817 priv->bcc_caption = modest_maemo_utils_create_captioned_with_size_type
818 (title_size_group, value_size_group,
819 _("mail_va_hotfix1"), FALSE, priv->bcc_field,
820 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
821 subject_caption = modest_maemo_utils_create_captioned (title_size_group, value_size_group,
822 _("mail_va_subject"), FALSE, priv->subject_box);
823 priv->attachments_caption = modest_maemo_utils_create_captioned_with_size_type (title_size_group, value_size_group,
824 _("mail_va_attachment"),
826 priv->attachments_view,
827 HILDON_SIZE_AUTO_WIDTH |
828 HILDON_SIZE_AUTO_HEIGHT);
829 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), value_size_group); */
830 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), value_size_group); */
831 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), value_size_group); */
832 g_object_unref (title_size_group);
833 g_object_unref (value_size_group);
835 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->from_field, FALSE, FALSE, 0);
836 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
837 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
838 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
839 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
840 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
841 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
843 init_wp_text_view_style ();
845 priv->msg_body = wp_text_view_new ();
848 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
849 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
850 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
851 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
852 #if (GTK_MINOR_VERSION >= 10)
853 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
854 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
856 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
857 deserialize_type, TRUE);
859 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
861 priv->find_toolbar = hildon_find_toolbar_new (NULL);
862 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
864 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
866 priv->pannable = hildon_pannable_area_new ();
868 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
870 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
871 priv->frame = gtk_frame_new (NULL);
872 gtk_box_pack_start (GTK_BOX(main_vbox), priv->frame, TRUE, TRUE, 0);
874 hildon_pannable_area_add_with_viewport (HILDON_PANNABLE_AREA (priv->pannable), main_vbox);
875 gtk_container_set_focus_vadjustment (GTK_CONTAINER (main_vbox),
876 hildon_pannable_area_get_vadjustment (HILDON_PANNABLE_AREA (priv->pannable)));
877 gtk_widget_show_all (GTK_WIDGET(priv->pannable));
879 window_box = gtk_vbox_new (FALSE, 0);
880 gtk_container_add (GTK_CONTAINER(obj), window_box);
882 gtk_box_pack_start (GTK_BOX (window_box), priv->pannable, TRUE, TRUE, 0);
884 gtk_container_add (GTK_CONTAINER (priv->frame), priv->msg_body);
886 /* Set window icon */
887 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
889 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
890 g_object_unref (window_icon);
895 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
897 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
899 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
900 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
901 priv->clipboard_change_handler_id))
902 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
903 priv->clipboard_change_handler_id);
904 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
905 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
906 priv->default_clipboard_change_handler_id))
907 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
908 priv->default_clipboard_change_handler_id);
910 if (priv->account_removed_handler_id &&
911 g_signal_handler_is_connected (modest_runtime_get_account_store (),
912 priv->account_removed_handler_id))
913 g_signal_handler_disconnect(modest_runtime_get_account_store (),
914 priv->account_removed_handler_id);
918 modest_msg_edit_window_finalize (GObject *obj)
920 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
922 /* Sanity check: shouldn't be needed, the window mgr should
923 call this function before */
924 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
926 if (priv->font_dialog != NULL) {
927 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
930 if (priv->clipboard_text != NULL) {
931 g_free (priv->clipboard_text);
932 priv->clipboard_text = NULL;
935 if (priv->draft_msg != NULL) {
936 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
937 if (TNY_IS_HEADER (header)) {
938 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
939 modest_window_mgr_unregister_header (mgr, header);
941 g_object_unref (priv->draft_msg);
942 priv->draft_msg = NULL;
944 if (priv->outbox_msg != NULL) {
945 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
946 if (TNY_IS_HEADER (header)) {
947 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
948 modest_window_mgr_unregister_header (mgr, header);
950 g_object_unref (priv->outbox_msg);
951 priv->outbox_msg = NULL;
953 if (priv->correct_scroll_idle > 0) {
954 g_source_remove (priv->correct_scroll_idle);
955 priv->correct_scroll_idle = 0;
957 if (priv->scroll_drag_timeout_id > 0) {
958 g_source_remove (priv->scroll_drag_timeout_id);
959 priv->scroll_drag_timeout_id = 0;
961 if (priv->clipboard_owner_idle > 0) {
962 g_source_remove (priv->clipboard_owner_idle);
963 priv->clipboard_owner_idle = 0;
965 if (priv->original_account_name)
966 g_free (priv->original_account_name);
967 g_free (priv->msg_uid);
968 g_free (priv->last_search);
969 g_slist_free (priv->font_items_group);
970 g_slist_free (priv->size_items_group);
971 g_object_unref (priv->attachments);
972 g_object_unref (priv->images);
974 /* This had to stay alive for as long as the picker that used it: */
975 modest_pair_list_free (priv->from_field_protos);
977 G_OBJECT_CLASS(parent_class)->finalize (obj);
981 pixbuf_from_stream (TnyStream *stream, const gchar *mime_type, guint64 *stream_size)
983 GdkPixbufLoader *loader;
989 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
991 if (loader == NULL) {
997 tny_stream_reset (TNY_STREAM (stream));
998 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
999 GError *error = NULL;
1000 unsigned char read_buffer[128];
1002 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
1004 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
1006 g_error_free (error);
1011 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1013 g_object_ref (pixbuf);
1014 gdk_pixbuf_loader_close (loader, NULL);
1015 g_object_unref (loader);
1020 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1021 GdkPixbuf *new_pixbuf;
1023 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1024 gdk_pixbuf_get_width (pixbuf);
1025 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1026 g_object_unref (pixbuf);
1027 pixbuf = new_pixbuf;
1031 *stream_size = size;
1037 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1039 ModestMsgEditWindowPrivate *priv;
1042 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1044 for (iter = tny_list_create_iterator (attachments);
1045 !tny_iterator_is_done (iter);
1046 tny_iterator_next (iter)) {
1047 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1048 const gchar *cid = tny_mime_part_get_content_id (part);
1049 const gchar *mime_type = tny_mime_part_get_content_type (part);
1050 if ((cid != NULL)&&(mime_type != NULL)) {
1051 guint64 stream_size;
1052 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1053 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
1056 g_object_unref (stream);
1058 if (pixbuf != NULL) {
1059 priv->images_count ++;
1060 priv->images_size += stream_size;
1061 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1062 g_object_unref (pixbuf);
1065 g_object_unref (part);
1067 g_object_unref (iter);
1071 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1073 TnyMimePart *parent = NULL;
1074 const gchar *content_type = NULL;
1075 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1077 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1079 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1080 parent = g_object_ref (msg);
1081 } else if (content_type && !g_strcasecmp (content_type, "multipart/mixed")) {
1082 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1085 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1086 iter = tny_list_create_iterator (parts);
1087 while (!tny_iterator_is_done (iter)) {
1089 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1090 content_type = tny_mime_part_get_content_type (part);
1091 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1095 g_object_unref (part);
1097 tny_iterator_next (iter);
1099 g_object_unref (iter);
1100 g_object_unref (parts);
1103 if (parent != NULL) {
1104 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1107 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1108 iter = tny_list_create_iterator (parts);
1109 while (!tny_iterator_is_done (iter)) {
1111 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1112 content_type = tny_mime_part_get_content_type (part);
1113 if (content_type && g_str_has_prefix (content_type, "image/")) {
1114 tny_list_prepend (priv->images, (GObject *) part);
1116 g_object_unref (part);
1117 tny_iterator_next (iter);
1119 g_object_unref (iter);
1120 g_object_unref (parts);
1121 g_object_unref (parent);
1126 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1129 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1131 for (iter = tny_list_create_iterator (attachments) ;
1132 !tny_iterator_is_done (iter);
1133 tny_iterator_next (iter)) {
1134 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1135 const gchar *cid = tny_mime_part_get_content_id (part);
1137 char *invalid = NULL;
1138 gint int_cid = strtol (cid, &invalid, 10);
1139 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1140 priv->next_cid = int_cid + 1;
1143 g_object_unref (part);
1145 g_object_unref (iter);
1149 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1152 gchar *to, *cc, *bcc, *subject;
1154 ModestMsgEditWindowPrivate *priv;
1155 ModestWindowPrivate *parent_priv;
1157 TnyHeaderFlags priority_flags;
1158 TnyFolder *msg_folder;
1159 gboolean is_html = FALSE;
1160 gboolean field_view_set;
1162 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1163 g_return_if_fail (TNY_IS_MSG (msg));
1165 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1166 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1168 header = tny_msg_get_header (msg);
1169 to = tny_header_dup_to (header);
1170 cc = tny_header_dup_cc (header);
1171 bcc = tny_header_dup_bcc (header);
1172 subject = tny_header_dup_subject (header);
1173 priority_flags = tny_header_get_priority (header);
1176 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
1178 field_view_set = TRUE;
1180 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
1181 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1182 gtk_widget_show (priv->cc_caption);
1183 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1184 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1185 gtk_widget_hide (priv->cc_caption);
1186 field_view_set = FALSE;
1188 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button), field_view_set);
1190 field_view_set = TRUE;
1192 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
1193 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1194 gtk_widget_show (priv->bcc_caption);
1195 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1196 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1197 gtk_widget_hide (priv->bcc_caption);
1198 field_view_set = FALSE;
1200 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button), field_view_set);
1204 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1205 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1208 update_window_title (self);
1210 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1211 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1213 if ((body == NULL)||(body[0] == '\0')) {
1215 body = modest_text_utils_convert_to_html ("");
1218 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1219 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1222 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1225 /* Add attachments to the view */
1226 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1227 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1228 if (tny_list_get_length (priv->attachments) == 0) {
1229 gtk_widget_hide (priv->attachments_caption);
1231 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1232 gtk_widget_show_all (priv->attachments_caption);
1234 get_related_images (self, msg);
1235 update_next_cid (self, priv->attachments);
1236 update_next_cid (self, priv->images);
1237 replace_with_images (self, priv->images);
1239 if (preserve_is_rich && !is_html) {
1240 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1241 /* Get the default format required from configuration */
1242 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1243 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1246 /* Set the default focus depending on having already a To: field or not */
1247 if ((!to)||(*to == '\0')) {
1248 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1250 gtk_widget_grab_focus (priv->msg_body);
1253 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1255 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1256 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1258 modest_msg_edit_window_set_modified (self, FALSE);
1260 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1261 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1262 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1263 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1265 if (priv->msg_uid) {
1266 g_free (priv->msg_uid);
1267 priv->msg_uid = NULL;
1270 /* we should set a reference to the incoming message if it is a draft */
1271 msg_folder = tny_msg_get_folder (msg);
1273 if (modest_tny_folder_is_local_folder (msg_folder)) {
1274 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1275 if (type == TNY_FOLDER_TYPE_INVALID)
1276 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1278 if (type == TNY_FOLDER_TYPE_DRAFTS)
1279 priv->draft_msg = g_object_ref(msg);
1280 if (type == TNY_FOLDER_TYPE_OUTBOX)
1281 priv->outbox_msg = g_object_ref(msg);
1282 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1284 g_object_unref (msg_folder);
1294 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
1297 GList *item_children, *node;
1298 GtkWidget *bin_child;
1300 bin_child = gtk_bin_get_child (GTK_BIN(item));
1302 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
1304 for (node = item_children; node != NULL; node = g_list_next (node)) {
1305 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
1306 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
1309 g_list_free (item_children);
1313 menu_tool_button_dont_expand (GtkMenuToolButton *item)
1316 GList *item_children, *node;
1318 box = gtk_bin_get_child (GTK_BIN (item));
1319 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
1320 item_children = gtk_container_get_children (GTK_CONTAINER (box));
1322 for (node = item_children; node != NULL; node = g_list_next (node)) {
1323 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
1324 if (GTK_IS_TOGGLE_BUTTON (node->data))
1325 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
1326 else if (GTK_IS_BUTTON (node->data))
1327 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
1329 g_list_free (item_children);
1334 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1336 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1337 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1338 GtkWidget *placeholder;
1339 GtkWidget *tool_item;
1344 GtkWidget *sizes_menu;
1345 GtkWidget *fonts_menu;
1346 GSList *radio_group = NULL;
1347 GSList *node = NULL;
1351 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1352 gtk_toolbar_set_show_arrow (GTK_TOOLBAR (parent_priv->toolbar), FALSE);
1353 gtk_toolbar_set_icon_size (GTK_TOOLBAR (parent_priv->toolbar), HILDON_ICON_SIZE_FINGER);
1354 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1356 /* Font color placeholder */
1357 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1358 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1361 priv->font_color_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1362 priv->font_color_button = hildon_color_button_new ();
1363 gtk_widget_set_size_request (priv->font_color_button, -1, 48);
1364 GTK_WIDGET_UNSET_FLAGS (priv->font_color_toolitem, GTK_CAN_FOCUS);
1365 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1366 gtk_container_add (GTK_CONTAINER (priv->font_color_toolitem), priv->font_color_button);
1367 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1368 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1369 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->font_color_toolitem), insert_index);
1370 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1372 G_CALLBACK (modest_msg_edit_window_color_button_change),
1375 /* Font size and face placeholder */
1376 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1377 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1379 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1380 priv->size_tool_button_label = gtk_label_new (NULL);
1381 hildon_helper_set_logical_color (GTK_WIDGET (priv->size_tool_button_label), GTK_RC_TEXT,
1382 GTK_STATE_INSENSITIVE, "SecondaryTextColor");
1383 hildon_helper_set_logical_color (GTK_WIDGET (priv->size_tool_button_label), GTK_RC_FG,
1384 GTK_STATE_INSENSITIVE, "SecondaryTextColor");
1385 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1386 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1387 size_text,"</span>", NULL);
1388 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1390 hildon_helper_set_logical_font (priv->size_tool_button_label, "LargeSystemFont");
1391 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
1392 sizes_menu = gtk_menu_new ();
1393 priv->size_items_group = NULL;
1395 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1396 GtkWidget *size_menu_item;
1398 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1399 size_menu_item = gtk_radio_menu_item_new_with_label (radio_group, size_text);
1400 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (size_menu_item));
1401 gtk_menu_shell_append (GTK_MENU_SHELL (sizes_menu), size_menu_item);
1402 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (size_menu_item), (wp_font_size[size_index] == 12));
1403 gtk_widget_show (size_menu_item);
1405 priv->size_items_group = g_slist_prepend (priv->size_items_group, size_menu_item);
1409 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1410 GtkWidget *item = (GtkWidget *) node->data;
1411 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_size_change),
1415 priv->size_items_group = g_slist_reverse (priv->size_items_group);
1416 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), sizes_menu);
1417 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1418 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1419 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), FALSE);
1420 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), FALSE);
1421 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1422 priv->font_size_toolitem = tool_item;
1425 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1426 priv->font_tool_button_label = gtk_label_new (NULL);
1427 hildon_helper_set_logical_color (GTK_WIDGET (priv->font_tool_button_label), GTK_RC_TEXT,
1428 GTK_STATE_INSENSITIVE, "SecondaryTextColor");
1429 hildon_helper_set_logical_color (GTK_WIDGET (priv->font_tool_button_label), GTK_RC_FG,
1430 GTK_STATE_INSENSITIVE, "SecondaryTextColor");
1431 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1432 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1434 hildon_helper_set_logical_font (priv->font_tool_button_label, "LargeSystemFont");
1435 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
1436 fonts_menu = gtk_menu_new ();
1437 priv->font_items_group = NULL;
1439 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1440 GtkWidget *font_menu_item;
1441 GtkWidget *child_label;
1443 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
1444 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
1445 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
1446 wp_get_font_name (font_index), "</span>", NULL);
1447 gtk_label_set_markup (GTK_LABEL (child_label), markup);
1450 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
1451 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
1452 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
1453 gtk_widget_show (font_menu_item);
1455 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
1458 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1459 GtkWidget *item = (GtkWidget *) node->data;
1460 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
1463 priv->font_items_group = g_slist_reverse (priv->font_items_group);
1464 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
1465 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1466 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1467 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), FALSE);
1468 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), FALSE);
1469 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1470 priv->font_face_toolitem = tool_item;
1472 /* Set expand and homogeneous for remaining items */
1473 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
1474 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1475 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1476 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1477 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1478 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1479 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1480 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1481 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1483 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1484 will not show the tool items added to the placeholders) */
1485 gtk_widget_show_all (parent_priv->toolbar);
1487 /* Set the no show all *after* showing all items. We do not
1488 want the toolbar to be shown with a show all because it
1489 could go agains the gconf setting regarding showing or not
1490 the toolbar of the editor window */
1491 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1497 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, gboolean preserve_is_rich)
1500 ModestWindowPrivate *parent_priv;
1501 ModestMsgEditWindowPrivate *priv;
1502 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1503 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1504 ModestWindowMgr *mgr = NULL;
1506 g_return_val_if_fail (msg, NULL);
1507 g_return_val_if_fail (account_name, NULL);
1509 mgr = modest_runtime_get_window_mgr ();
1511 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1513 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1514 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1516 /* Menubar. Update the state of some toggles */
1517 priv->from_field_protos = get_transports ();
1518 modest_selector_picker_set_pair_list (MODEST_SELECTOR_PICKER (priv->from_field), priv->from_field_protos);
1519 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1520 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1521 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1523 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1524 hildon_touch_selector_get_current_text
1525 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1526 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1527 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1530 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1532 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1534 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1536 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1538 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1539 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1540 /* Add common dimming rules */
1541 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1542 modest_msg_edit_window_toolbar_dimming_entries,
1543 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1544 MODEST_WINDOW (obj));
1545 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_toolitem,
1546 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1547 MODEST_WINDOW (obj));
1548 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1549 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1550 MODEST_WINDOW (obj));
1551 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1552 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1553 MODEST_WINDOW (obj));
1554 /* Insert dimming rules group for this window */
1555 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1556 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1558 /* Setup app menu */
1559 setup_menu (MODEST_MSG_EDIT_WINDOW (obj));
1561 /* Checks the dimming rules */
1562 g_object_unref (toolbar_rules_group);
1563 g_object_unref (clipboard_rules_group);
1564 gtk_widget_hide (priv->priority_icon);
1565 gtk_widget_queue_resize (priv->subject_box);
1566 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1568 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1570 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1571 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1572 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1573 priv->update_caption_visibility = TRUE;
1575 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1577 /* Track account-removed signal, this window should be closed
1578 in the case we're creating a mail associated to the account
1580 priv->account_removed_handler_id =
1581 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1583 G_CALLBACK(on_account_removed),
1586 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1588 return (ModestWindow*) obj;
1592 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1594 GString **string_buffer = (GString **) user_data;
1596 *string_buffer = g_string_append (*string_buffer, buffer);
1602 * @result: A new string which should be freed with g_free().
1605 get_formatted_data (ModestMsgEditWindow *edit_window)
1607 ModestMsgEditWindowPrivate *priv;
1608 GString *string_buffer = g_string_new ("");
1610 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1612 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1614 modest_text_utils_hyperlinkify (string_buffer);
1616 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1618 return g_string_free (string_buffer, FALSE);
1623 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1626 const gchar *account_name;
1627 ModestMsgEditWindowPrivate *priv;
1628 TnyIterator *att_iter;
1630 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1632 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1634 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1635 g_return_val_if_fail (account_name, NULL);
1638 /* don't free these (except from) */
1639 data = g_slice_new0 (MsgData);
1640 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1642 data->account_name = g_strdup (account_name);
1643 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1644 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1645 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1646 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1647 if (priv->draft_msg) {
1648 data->draft_msg = g_object_ref (priv->draft_msg);
1649 } else if (priv->outbox_msg) {
1650 data->draft_msg = g_object_ref (priv->outbox_msg);
1652 data->draft_msg = NULL;
1655 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1657 gtk_text_buffer_get_bounds (buf, &b, &e);
1658 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1660 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1661 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1663 data->html_body = NULL;
1665 /* deep-copy the data */
1666 att_iter = tny_list_create_iterator (priv->attachments);
1667 data->attachments = NULL;
1668 while (!tny_iterator_is_done (att_iter)) {
1669 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1670 if (!(TNY_IS_MIME_PART(part))) {
1671 g_warning ("strange data in attachment list");
1672 g_object_unref (part);
1673 tny_iterator_next (att_iter);
1676 data->attachments = g_list_append (data->attachments,
1678 tny_iterator_next (att_iter);
1680 g_object_unref (att_iter);
1682 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1683 att_iter = tny_list_create_iterator (priv->images);
1684 data->images = NULL;
1685 while (!tny_iterator_is_done (att_iter)) {
1686 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1688 if (!(TNY_IS_MIME_PART(part))) {
1689 g_warning ("strange data in attachment list");
1690 g_object_unref (part);
1691 tny_iterator_next (att_iter);
1694 cid = tny_mime_part_get_content_id (part);
1696 gchar *image_tag_id;
1697 GtkTextTag *image_tag;
1699 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1700 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1701 g_free (image_tag_id);
1703 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1705 ((gtk_text_iter_has_tag (&iter, image_tag))||
1706 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1707 data->images = g_list_append (data->images,
1708 g_object_ref (part));
1710 g_object_unref (part);
1711 tny_iterator_next (att_iter);
1713 g_object_unref (att_iter);
1715 data->priority_flags = priv->priority_flags;
1722 unref_gobject (GObject *obj, gpointer data)
1724 if (!G_IS_OBJECT(obj))
1726 g_object_unref (obj);
1730 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1733 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1741 g_free (data->from);
1742 g_free (data->subject);
1743 g_free (data->plain_body);
1744 g_free (data->html_body);
1745 g_free (data->account_name);
1747 if (data->draft_msg != NULL) {
1748 g_object_unref (data->draft_msg);
1749 data->draft_msg = NULL;
1752 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1753 g_list_free (data->attachments);
1754 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1755 g_list_free (data->images);
1757 g_slice_free (MsgData, data);
1761 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1763 guint64 *parts_size)
1765 ModestMsgEditWindowPrivate *priv;
1767 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1769 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1771 /* TODO: add images */
1772 *parts_size += priv->images_size;
1773 *parts_count += priv->images_count;
1778 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1781 ModestMsgEditWindowPrivate *priv = NULL;
1782 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1784 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1786 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1788 return MODEST_MSG_EDIT_FORMAT_HTML;
1790 return MODEST_MSG_EDIT_FORMAT_TEXT;
1794 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1795 ModestMsgEditFormat format)
1797 ModestMsgEditWindowPrivate *priv;
1799 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1800 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1803 case MODEST_MSG_EDIT_FORMAT_HTML:
1804 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1806 case MODEST_MSG_EDIT_FORMAT_TEXT:
1807 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1810 g_return_if_reached ();
1814 ModestMsgEditFormatState *
1815 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1817 ModestMsgEditFormatState *format_state = NULL;
1818 ModestMsgEditWindowPrivate *priv;
1819 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1821 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1822 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1824 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1826 format_state = g_new0 (ModestMsgEditFormatState, 1);
1827 format_state->bold = buffer_format->bold&0x1;
1828 format_state->italics = buffer_format->italic&0x1;
1829 format_state->bullet = buffer_format->bullet&0x1;
1830 format_state->color = buffer_format->color;
1831 format_state->font_size = buffer_format->font_size;
1832 format_state->font_family = wp_get_font_name (buffer_format->font);
1833 format_state->justification = buffer_format->justification;
1834 g_free (buffer_format);
1836 return format_state;
1841 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1842 const ModestMsgEditFormatState *format_state)
1844 ModestMsgEditWindowPrivate *priv;
1845 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1846 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1847 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1848 g_return_if_fail (format_state != NULL);
1850 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1851 gtk_widget_grab_focus (priv->msg_body);
1852 buffer_format->bold = (format_state->bold != FALSE);
1853 buffer_format->italic = (format_state->italics != FALSE);
1854 buffer_format->color = format_state->color;
1855 buffer_format->font_size = format_state->font_size;
1856 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1857 buffer_format->justification = format_state->justification;
1858 buffer_format->bullet = format_state->bullet;
1860 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1862 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1863 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1864 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1865 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1866 buffer_format->cs.font = (buffer_format->font != current_format->font);
1867 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1868 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1870 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1871 if (buffer_format->cs.bold) {
1872 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
1873 GINT_TO_POINTER (buffer_format->bold&0x1));
1875 if (buffer_format->cs.italic) {
1876 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
1877 GINT_TO_POINTER (buffer_format->italic&0x1));
1879 if (buffer_format->cs.color) {
1880 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1881 GINT_TO_POINTER (&(buffer_format->color)));
1883 if (buffer_format->cs.font_size) {
1884 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1885 GINT_TO_POINTER (buffer_format->font_size));
1887 if (buffer_format->cs.justification) {
1888 switch (buffer_format->justification) {
1889 case GTK_JUSTIFY_LEFT:
1890 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
1891 GINT_TO_POINTER(TRUE));
1893 case GTK_JUSTIFY_CENTER:
1894 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
1895 GINT_TO_POINTER(TRUE));
1897 case GTK_JUSTIFY_RIGHT:
1898 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
1899 GINT_TO_POINTER(TRUE));
1906 if (buffer_format->cs.font) {
1907 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1908 GINT_TO_POINTER (buffer_format->font));
1910 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1911 if (buffer_format->cs.bullet) {
1912 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
1913 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
1915 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1917 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
1919 g_free (buffer_format);
1920 g_free (current_format);
1922 /* Check dimming rules */
1923 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1924 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1928 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1930 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1932 ModestWindowPrivate *parent_priv;
1933 ModestMsgEditWindowPrivate *priv;
1934 GtkWidget *new_size_menuitem;
1935 GtkWidget *new_font_menuitem;
1937 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1938 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1940 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1941 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu");
1942 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1943 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1945 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatPlainTextMenu");
1946 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1947 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1950 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1952 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1953 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1955 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1956 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1958 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
1959 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
1962 switch (buffer_format->justification)
1964 case GTK_JUSTIFY_LEFT:
1965 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
1967 case GTK_JUSTIFY_CENTER:
1968 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
1970 case GTK_JUSTIFY_RIGHT:
1971 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
1978 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
1980 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1981 G_CALLBACK (modest_msg_edit_window_color_button_change),
1983 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1984 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1985 G_CALLBACK (modest_msg_edit_window_color_button_change),
1988 new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group,
1989 buffer_format->font_size))->data);
1990 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1994 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1995 markup = g_strconcat ("<span font_family='Sans'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1996 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1998 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1999 G_CALLBACK (modest_msg_edit_window_size_change),
2001 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
2002 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
2003 G_CALLBACK (modest_msg_edit_window_size_change),
2007 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
2008 buffer_format->font))->data);
2009 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
2013 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
2014 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2015 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2017 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
2018 G_CALLBACK (modest_msg_edit_window_font_change),
2020 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
2021 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
2022 G_CALLBACK (modest_msg_edit_window_font_change),
2026 g_free (buffer_format);
2030 #ifdef MODEST_HILDON_VERSION_0
2032 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2035 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2036 ModestMsgEditWindowPrivate *priv;
2037 GtkWidget *dialog = NULL;
2039 GdkColor *new_color = NULL;
2041 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2042 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2044 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2045 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
2046 g_free (buffer_format);
2048 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2049 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2050 if (new_color != NULL) {
2051 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2052 (gpointer) new_color);
2055 gtk_widget_destroy (dialog);
2060 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2063 ModestMsgEditWindowPrivate *priv;
2064 GtkWidget *dialog = NULL;
2066 GdkColor *old_color = NULL;
2067 const GdkColor *new_color = NULL;
2069 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2070 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2072 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2073 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2075 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2076 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2077 if (new_color != NULL)
2078 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2080 gtk_widget_destroy (dialog);
2086 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2089 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2090 ModestMsgEditWindowPrivate *priv;
2091 GtkWidget *dialog = NULL;
2093 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2094 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2096 dialog = hildon_color_chooser_new ();
2097 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2098 g_free (buffer_format);
2100 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2102 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2103 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2106 gtk_widget_destroy (dialog);
2111 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2114 ModestMsgEditWindowPrivate *priv;
2115 GtkWidget *dialog = NULL;
2116 GdkColor *old_color = NULL;
2118 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2119 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2121 dialog = hildon_color_chooser_new ();
2122 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2124 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2126 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2127 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2129 gtk_widget_destroy (dialog);
2132 #endif /*!MODEST_HILDON_VERSION_0*/
2137 create_stream_for_uri (const gchar* uri)
2142 TnyStream *result = NULL;
2144 GnomeVFSHandle *handle = NULL;
2145 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2146 if (test == GNOME_VFS_OK) {
2147 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2148 /* Streams over OBEX (Bluetooth) are not seekable but
2149 * we expect them to be (we might need to read them
2150 * several times). So if this is a Bluetooth URI just
2151 * read the whole file into memory (this is not a fast
2152 * protocol so we can assume that these files are not
2153 * going to be very big) */
2154 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2155 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2156 TnyStream *memstream = tny_camel_mem_stream_new ();
2157 tny_stream_write_to_stream (vfssstream, memstream);
2158 g_object_unref (vfssstream);
2161 result = vfssstream;
2169 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2172 ModestMsgEditWindowPrivate *priv;
2173 GtkWidget *dialog = NULL;
2175 GSList *uris = NULL;
2176 GSList *uri_node = NULL;
2178 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2180 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2181 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2182 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2184 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2186 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2187 GTK_WINDOW (dialog), GTK_WINDOW (window));
2189 response = gtk_dialog_run (GTK_DIALOG (dialog));
2191 case GTK_RESPONSE_OK:
2192 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2197 gtk_widget_destroy (dialog);
2199 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2201 GnomeVFSHandle *handle = NULL;
2202 GnomeVFSResult result;
2203 GtkTextIter position;
2204 GtkTextMark *insert_mark;
2206 uri = (const gchar *) uri_node->data;
2207 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2208 if (result == GNOME_VFS_OK) {
2210 GnomeVFSFileInfo *info;
2211 gchar *filename, *basename, *escaped_filename;
2212 TnyMimePart *mime_part;
2214 const gchar *mime_type = NULL;
2215 GnomeVFSURI *vfs_uri;
2216 guint64 stream_size;
2218 gnome_vfs_close (handle);
2219 vfs_uri = gnome_vfs_uri_new (uri);
2221 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2222 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2223 g_free (escaped_filename);
2224 gnome_vfs_uri_unref (vfs_uri);
2225 info = gnome_vfs_file_info_new ();
2227 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2228 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2230 mime_type = gnome_vfs_file_info_get_mime_type (info);
2232 mime_part = tny_platform_factory_new_mime_part
2233 (modest_runtime_get_platform_factory ());
2235 TnyStream *stream = create_stream_for_uri (uri);
2237 if (stream == NULL) {
2239 modest_platform_information_banner (NULL, NULL,
2240 _FM("sfil_ib_opening_not_allowed"));
2242 g_object_unref (mime_part);
2243 gnome_vfs_file_info_unref (info);
2247 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2249 content_id = g_strdup_printf ("%d", priv->next_cid);
2250 tny_mime_part_set_content_id (mime_part, content_id);
2251 g_free (content_id);
2254 basename = g_path_get_basename (filename);
2255 tny_mime_part_set_filename (mime_part, basename);
2258 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
2260 if (pixbuf != NULL) {
2261 priv->images_size += stream_size;
2262 priv->images_count ++;
2263 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2264 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2265 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
2266 g_object_unref (pixbuf);
2269 tny_list_prepend (priv->images, (GObject *) mime_part);
2270 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2272 g_object_unref (mime_part);
2273 gnome_vfs_file_info_unref (info);
2282 on_attach_file_response (GtkDialog *dialog,
2286 GSList *uris = NULL;
2288 GnomeVFSFileSize total_size, allowed_size;
2289 ModestMsgEditWindow *window;
2290 ModestMsgEditWindowPrivate *priv;
2295 case GTK_RESPONSE_OK:
2296 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2302 window = MODEST_MSG_EDIT_WINDOW (user_data);
2303 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2305 /* allowed size is the maximum size - what's already there */
2306 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2307 &att_num, &att_size);
2308 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2311 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2313 const gchar *uri = (const gchar *) uri_node->data;
2316 modest_msg_edit_window_attach_file_one (window, uri, allowed_size);
2318 if (total_size > allowed_size) {
2319 g_warning ("%s: total size: %u",
2320 __FUNCTION__, (unsigned int)total_size);
2323 allowed_size -= total_size;
2325 g_slist_foreach (uris, (GFunc) g_free, NULL);
2326 g_slist_free (uris);
2328 gtk_widget_destroy (GTK_WIDGET (dialog));
2332 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2334 GtkWidget *dialog = NULL;
2335 ModestMsgEditWindowPrivate *priv;
2337 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2339 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2341 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2344 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window),
2345 GTK_FILE_CHOOSER_ACTION_OPEN);
2346 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2347 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2348 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2349 GTK_WINDOW (dialog), GTK_WINDOW (window));
2351 /* Connect to response & show */
2352 g_signal_connect (dialog, "response",
2353 G_CALLBACK (on_attach_file_response), window);
2354 gtk_widget_show (dialog);
2359 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2361 GnomeVFSFileSize allowed_size)
2364 GnomeVFSHandle *handle = NULL;
2365 ModestMsgEditWindowPrivate *priv;
2366 GnomeVFSResult result;
2367 GnomeVFSFileSize size = 0;
2368 g_return_val_if_fail (window, 0);
2369 g_return_val_if_fail (uri, 0);
2371 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2373 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2374 if (result == GNOME_VFS_OK) {
2375 TnyMimePart *mime_part;
2377 const gchar *mime_type = NULL;
2379 gchar *escaped_filename;
2382 GnomeVFSFileInfo *info;
2383 GnomeVFSURI *vfs_uri;
2385 gnome_vfs_close (handle);
2386 vfs_uri = gnome_vfs_uri_new (uri);
2389 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2390 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2391 g_free (escaped_filename);
2392 gnome_vfs_uri_unref (vfs_uri);
2394 info = gnome_vfs_file_info_new ();
2396 if (gnome_vfs_get_file_info (uri,
2398 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2400 mime_type = gnome_vfs_file_info_get_mime_type (info);
2401 mime_part = tny_platform_factory_new_mime_part
2402 (modest_runtime_get_platform_factory ());
2404 /* try to get the attachment's size; this may fail for weird
2405 * file systems, like obex, upnp... */
2406 if (allowed_size != 0 &&
2407 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2409 if (size > allowed_size) {
2410 modest_platform_information_banner (NULL, NULL,
2411 _FM("sfil_ib_opening_not_allowed"));
2415 g_warning ("%s: could not get attachment size", __FUNCTION__);
2417 stream = create_stream_for_uri (uri);
2419 if (stream == NULL) {
2421 modest_platform_information_banner (NULL, NULL, _FM("sfil_ib_opening_not_allowed"));
2423 g_object_unref (mime_part);
2424 gnome_vfs_file_info_unref (info);
2428 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2429 g_object_unref (stream);
2431 content_id = g_strdup_printf ("%d", priv->next_cid);
2432 tny_mime_part_set_content_id (mime_part, content_id);
2433 g_free (content_id);
2436 basename = g_path_get_basename (filename);
2437 tny_mime_part_set_filename (mime_part, basename);
2440 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2441 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2443 info->size == 0, info->size);
2444 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2445 gtk_widget_show_all (priv->attachments_caption);
2446 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2448 g_object_unref (mime_part);
2449 gnome_vfs_file_info_unref (info);
2456 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2459 ModestMsgEditWindowPrivate *priv;
2462 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2463 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2465 if (att_list == NULL) {
2466 att_list = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2467 if (!modest_maemo_utils_select_attachments (GTK_WINDOW (window), att_list)) {
2468 g_object_unref (att_list);
2473 g_object_ref (att_list);
2476 if (tny_list_get_length (att_list) == 0) {
2477 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2479 gboolean dialog_response;
2480 gchar *message = NULL;
2481 gchar *filename = NULL;
2483 if (tny_list_get_length (att_list) == 1) {
2485 iter = tny_list_create_iterator (att_list);
2486 part = (TnyMimePart *) tny_iterator_get_current (iter);
2487 g_object_unref (iter);
2488 if (TNY_IS_MSG (part)) {
2489 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2491 filename = tny_header_dup_subject (header);
2492 g_object_unref (header);
2494 if (filename == NULL) {
2495 filename = g_strdup (_("mail_va_no_subject"));
2498 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2500 g_object_unref (part);
2502 filename = g_strdup ("");
2504 message = g_strdup_printf (ngettext("emev_nc_delete_attachment",
2505 "emev_nc_delete_attachments",
2506 tny_list_get_length (att_list)), filename);
2509 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
2513 if (dialog_response != GTK_RESPONSE_OK) {
2514 g_object_unref (att_list);
2518 for (iter = tny_list_create_iterator (att_list);
2519 !tny_iterator_is_done (iter);
2520 tny_iterator_next (iter)) {
2521 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2522 const gchar *att_id;
2523 tny_list_remove (priv->attachments, (GObject *) mime_part);
2525 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2527 if (tny_list_get_length (priv->attachments) == 0)
2528 gtk_widget_hide (priv->attachments_caption);
2529 att_id = tny_mime_part_get_content_id (mime_part);
2531 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2533 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2534 g_object_unref (mime_part);
2536 g_object_unref (iter);
2539 g_object_unref (att_list);
2541 /* if the last attachment has been removed, focus the Subject: field */
2542 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2543 gtk_widget_grab_focus (priv->subject_field);
2547 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2550 ModestMsgEditWindowPrivate *priv;
2551 GdkColor *new_color;
2552 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2554 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2555 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2558 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2560 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2562 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2564 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2569 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
2572 ModestMsgEditWindowPrivate *priv;
2573 gint new_size_index;
2574 ModestMsgEditWindow *window;
2577 window = MODEST_MSG_EDIT_WINDOW (userdata);
2578 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2579 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2581 if (gtk_check_menu_item_get_active (menu_item)) {
2583 WPTextBufferFormat format;
2585 memset (&format, 0, sizeof (format));
2586 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2588 label = gtk_bin_get_child (GTK_BIN (menu_item));
2590 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
2591 format.cs.font_size = TRUE;
2592 format.cs.text_position = TRUE;
2593 format.cs.font = TRUE;
2594 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
2595 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2597 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2598 GINT_TO_POINTER (wp_get_font_size_index (new_size_index, 12))))
2599 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2601 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2602 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
2603 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2609 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
2612 ModestMsgEditWindowPrivate *priv;
2613 gint new_font_index;
2614 ModestMsgEditWindow *window;
2617 window = MODEST_MSG_EDIT_WINDOW (userdata);
2618 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2619 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2621 if (gtk_check_menu_item_get_active (menu_item)) {
2624 label = gtk_bin_get_child (GTK_BIN (menu_item));
2626 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
2628 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2629 GINT_TO_POINTER(new_font_index)))
2630 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2632 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2633 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2634 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2640 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2643 ModestMsgEditWindowPrivate *priv = NULL;
2644 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2646 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2647 if (!priv->update_caption_visibility)
2650 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2652 gtk_widget_show (priv->cc_caption);
2654 gtk_widget_hide (priv->cc_caption);
2656 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2660 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2663 ModestMsgEditWindowPrivate *priv = NULL;
2664 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2666 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2667 if (!priv->update_caption_visibility)
2670 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2672 gtk_widget_show (priv->bcc_caption);
2674 gtk_widget_hide (priv->bcc_caption);
2676 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2680 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2681 ModestRecptEditor *editor)
2683 ModestMsgEditWindowPrivate *priv;
2685 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2686 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2688 /* we check for low-mem; in that case, show a warning, and don't allow
2689 * for the addressbook
2691 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2694 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2696 if (editor == NULL) {
2697 GtkWidget *view_focus;
2698 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2700 /* This code should be kept in sync with ModestRecptEditor. The
2701 textview inside the recpt editor is the one that really gets the
2702 focus. As it's inside a scrolled window, and this one inside the
2703 hbox recpt editor inherits from, we'll need to go up in the
2704 hierarchy to know if the text view is part of the recpt editor
2705 or if it's a different text entry */
2707 if (gtk_widget_get_parent (view_focus)) {
2708 GtkWidget *first_parent;
2710 first_parent = gtk_widget_get_parent (view_focus);
2711 if (gtk_widget_get_parent (first_parent) &&
2712 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2713 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2718 editor = MODEST_RECPT_EDITOR (priv->to_field);
2722 modest_address_book_select_addresses (editor);
2727 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2729 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2731 modest_msg_edit_window_open_addressbook (window, NULL);
2735 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2736 gboolean show_toolbar)
2738 ModestWindowPrivate *parent_priv;
2740 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2741 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2743 /* We can not just use the code of
2744 modest_msg_edit_window_setup_toolbar because it has a
2745 mixture of both initialization and creation code. */
2747 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2749 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2753 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2754 TnyHeaderFlags priority_flags)
2756 ModestMsgEditWindowPrivate *priv;
2757 ModestWindowPrivate *parent_priv;
2759 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2761 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2762 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2764 if (priv->priority_flags != priority_flags) {
2765 GtkAction *priority_action = NULL;
2767 priv->priority_flags = priority_flags;
2769 switch (priority_flags) {
2770 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2771 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2772 MODEST_HEADER_ICON_HIGH,
2773 HILDON_ICON_SIZE_SMALL);
2774 gtk_widget_show (priv->priority_icon);
2775 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2776 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2778 case TNY_HEADER_FLAG_LOW_PRIORITY:
2779 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2780 MODEST_HEADER_ICON_LOW,
2781 HILDON_ICON_SIZE_SMALL);
2782 gtk_widget_show (priv->priority_icon);
2783 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2784 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2787 gtk_widget_hide (priv->priority_icon);
2788 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2789 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2792 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2793 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2795 gtk_widget_queue_resize (priv->subject_box);
2799 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2802 ModestMsgEditWindowPrivate *priv;
2803 ModestWindowPrivate *parent_priv;
2804 gint current_format;
2806 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2808 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2809 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2811 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2812 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2814 if (current_format != file_format) {
2815 switch (file_format) {
2816 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2817 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2818 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
2820 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2824 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2825 response = gtk_dialog_run (GTK_DIALOG (dialog));
2826 gtk_widget_destroy (dialog);
2827 if (response == GTK_RESPONSE_OK) {
2828 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2830 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
2831 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
2836 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2837 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2838 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2843 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2846 ModestMsgEditWindowPrivate *priv;
2847 WPTextBufferFormat oldfmt, fmt;
2848 gint old_position = 0;
2852 GdkColor *color = NULL;
2853 gboolean bold, bold_set, italic, italic_set;
2854 gboolean underline, underline_set;
2855 gboolean strikethrough, strikethrough_set;
2856 gboolean position_set;
2857 gboolean font_size_set, font_set, color_set;
2860 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2861 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2863 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2864 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
2865 GTK_WINDOW(dialog), GTK_WINDOW (window));
2867 /* First we get the currently selected font information */
2868 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2870 switch (oldfmt.text_position) {
2871 case TEXT_POSITION_NORMAL:
2874 case TEXT_POSITION_SUPERSCRIPT:
2882 g_object_set (G_OBJECT (dialog),
2883 "bold", oldfmt.bold != FALSE,
2884 "bold-set", !oldfmt.cs.bold,
2885 "underline", oldfmt.underline != FALSE,
2886 "underline-set", !oldfmt.cs.underline,
2887 "italic", oldfmt.italic != FALSE,
2888 "italic-set", !oldfmt.cs.italic,
2889 "strikethrough", oldfmt.strikethrough != FALSE,
2890 "strikethrough-set", !oldfmt.cs.strikethrough,
2891 "color", &oldfmt.color,
2892 "color-set", !oldfmt.cs.color,
2893 "size", wp_font_size[oldfmt.font_size],
2894 "size-set", !oldfmt.cs.font_size,
2895 "position", old_position,
2896 "position-set", !oldfmt.cs.text_position,
2897 "family", wp_get_font_name (oldfmt.font),
2898 "family-set", !oldfmt.cs.font,
2901 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2902 GTK_WINDOW (dialog), GTK_WINDOW (window));
2903 gtk_widget_show_all (dialog);
2904 priv->font_dialog = dialog;
2905 response = gtk_dialog_run (GTK_DIALOG (dialog));
2906 priv->font_dialog = NULL;
2907 if (response == GTK_RESPONSE_OK) {
2909 g_object_get( dialog,
2911 "bold-set", &bold_set,
2912 "underline", &underline,
2913 "underline-set", &underline_set,
2915 "italic-set", &italic_set,
2916 "strikethrough", &strikethrough,
2917 "strikethrough-set", &strikethrough_set,
2919 "color-set", &color_set,
2921 "size-set", &font_size_set,
2922 "family", &font_name,
2923 "family-set", &font_set,
2924 "position", &position,
2925 "position-set", &position_set,
2930 if (response == GTK_RESPONSE_OK) {
2931 memset(&fmt, 0, sizeof(fmt));
2937 fmt.italic = italic;
2938 fmt.cs.italic = TRUE;
2940 if (underline_set) {
2941 fmt.underline = underline;
2942 fmt.cs.underline = TRUE;
2944 if (strikethrough_set) {
2945 fmt.strikethrough = strikethrough;
2946 fmt.cs.strikethrough = TRUE;
2951 ? TEXT_POSITION_NORMAL
2952 : ( ( position == 1 )
2953 ? TEXT_POSITION_SUPERSCRIPT
2954 : TEXT_POSITION_SUBSCRIPT );
2955 fmt.cs.text_position = TRUE;
2956 fmt.font_size = oldfmt.font_size;
2960 fmt.cs.color = TRUE;
2963 fmt.font = wp_get_font_index(font_name,
2968 if (font_size_set) {
2969 fmt.cs.font_size = TRUE;
2970 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
2972 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2973 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2975 gtk_widget_destroy (dialog);
2977 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2981 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2983 ModestMsgEditWindowPrivate *priv;
2985 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2986 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2988 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2990 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2991 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2995 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
2997 ModestMsgEditWindowPrivate *priv;
2999 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3000 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3002 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
3004 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3005 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3010 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
3012 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3014 priv->can_undo = can_undo;
3018 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
3020 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3022 priv->can_redo = can_redo;
3026 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3028 ModestMsgEditWindowPrivate *priv;
3029 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3030 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3032 return priv->can_undo;
3036 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3038 ModestMsgEditWindowPrivate *priv;
3039 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3040 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3042 return priv->can_redo;
3047 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3050 GtkTextIter match_start, match_end;
3052 if (image_id == NULL)
3055 gtk_text_buffer_get_start_iter (buffer, &iter);
3057 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3058 GSList *tags = gtk_text_iter_get_tags (&match_start);
3060 for (node = tags; node != NULL; node = g_slist_next (node)) {
3061 GtkTextTag *tag = (GtkTextTag *) node->data;
3062 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3063 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3064 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3066 offset = gtk_text_iter_get_offset (&match_start);
3067 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3068 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3072 gtk_text_iter_forward_char (&iter);
3077 message_is_empty (ModestMsgEditWindow *window)
3079 ModestMsgEditWindowPrivate *priv = NULL;
3081 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3082 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3084 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3085 * so we can ignore markup.
3087 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3090 count = gtk_text_buffer_get_char_count (buf);
3096 msg_body_focus (GtkWidget *focus,
3097 GdkEventFocus *event,
3101 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3102 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3103 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3108 recpt_field_changed (GtkTextBuffer *buffer,
3109 ModestMsgEditWindow *editor)
3111 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3112 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3116 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3118 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3119 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3123 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3126 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3127 GtkTextBuffer *buffer;
3129 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3130 gtk_text_buffer_set_modified (buffer, modified);
3131 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3132 gtk_text_buffer_set_modified (buffer, modified);
3133 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3134 gtk_text_buffer_set_modified (buffer, modified);
3135 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3139 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3141 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3142 const char *account_name;
3143 GtkTextBuffer *buffer;
3145 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3146 if (gtk_text_buffer_get_modified (buffer))
3148 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3149 if (gtk_text_buffer_get_modified (buffer))
3151 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3152 if (gtk_text_buffer_get_modified (buffer))
3154 if (gtk_text_buffer_get_modified (priv->text_buffer))
3156 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3157 if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3168 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3170 ModestMsgEditWindowPrivate *priv = NULL;
3172 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3173 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3175 /* check if there's no recipient added */
3176 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3177 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3178 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3179 /* no recipient contents, then select contacts */
3180 modest_msg_edit_window_open_addressbook (window, NULL);
3184 g_object_ref (window);
3185 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3186 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3187 g_object_unref (window);
3190 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3191 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3192 g_object_unref (window);
3195 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3196 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3197 g_object_unref (window);
3201 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3202 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3203 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3204 g_object_unref (window);
3211 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3212 ModestMsgEditWindow *window)
3214 modest_msg_edit_window_offer_attach_file (window);
3218 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3220 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3222 return priv->clipboard_text;
3226 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3228 ModestMsgEditWindow *window)
3230 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3231 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3233 if (!GTK_WIDGET_VISIBLE (window))
3236 g_object_ref (window);
3237 text = gtk_clipboard_wait_for_text (selection_clipboard);
3239 if (priv->clipboard_text != NULL) {
3240 g_free (priv->clipboard_text);
3242 priv->clipboard_text = text;
3244 if (GTK_WIDGET_VISIBLE (window)) {
3245 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3247 g_object_unref (window);
3250 static gboolean clipboard_owner_change_idle (gpointer userdata)
3252 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3253 ModestMsgEditWindowPrivate *priv;
3255 gdk_threads_enter ();
3256 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3257 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3259 priv->clipboard_owner_idle = 0;
3260 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3261 gdk_threads_leave ();
3267 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3269 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3270 if (priv->clipboard_owner_idle == 0) {
3271 priv->clipboard_owner_idle = g_idle_add (clipboard_owner_change_idle, window);
3276 subject_field_move_cursor (GtkEntry *entry,
3277 GtkMovementStep step,
3282 if (!GTK_WIDGET_VISIBLE (window))
3285 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3289 update_window_title (ModestMsgEditWindow *window)
3291 ModestMsgEditWindowPrivate *priv = NULL;
3292 const gchar *subject;
3294 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3295 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3296 if (subject == NULL || subject[0] == '\0')
3297 subject = _("mail_va_new_email");
3299 gtk_window_set_title (GTK_WINDOW (window), subject);
3304 subject_field_changed (GtkEditable *editable,
3305 ModestMsgEditWindow *window)
3307 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3308 update_window_title (window);
3309 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3310 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3311 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3315 subject_field_insert_text (GtkEditable *editable,
3317 gint new_text_length,
3319 ModestMsgEditWindow *window)
3321 GString *result = g_string_new ("");
3323 gint result_len = 0;
3324 const gchar *entry_text = NULL;
3327 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3328 old_length = g_utf8_strlen (entry_text, -1);
3330 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3331 gunichar c = g_utf8_get_char_validated (current, 8);
3332 /* Invalid unichar, stop */
3338 result = g_string_append_unichar (result, c);
3342 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3343 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3346 /* Prevent endless recursion */
3347 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3348 g_signal_emit_by_name (editable, "insert-text",
3349 (gpointer) result->str, (gpointer) result->len,
3350 (gpointer) position, (gpointer) window);
3351 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3355 if (result_len + old_length > 1000) {
3356 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3357 _CS("ckdg_ib_maximum_characters_reached"));
3359 g_string_free (result, TRUE);
3363 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3366 ModestMsgEditWindowPrivate *priv = NULL;
3368 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3369 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3371 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3374 gtk_widget_show_all (priv->find_toolbar);
3375 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3377 gtk_widget_hide_all (priv->find_toolbar);
3378 gtk_widget_grab_focus (priv->msg_body);
3383 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3385 GtkTextIter *match_start,
3386 GtkTextIter *match_end)
3388 GtkTextIter end_iter;
3389 gchar *str_casefold;
3392 gchar *range_casefold;
3395 gboolean result = FALSE;
3402 gtk_text_iter_forward_to_end (&end_iter);
3404 str_casefold = g_utf8_casefold (str, -1);
3405 str_chars_n = strlen (str);
3407 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3408 range_casefold = g_utf8_casefold (range_text, -1);
3409 range_chars_n = strlen (range_casefold);
3411 if (range_chars_n < str_chars_n) {
3412 g_free (str_casefold);
3413 g_free (range_text);
3414 g_free (range_casefold);
3418 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3419 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3420 if (!g_utf8_collate (range_subtext, str_casefold)) {
3421 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3423 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3424 match_start, match_end, NULL);
3425 g_free (found_text);
3427 g_free (range_subtext);
3431 g_free (str_casefold);
3432 g_free (range_text);
3433 g_free (range_casefold);
3440 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3441 ModestMsgEditWindow *window)
3443 gchar *current_search = NULL;
3444 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3446 GtkTextIter selection_start, selection_end;
3447 GtkTextIter match_start, match_end;
3448 gboolean continue_search = FALSE;
3450 if (message_is_empty (window)) {
3451 g_free (priv->last_search);
3452 priv->last_search = NULL;
3453 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3457 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3458 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3459 g_free (current_search);
3460 g_free (priv->last_search);
3461 priv->last_search = NULL;
3462 /* Information banner about empty search */
3463 hildon_banner_show_information (NULL, NULL, _CS("ecdg_ib_find_rep_enter_text"));
3467 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3468 continue_search = TRUE;
3470 g_free (priv->last_search);
3471 priv->last_search = g_strdup (current_search);
3474 if (continue_search) {
3475 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3476 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3477 &match_start, &match_end);
3479 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_search_complete"));
3481 GtkTextIter buffer_start;
3482 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3483 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3484 &match_start, &match_end);
3486 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_no_matches"));
3489 /* Mark as selected the string found in search */
3491 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3492 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3493 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3495 g_free (priv->last_search);
3496 priv->last_search = NULL;
3498 g_free (current_search);
3502 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3504 ModestMsgEditWindowPrivate *priv;
3506 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3511 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3514 ModestMsgEditWindowPrivate *priv;
3516 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3521 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3522 ModestMsgEditWindow *window)
3524 modest_msg_edit_window_toggle_find_toolbar (window, FALSE);
3528 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3531 ModestMsgEditWindowPrivate *priv;
3532 TnyHeader *header = NULL;
3534 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3535 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3537 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3538 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3540 if (priv->draft_msg != NULL) {
3541 g_object_unref (priv->draft_msg);
3544 if (draft != NULL) {
3545 g_object_ref (draft);
3546 header = tny_msg_get_header (draft);
3547 if (priv->msg_uid) {
3548 g_free (priv->msg_uid);
3549 priv->msg_uid = NULL;
3551 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3552 if (GTK_WIDGET_REALIZED (window)) {
3553 if (!modest_window_mgr_register_window (mgr, MODEST_WINDOW (window), NULL)) {
3554 gtk_widget_destroy (GTK_WIDGET (window));
3560 priv->draft_msg = draft;
3564 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3565 GtkTextIter *start, GtkTextIter *end,
3568 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3569 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3572 if (tag == NULL) return;
3573 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3574 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3575 replace_with_images (window, priv->images);
3580 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3583 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3585 g_return_if_fail (TNY_IS_MIME_PART (part));
3586 tny_list_prepend (priv->attachments, (GObject *) part);
3587 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3588 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3589 gtk_widget_show_all (priv->attachments_caption);
3590 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3594 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3596 ModestMsgEditWindowPrivate *priv;
3598 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3599 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3601 return priv->msg_uid;
3605 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3606 ModestMsgEditWindowWidgetType widget_type)
3608 ModestMsgEditWindowPrivate *priv;
3610 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3611 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3613 switch (widget_type) {
3614 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3615 return priv->msg_body;
3617 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3618 return priv->to_field;
3620 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3621 return priv->cc_field;
3623 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3624 return priv->bcc_field;
3626 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3627 return priv->subject_field;
3629 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3630 return priv->attachments_view;
3638 remove_tags (WPTextBuffer *buffer)
3640 GtkTextIter start, end;
3642 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3643 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3645 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3649 on_account_removed (TnyAccountStore *account_store,
3650 TnyAccount *account,
3653 /* Do nothing if it's a store account, because we use the
3654 transport to send the messages */
3655 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3656 const gchar *parent_acc = NULL;
3657 const gchar *our_acc = NULL;
3659 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3660 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3661 /* Close this window if I'm showing a message of the removed account */
3662 if (strcmp (parent_acc, our_acc) == 0)
3663 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3668 from_field_changed (HildonPickerButton *button,
3669 ModestMsgEditWindow *self)
3671 ModestMsgEditWindowPrivate *priv;
3672 gboolean has_old_signature, has_new_signature;
3674 GtkTextIter match_start, match_end;
3675 ModestAccountMgr *mgr;
3677 gchar *full_signature;
3679 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3681 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
3682 mgr = modest_runtime_get_account_mgr ();
3683 signature = modest_account_mgr_get_signature (mgr, priv->last_from_account, &has_old_signature);
3684 if (has_old_signature) {
3685 full_signature = g_strconcat ("\n--\n", signature, NULL);
3686 if (gtk_text_iter_forward_search (&iter, full_signature, 0, &match_start, &match_end, NULL)) {
3687 gtk_text_buffer_delete (priv->text_buffer, &match_start, &match_end);
3689 } else if (gtk_text_iter_forward_search (&iter, _("mcen_ia_editor_original_message"), 0,
3690 &match_start, &match_end, NULL)) {
3693 g_free (full_signature);
3697 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3698 signature = modest_account_mgr_get_signature (mgr, priv->last_from_account, &has_new_signature);
3699 if (has_new_signature) {
3700 full_signature = g_strconcat ("\n--\n", signature, NULL);
3701 gtk_text_buffer_insert (priv->text_buffer, &iter, full_signature, -1);
3702 g_free (full_signature);
3707 typedef struct _MessageSettingsHelper {
3708 ModestMsgEditWindow *window;
3709 GSList *priority_group;
3710 GSList *format_group;
3711 GtkToggleButton *current_priority;
3712 GtkToggleButton *current_format;
3713 } MessageSettingsHelper;
3716 on_priority_toggle (GtkToggleButton *button,
3717 MessageSettingsHelper *helper)
3720 ModestMsgEditWindowPrivate *priv;
3722 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3723 if (gtk_toggle_button_get_active (button)) {
3725 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3726 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3727 if ((node_button != button) &&
3728 gtk_toggle_button_get_active (node_button)) {
3729 gtk_toggle_button_set_active (node_button, FALSE);
3732 helper->current_priority = button;
3734 gboolean found = FALSE;
3735 /* If no one is active, activate it again */
3736 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3737 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3738 if (gtk_toggle_button_get_active (node_button)) {
3744 gtk_toggle_button_set_active (button, TRUE);
3750 on_format_toggle (GtkToggleButton *button,
3751 MessageSettingsHelper *helper)
3754 ModestMsgEditWindowPrivate *priv;
3756 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3757 if (gtk_toggle_button_get_active (button)) {
3759 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
3760 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3761 if ((node_button != button) &&
3762 gtk_toggle_button_get_active (node_button)) {
3763 gtk_toggle_button_set_active (node_button, FALSE);
3766 helper->current_format = button;
3768 gboolean found = FALSE;
3769 /* If no one is active, activate it again */
3770 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
3771 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3772 if (gtk_toggle_button_get_active (node_button)) {
3778 gtk_toggle_button_set_active (button, TRUE);
3785 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
3789 GtkWidget *priority_hbox;
3790 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
3791 GtkWidget *captioned;
3792 GtkSizeGroup *title_sizegroup, *value_sizegroup;
3793 GtkWidget *format_hbox;
3794 GtkWidget *html_toggle, *text_toggle;
3795 ModestMsgEditWindowPrivate *priv;
3796 MessageSettingsHelper helper = {0,};
3798 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3799 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3800 helper.window = window;
3801 helper.priority_group = NULL;
3803 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3804 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3806 dialog = gtk_dialog_new_with_buttons (_("mcen_me_message_settings"), NULL,
3807 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
3808 _HL("wdgt_bd_done"), GTK_RESPONSE_ACCEPT, NULL);
3809 vbox = gtk_vbox_new (FALSE, 0);
3810 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), vbox);
3811 gtk_widget_show (vbox);
3813 /* Priority toggles */
3814 priority_hbox = gtk_hbox_new (TRUE, 0);
3815 high_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3816 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
3817 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
3818 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
3819 medium_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3820 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
3821 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
3822 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
3823 low_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3824 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
3825 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
3826 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
3827 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, TRUE, TRUE, 0);
3828 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, TRUE, TRUE, 0);
3829 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, TRUE, TRUE, 0);
3830 gtk_widget_show_all (priority_hbox);
3831 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
3832 _("mcen_me_editor_message_priority"), FALSE, priority_hbox);
3833 gtk_widget_show (captioned);
3834 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
3836 /* format toggles */
3837 format_hbox = gtk_hbox_new (TRUE, 0);
3838 html_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3839 gtk_button_set_label (GTK_BUTTON (html_toggle), _("mcen_me_editor_formatted_text"));
3840 helper.format_group = g_slist_prepend (helper.format_group, html_toggle);
3841 g_object_set_data (G_OBJECT (html_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_HTML));
3842 g_object_set_data (G_OBJECT (html_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_FORMATTED_TEXT));
3843 text_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3844 gtk_button_set_label (GTK_BUTTON (text_toggle), _("mcen_me_editor_plain_text"));
3845 helper.format_group = g_slist_prepend (helper.format_group, text_toggle);
3846 g_object_set_data (G_OBJECT (text_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_TEXT));
3847 g_object_set_data (G_OBJECT (text_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_PLAIN_TEXT));
3848 gtk_box_pack_start (GTK_BOX (format_hbox), html_toggle, TRUE, TRUE, 0);
3849 gtk_box_pack_start (GTK_BOX (format_hbox), text_toggle, TRUE, TRUE, 0);
3850 gtk_widget_show_all (format_hbox);
3851 gtk_widget_show (format_hbox);
3852 gtk_box_pack_start (GTK_BOX (vbox), format_hbox, FALSE, FALSE, 0);
3855 g_object_unref (title_sizegroup);
3856 g_object_unref (value_sizegroup);
3858 /* Set current values */
3859 switch (priv->priority_flags) {
3860 case TNY_HEADER_FLAG_HIGH_PRIORITY:
3861 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (high_toggle), TRUE);
3862 helper.current_priority = GTK_TOGGLE_BUTTON (high_toggle);
3864 case TNY_HEADER_FLAG_LOW_PRIORITY:
3865 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (low_toggle), TRUE);
3866 helper.current_priority = GTK_TOGGLE_BUTTON (low_toggle);
3869 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (medium_toggle), TRUE);
3870 helper.current_priority = GTK_TOGGLE_BUTTON (medium_toggle);
3874 switch (modest_msg_edit_window_get_format (window)) {
3875 case MODEST_MSG_EDIT_FORMAT_TEXT:
3876 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_toggle), TRUE);
3877 helper.current_format = GTK_TOGGLE_BUTTON (text_toggle);
3879 case MODEST_MSG_EDIT_FORMAT_HTML:
3881 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (html_toggle), TRUE);
3882 helper.current_format = GTK_TOGGLE_BUTTON (html_toggle);
3886 /* Signal connects */
3887 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3888 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3889 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3890 g_signal_connect (G_OBJECT (html_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
3891 g_signal_connect (G_OBJECT (text_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
3893 /* Save settings if the user clicked on done */
3894 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
3895 TnyHeaderFlags flags;
3896 ModestMsgEditFormat old_format, new_format;
3898 /* Set priority flags */
3899 flags = (TnyHeaderFlags) g_object_get_data (G_OBJECT (helper.current_priority), "priority");
3900 if (priv->priority_flags != flags)
3901 modest_msg_edit_window_set_priority_flags (window, flags);
3903 /* Set edit format */
3904 old_format = modest_msg_edit_window_get_format (window);
3905 new_format = (ModestMsgEditFormat) g_object_get_data (G_OBJECT (helper.current_format), "format");
3906 if (old_format != new_format) {
3907 gint file_format = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (helper.current_format), "file-format"));
3908 modest_msg_edit_window_set_file_format (window, file_format);
3912 gtk_widget_destroy (dialog);
3913 g_slist_free (helper.priority_group);
3917 on_message_settings (GtkAction *action,
3918 ModestMsgEditWindow *window)
3920 modest_msg_edit_window_show_msg_settings_dialog (window);
3924 on_cc_button_toggled (HildonCheckButton *button,
3925 ModestMsgEditWindow *window)
3927 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
3929 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
3930 hildon_check_button_get_active (button));
3934 on_bcc_button_toggled (HildonCheckButton *button,
3935 ModestMsgEditWindow *window)
3937 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
3939 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
3940 hildon_check_button_get_active (button));
3944 setup_menu (ModestMsgEditWindow *self)
3946 ModestMsgEditWindowPrivate *priv = NULL;
3948 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
3950 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3952 /* Settings menu buttons */
3953 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_checknames"), NULL,
3954 APP_MENU_CALLBACK (modest_ui_actions_on_check_names),
3956 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_undo"), "<Ctrl>z",
3957 APP_MENU_CALLBACK (modest_ui_actions_on_undo),
3958 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_undo));
3960 priv->cc_button = hildon_check_button_new (0);
3961 gtk_button_set_label (GTK_BUTTON (priv->cc_button), _("mcen_me_editor_showcc"));
3962 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button),
3964 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->cc_button),
3966 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
3967 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
3968 priv->bcc_button = hildon_check_button_new (0);
3969 gtk_button_set_label (GTK_BUTTON (priv->bcc_button), _("mcen_me_editor_showbcc"));
3970 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button),
3972 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->bcc_button),
3974 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
3975 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
3977 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_attach_inlineimage"), NULL,
3978 APP_MENU_CALLBACK (modest_ui_actions_on_insert_image),
3979 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_set_style));
3980 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_remove_attachments"), NULL,
3981 APP_MENU_CALLBACK (modest_ui_actions_on_remove_attachments),
3982 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
3983 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_message_settings"), NULL,
3984 APP_MENU_CALLBACK (on_message_settings),
3986 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_viewer_find"), "<Ctrl>f",
3987 APP_MENU_CALLBACK (modest_ui_actions_on_toggle_find_in_page),