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 ModestMsgEditWindowPrivate *priv;
700 GtkActionGroup *action_group;
701 ModestWindowPrivate *parent_priv;
702 GdkPixbuf *window_icon = NULL;
703 GError *error = NULL;
705 GtkSizeGroup *title_size_group;
706 GtkSizeGroup *value_size_group;
707 GtkWidget *attachment_icon;
708 GtkWidget *window_box;
709 #if (GTK_MINOR_VERSION >= 10)
710 GdkAtom deserialize_type;
713 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
714 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
716 parent_priv->ui_manager = gtk_ui_manager_new();
717 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
718 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
720 /* Add common actions */
721 gtk_action_group_add_actions (action_group,
722 modest_msg_edit_action_entries,
723 G_N_ELEMENTS (modest_msg_edit_action_entries),
725 gtk_action_group_add_actions (action_group,
726 hildon2_msg_edit_action_entries,
727 G_N_ELEMENTS (hildon2_msg_edit_action_entries),
729 gtk_action_group_add_toggle_actions (action_group,
730 modest_msg_edit_toggle_action_entries,
731 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
733 gtk_action_group_add_radio_actions (action_group,
734 modest_msg_edit_alignment_radio_action_entries,
735 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
737 G_CALLBACK (modest_ui_actions_on_change_justify),
739 gtk_action_group_add_radio_actions (action_group,
740 modest_msg_edit_priority_action_entries,
741 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
743 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
745 gtk_action_group_add_radio_actions (action_group,
746 modest_msg_edit_file_format_action_entries,
747 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
748 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
749 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
751 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
752 g_object_unref (action_group);
754 /* Load the UI definition */
755 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
758 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
759 g_clear_error (&error);
762 /* Add accelerators */
763 gtk_window_add_accel_group (GTK_WINDOW (obj),
764 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
766 parent_priv->menubar = NULL;
768 title_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
769 value_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
771 /* Note: This ModestPairList* must exist for as long as the picker
772 * that uses it, because the ModestSelectorPicker uses the ID opaquely,
773 * so it can't know how to manage its memory. */
774 priv->from_field = modest_selector_picker_new (MODEST_EDITABLE_SIZE,
775 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL,
777 modest_maemo_utils_set_hbutton_layout (title_size_group, value_size_group,
778 _("mail_va_from"), priv->from_field);
780 priv->to_field = modest_recpt_editor_new ();
781 priv->cc_field = modest_recpt_editor_new ();
782 priv->bcc_field = modest_recpt_editor_new ();
783 priv->subject_box = gtk_hbox_new (FALSE, MODEST_MARGIN_NONE);
784 priv->priority_icon = gtk_image_new ();
785 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->priority_icon, FALSE, FALSE, 0);
786 priv->subject_field = hildon_entry_new (MODEST_EDITABLE_SIZE);
787 gtk_entry_set_max_length (GTK_ENTRY (priv->subject_field) ,SUBJECT_MAX_LENGTH);
788 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
789 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
790 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
791 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->subject_field, TRUE, TRUE, 0);
792 priv->add_attachment_button = hildon_button_new (MODEST_EDITABLE_SIZE, HILDON_BUTTON_ARRANGEMENT_VERTICAL);
793 gtk_widget_set_size_request (priv->add_attachment_button, ATTACHMENT_BUTTON_WIDTH, -1);
794 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
795 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
796 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, HILDON_ICON_SIZE_FINGER);
797 hildon_button_set_image (HILDON_BUTTON (priv->add_attachment_button), attachment_icon);
798 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->add_attachment_button, FALSE, FALSE, 0);
799 priv->attachments_view = modest_attachments_view_new (NULL);
800 modest_attachments_view_set_style (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
801 MODEST_ATTACHMENTS_VIEW_STYLE_NO_FOCUS);
803 priv->header_box = gtk_vbox_new (FALSE, 0);
805 to_caption = modest_maemo_utils_create_captioned_with_size_type
806 (title_size_group, value_size_group,
807 _("mail_va_to"), FALSE, priv->to_field,
808 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
809 priv->cc_caption = modest_maemo_utils_create_captioned_with_size_type
810 (title_size_group, value_size_group,
811 _("mail_va_cc"), FALSE, priv->cc_field,
812 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
813 priv->bcc_caption = modest_maemo_utils_create_captioned_with_size_type
814 (title_size_group, value_size_group,
815 _("mail_va_hotfix1"), FALSE, priv->bcc_field,
816 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
817 subject_caption = modest_maemo_utils_create_captioned (title_size_group, value_size_group,
818 _("mail_va_subject"), FALSE, priv->subject_box);
819 priv->attachments_caption = modest_maemo_utils_create_captioned_with_size_type (title_size_group, value_size_group,
820 _("mail_va_attachment"),
822 priv->attachments_view,
823 HILDON_SIZE_AUTO_WIDTH |
824 HILDON_SIZE_AUTO_HEIGHT);
825 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), value_size_group); */
826 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), value_size_group); */
827 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), value_size_group); */
828 g_object_unref (title_size_group);
829 g_object_unref (value_size_group);
831 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->from_field, FALSE, FALSE, 0);
832 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
833 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
834 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
835 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
836 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
837 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
839 init_wp_text_view_style ();
841 priv->msg_body = wp_text_view_new ();
844 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
845 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
846 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
847 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
848 #if (GTK_MINOR_VERSION >= 10)
849 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
850 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
852 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
853 deserialize_type, TRUE);
855 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
857 priv->find_toolbar = hildon_find_toolbar_new (NULL);
858 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
860 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
862 priv->pannable = hildon_pannable_area_new ();
864 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
866 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
867 priv->frame = gtk_frame_new (NULL);
868 gtk_box_pack_start (GTK_BOX(main_vbox), priv->frame, TRUE, TRUE, 0);
870 hildon_pannable_area_add_with_viewport (HILDON_PANNABLE_AREA (priv->pannable), main_vbox);
871 gtk_container_set_focus_vadjustment (GTK_CONTAINER (main_vbox),
872 hildon_pannable_area_get_vadjustment (HILDON_PANNABLE_AREA (priv->pannable)));
873 gtk_widget_show_all (GTK_WIDGET(priv->pannable));
875 window_box = gtk_vbox_new (FALSE, 0);
876 gtk_container_add (GTK_CONTAINER(obj), window_box);
878 gtk_box_pack_start (GTK_BOX (window_box), priv->pannable, TRUE, TRUE, 0);
880 gtk_container_add (GTK_CONTAINER (priv->frame), priv->msg_body);
882 /* Set window icon */
883 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
885 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
886 g_object_unref (window_icon);
891 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
893 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
895 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
896 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
897 priv->clipboard_change_handler_id))
898 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
899 priv->clipboard_change_handler_id);
900 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
901 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
902 priv->default_clipboard_change_handler_id))
903 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
904 priv->default_clipboard_change_handler_id);
906 if (priv->account_removed_handler_id &&
907 g_signal_handler_is_connected (modest_runtime_get_account_store (),
908 priv->account_removed_handler_id))
909 g_signal_handler_disconnect(modest_runtime_get_account_store (),
910 priv->account_removed_handler_id);
914 modest_msg_edit_window_finalize (GObject *obj)
916 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
918 /* Sanity check: shouldn't be needed, the window mgr should
919 call this function before */
920 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
922 if (priv->font_dialog != NULL) {
923 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
926 if (priv->clipboard_text != NULL) {
927 g_free (priv->clipboard_text);
928 priv->clipboard_text = NULL;
931 if (priv->draft_msg != NULL) {
932 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
933 if (TNY_IS_HEADER (header)) {
934 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
935 modest_window_mgr_unregister_header (mgr, header);
937 g_object_unref (priv->draft_msg);
938 priv->draft_msg = NULL;
940 if (priv->outbox_msg != NULL) {
941 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
942 if (TNY_IS_HEADER (header)) {
943 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
944 modest_window_mgr_unregister_header (mgr, header);
946 g_object_unref (priv->outbox_msg);
947 priv->outbox_msg = NULL;
949 if (priv->correct_scroll_idle > 0) {
950 g_source_remove (priv->correct_scroll_idle);
951 priv->correct_scroll_idle = 0;
953 if (priv->scroll_drag_timeout_id > 0) {
954 g_source_remove (priv->scroll_drag_timeout_id);
955 priv->scroll_drag_timeout_id = 0;
957 if (priv->clipboard_owner_idle > 0) {
958 g_source_remove (priv->clipboard_owner_idle);
959 priv->clipboard_owner_idle = 0;
961 if (priv->original_account_name)
962 g_free (priv->original_account_name);
963 g_free (priv->msg_uid);
964 g_free (priv->last_search);
965 g_slist_free (priv->font_items_group);
966 g_slist_free (priv->size_items_group);
967 g_object_unref (priv->attachments);
968 g_object_unref (priv->images);
970 /* This had to stay alive for as long as the picker that used it: */
971 modest_pair_list_free (priv->from_field_protos);
973 G_OBJECT_CLASS(parent_class)->finalize (obj);
977 pixbuf_from_stream (TnyStream *stream, const gchar *mime_type, guint64 *stream_size)
979 GdkPixbufLoader *loader;
985 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
987 if (loader == NULL) {
993 tny_stream_reset (TNY_STREAM (stream));
994 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
995 GError *error = NULL;
996 unsigned char read_buffer[128];
998 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
1000 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
1002 g_error_free (error);
1007 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1009 g_object_ref (pixbuf);
1010 gdk_pixbuf_loader_close (loader, NULL);
1011 g_object_unref (loader);
1016 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1017 GdkPixbuf *new_pixbuf;
1019 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1020 gdk_pixbuf_get_width (pixbuf);
1021 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1022 g_object_unref (pixbuf);
1023 pixbuf = new_pixbuf;
1027 *stream_size = size;
1033 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1035 ModestMsgEditWindowPrivate *priv;
1038 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1040 for (iter = tny_list_create_iterator (attachments);
1041 !tny_iterator_is_done (iter);
1042 tny_iterator_next (iter)) {
1043 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1044 const gchar *cid = tny_mime_part_get_content_id (part);
1045 const gchar *mime_type = tny_mime_part_get_content_type (part);
1046 if ((cid != NULL)&&(mime_type != NULL)) {
1047 guint64 stream_size;
1048 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1049 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
1052 g_object_unref (stream);
1054 if (pixbuf != NULL) {
1055 priv->images_count ++;
1056 priv->images_size += stream_size;
1057 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1058 g_object_unref (pixbuf);
1061 g_object_unref (part);
1063 g_object_unref (iter);
1067 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1069 TnyMimePart *parent = NULL;
1070 const gchar *content_type = NULL;
1071 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1073 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1075 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1076 parent = g_object_ref (msg);
1077 } else if (content_type && !g_strcasecmp (content_type, "multipart/mixed")) {
1078 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1081 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1082 iter = tny_list_create_iterator (parts);
1083 while (!tny_iterator_is_done (iter)) {
1085 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1086 content_type = tny_mime_part_get_content_type (part);
1087 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1091 g_object_unref (part);
1093 tny_iterator_next (iter);
1095 g_object_unref (iter);
1096 g_object_unref (parts);
1099 if (parent != NULL) {
1100 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1103 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1104 iter = tny_list_create_iterator (parts);
1105 while (!tny_iterator_is_done (iter)) {
1107 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1108 content_type = tny_mime_part_get_content_type (part);
1109 if (content_type && g_str_has_prefix (content_type, "image/")) {
1110 tny_list_prepend (priv->images, (GObject *) part);
1112 g_object_unref (part);
1113 tny_iterator_next (iter);
1115 g_object_unref (iter);
1116 g_object_unref (parts);
1117 g_object_unref (parent);
1122 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1125 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1127 for (iter = tny_list_create_iterator (attachments) ;
1128 !tny_iterator_is_done (iter);
1129 tny_iterator_next (iter)) {
1130 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1131 const gchar *cid = tny_mime_part_get_content_id (part);
1133 char *invalid = NULL;
1134 gint int_cid = strtol (cid, &invalid, 10);
1135 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1136 priv->next_cid = int_cid + 1;
1139 g_object_unref (part);
1141 g_object_unref (iter);
1145 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1148 gchar *to, *cc, *bcc, *subject;
1150 ModestMsgEditWindowPrivate *priv;
1151 ModestWindowPrivate *parent_priv;
1153 TnyHeaderFlags priority_flags;
1154 TnyFolder *msg_folder;
1155 gboolean is_html = FALSE;
1156 gboolean field_view_set;
1158 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1159 g_return_if_fail (TNY_IS_MSG (msg));
1161 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1162 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1164 header = tny_msg_get_header (msg);
1165 to = tny_header_dup_to (header);
1166 cc = tny_header_dup_cc (header);
1167 bcc = tny_header_dup_bcc (header);
1168 subject = tny_header_dup_subject (header);
1169 priority_flags = tny_header_get_priority (header);
1172 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
1174 field_view_set = TRUE;
1176 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
1177 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1178 gtk_widget_show (priv->cc_caption);
1179 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1180 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1181 gtk_widget_hide (priv->cc_caption);
1182 field_view_set = FALSE;
1184 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button), field_view_set);
1186 field_view_set = TRUE;
1188 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
1189 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1190 gtk_widget_show (priv->bcc_caption);
1191 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1192 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1193 gtk_widget_hide (priv->bcc_caption);
1194 field_view_set = FALSE;
1196 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button), field_view_set);
1200 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1201 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1204 update_window_title (self);
1206 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1207 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1209 if ((body == NULL)||(body[0] == '\0')) {
1211 body = modest_text_utils_convert_to_html ("");
1214 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1215 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1218 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1221 /* Add attachments to the view */
1222 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1223 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1224 if (tny_list_get_length (priv->attachments) == 0) {
1225 gtk_widget_hide (priv->attachments_caption);
1227 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1228 gtk_widget_show_all (priv->attachments_caption);
1230 get_related_images (self, msg);
1231 update_next_cid (self, priv->attachments);
1232 update_next_cid (self, priv->images);
1233 replace_with_images (self, priv->images);
1235 if (preserve_is_rich && !is_html) {
1236 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1237 /* Get the default format required from configuration */
1238 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1239 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1242 /* Set the default focus depending on having already a To: field or not */
1243 if ((!to)||(*to == '\0')) {
1244 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1246 gtk_widget_grab_focus (priv->msg_body);
1249 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1251 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1252 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1254 modest_msg_edit_window_set_modified (self, FALSE);
1256 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1257 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1258 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1259 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1261 if (priv->msg_uid) {
1262 g_free (priv->msg_uid);
1263 priv->msg_uid = NULL;
1266 /* we should set a reference to the incoming message if it is a draft */
1267 msg_folder = tny_msg_get_folder (msg);
1269 if (modest_tny_folder_is_local_folder (msg_folder)) {
1270 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1271 if (type == TNY_FOLDER_TYPE_INVALID)
1272 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1274 if (type == TNY_FOLDER_TYPE_DRAFTS)
1275 priv->draft_msg = g_object_ref(msg);
1276 if (type == TNY_FOLDER_TYPE_OUTBOX)
1277 priv->outbox_msg = g_object_ref(msg);
1278 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1280 g_object_unref (msg_folder);
1290 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
1293 GList *item_children, *node;
1294 GtkWidget *bin_child;
1296 bin_child = gtk_bin_get_child (GTK_BIN(item));
1298 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
1300 for (node = item_children; node != NULL; node = g_list_next (node)) {
1301 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
1302 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
1305 g_list_free (item_children);
1309 menu_tool_button_dont_expand (GtkMenuToolButton *item)
1312 GList *item_children, *node;
1314 box = gtk_bin_get_child (GTK_BIN (item));
1315 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
1316 item_children = gtk_container_get_children (GTK_CONTAINER (box));
1318 for (node = item_children; node != NULL; node = g_list_next (node)) {
1319 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
1320 if (GTK_IS_TOGGLE_BUTTON (node->data))
1321 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
1322 else if (GTK_IS_BUTTON (node->data))
1323 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
1325 g_list_free (item_children);
1330 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1332 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1333 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1334 GtkWidget *placeholder;
1335 GtkWidget *tool_item;
1340 GtkWidget *sizes_menu;
1341 GtkWidget *fonts_menu;
1342 GSList *radio_group = NULL;
1343 GSList *node = NULL;
1347 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1348 gtk_toolbar_set_show_arrow (GTK_TOOLBAR (parent_priv->toolbar), FALSE);
1349 gtk_toolbar_set_icon_size (GTK_TOOLBAR (parent_priv->toolbar), HILDON_ICON_SIZE_FINGER);
1350 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1352 /* Font color placeholder */
1353 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1354 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1357 priv->font_color_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1358 priv->font_color_button = hildon_color_button_new ();
1359 gtk_widget_set_size_request (priv->font_color_button, -1, 48);
1360 GTK_WIDGET_UNSET_FLAGS (priv->font_color_toolitem, GTK_CAN_FOCUS);
1361 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1362 gtk_container_add (GTK_CONTAINER (priv->font_color_toolitem), priv->font_color_button);
1363 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1364 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1365 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->font_color_toolitem), insert_index);
1366 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1368 G_CALLBACK (modest_msg_edit_window_color_button_change),
1371 /* Font size and face placeholder */
1372 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1373 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1375 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1376 priv->size_tool_button_label = gtk_label_new (NULL);
1377 hildon_helper_set_logical_color (GTK_WIDGET (priv->size_tool_button_label), GTK_RC_TEXT,
1378 GTK_STATE_INSENSITIVE, "SecondaryTextColor");
1379 hildon_helper_set_logical_color (GTK_WIDGET (priv->size_tool_button_label), GTK_RC_FG,
1380 GTK_STATE_INSENSITIVE, "SecondaryTextColor");
1381 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1382 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1383 size_text,"</span>", NULL);
1384 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1386 hildon_helper_set_logical_font (priv->size_tool_button_label, "LargeSystemFont");
1387 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
1388 sizes_menu = gtk_menu_new ();
1389 priv->size_items_group = NULL;
1391 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1392 GtkWidget *size_menu_item;
1394 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1395 size_menu_item = gtk_radio_menu_item_new_with_label (radio_group, size_text);
1396 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (size_menu_item));
1397 gtk_menu_shell_append (GTK_MENU_SHELL (sizes_menu), size_menu_item);
1398 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (size_menu_item), (wp_font_size[size_index] == 12));
1399 gtk_widget_show (size_menu_item);
1401 priv->size_items_group = g_slist_prepend (priv->size_items_group, size_menu_item);
1405 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1406 GtkWidget *item = (GtkWidget *) node->data;
1407 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_size_change),
1411 priv->size_items_group = g_slist_reverse (priv->size_items_group);
1412 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), sizes_menu);
1413 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1414 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1415 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), FALSE);
1416 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), FALSE);
1417 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1418 priv->font_size_toolitem = tool_item;
1421 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1422 priv->font_tool_button_label = gtk_label_new (NULL);
1423 hildon_helper_set_logical_color (GTK_WIDGET (priv->font_tool_button_label), GTK_RC_TEXT,
1424 GTK_STATE_INSENSITIVE, "SecondaryTextColor");
1425 hildon_helper_set_logical_color (GTK_WIDGET (priv->font_tool_button_label), GTK_RC_FG,
1426 GTK_STATE_INSENSITIVE, "SecondaryTextColor");
1427 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1428 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1430 hildon_helper_set_logical_font (priv->font_tool_button_label, "LargeSystemFont");
1431 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
1432 fonts_menu = gtk_menu_new ();
1433 priv->font_items_group = NULL;
1435 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1436 GtkWidget *font_menu_item;
1437 GtkWidget *child_label;
1439 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
1440 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
1441 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
1442 wp_get_font_name (font_index), "</span>", NULL);
1443 gtk_label_set_markup (GTK_LABEL (child_label), markup);
1446 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
1447 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
1448 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
1449 gtk_widget_show (font_menu_item);
1451 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
1454 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1455 GtkWidget *item = (GtkWidget *) node->data;
1456 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
1459 priv->font_items_group = g_slist_reverse (priv->font_items_group);
1460 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
1461 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1462 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1463 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), FALSE);
1464 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), FALSE);
1465 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1466 priv->font_face_toolitem = tool_item;
1468 /* Set expand and homogeneous for remaining items */
1469 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
1470 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1471 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1472 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1473 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1474 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1475 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1476 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1477 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1479 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1480 will not show the tool items added to the placeholders) */
1481 gtk_widget_show_all (parent_priv->toolbar);
1483 /* Set the no show all *after* showing all items. We do not
1484 want the toolbar to be shown with a show all because it
1485 could go agains the gconf setting regarding showing or not
1486 the toolbar of the editor window */
1487 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1493 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, gboolean preserve_is_rich)
1496 ModestWindowPrivate *parent_priv;
1497 ModestMsgEditWindowPrivate *priv;
1498 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1499 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1500 ModestWindowMgr *mgr = NULL;
1502 g_return_val_if_fail (msg, NULL);
1503 g_return_val_if_fail (account_name, NULL);
1505 mgr = modest_runtime_get_window_mgr ();
1507 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1509 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1510 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1512 /* Menubar. Update the state of some toggles */
1513 priv->from_field_protos = get_transports ();
1514 modest_selector_picker_set_pair_list (MODEST_SELECTOR_PICKER (priv->from_field), priv->from_field_protos);
1515 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1516 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1517 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1519 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1520 hildon_touch_selector_get_current_text
1521 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1522 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1523 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1526 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1528 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1530 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1532 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1534 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1535 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1536 /* Add common dimming rules */
1537 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1538 modest_msg_edit_window_toolbar_dimming_entries,
1539 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1540 MODEST_WINDOW (obj));
1541 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_toolitem,
1542 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1543 MODEST_WINDOW (obj));
1544 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1545 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1546 MODEST_WINDOW (obj));
1547 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1548 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1549 MODEST_WINDOW (obj));
1550 /* Insert dimming rules group for this window */
1551 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1552 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1554 /* Setup app menu */
1555 setup_menu (MODEST_MSG_EDIT_WINDOW (obj));
1557 /* Checks the dimming rules */
1558 g_object_unref (toolbar_rules_group);
1559 g_object_unref (clipboard_rules_group);
1560 gtk_widget_hide (priv->priority_icon);
1561 gtk_widget_queue_resize (priv->subject_box);
1562 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1564 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1566 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1567 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1568 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1569 priv->update_caption_visibility = TRUE;
1571 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1573 /* Track account-removed signal, this window should be closed
1574 in the case we're creating a mail associated to the account
1576 priv->account_removed_handler_id =
1577 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1579 G_CALLBACK(on_account_removed),
1582 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1584 return (ModestWindow*) obj;
1588 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1590 GString **string_buffer = (GString **) user_data;
1592 *string_buffer = g_string_append (*string_buffer, buffer);
1598 * @result: A new string which should be freed with g_free().
1601 get_formatted_data (ModestMsgEditWindow *edit_window)
1603 ModestMsgEditWindowPrivate *priv;
1604 GString *string_buffer = g_string_new ("");
1606 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1608 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1610 modest_text_utils_hyperlinkify (string_buffer);
1612 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1614 return g_string_free (string_buffer, FALSE);
1619 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1622 const gchar *account_name;
1623 ModestMsgEditWindowPrivate *priv;
1624 TnyIterator *att_iter;
1626 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1628 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1630 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1631 g_return_val_if_fail (account_name, NULL);
1634 /* don't free these (except from) */
1635 data = g_slice_new0 (MsgData);
1636 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1638 data->account_name = g_strdup (account_name);
1639 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1640 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1641 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1642 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1643 if (priv->draft_msg) {
1644 data->draft_msg = g_object_ref (priv->draft_msg);
1645 } else if (priv->outbox_msg) {
1646 data->draft_msg = g_object_ref (priv->outbox_msg);
1648 data->draft_msg = NULL;
1651 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1653 gtk_text_buffer_get_bounds (buf, &b, &e);
1654 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1656 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1657 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1659 data->html_body = NULL;
1661 /* deep-copy the data */
1662 att_iter = tny_list_create_iterator (priv->attachments);
1663 data->attachments = NULL;
1664 while (!tny_iterator_is_done (att_iter)) {
1665 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1666 if (!(TNY_IS_MIME_PART(part))) {
1667 g_warning ("strange data in attachment list");
1668 g_object_unref (part);
1669 tny_iterator_next (att_iter);
1672 data->attachments = g_list_append (data->attachments,
1674 tny_iterator_next (att_iter);
1676 g_object_unref (att_iter);
1678 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1679 att_iter = tny_list_create_iterator (priv->images);
1680 data->images = NULL;
1681 while (!tny_iterator_is_done (att_iter)) {
1682 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1684 if (!(TNY_IS_MIME_PART(part))) {
1685 g_warning ("strange data in attachment list");
1686 g_object_unref (part);
1687 tny_iterator_next (att_iter);
1690 cid = tny_mime_part_get_content_id (part);
1692 gchar *image_tag_id;
1693 GtkTextTag *image_tag;
1695 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1696 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1697 g_free (image_tag_id);
1699 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1701 ((gtk_text_iter_has_tag (&iter, image_tag))||
1702 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1703 data->images = g_list_append (data->images,
1704 g_object_ref (part));
1706 g_object_unref (part);
1707 tny_iterator_next (att_iter);
1709 g_object_unref (att_iter);
1711 data->priority_flags = priv->priority_flags;
1718 unref_gobject (GObject *obj, gpointer data)
1720 if (!G_IS_OBJECT(obj))
1722 g_object_unref (obj);
1726 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1729 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1737 g_free (data->from);
1738 g_free (data->subject);
1739 g_free (data->plain_body);
1740 g_free (data->html_body);
1741 g_free (data->account_name);
1743 if (data->draft_msg != NULL) {
1744 g_object_unref (data->draft_msg);
1745 data->draft_msg = NULL;
1748 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1749 g_list_free (data->attachments);
1750 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1751 g_list_free (data->images);
1753 g_slice_free (MsgData, data);
1757 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1759 guint64 *parts_size)
1761 ModestMsgEditWindowPrivate *priv;
1763 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1765 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1767 /* TODO: add images */
1768 *parts_size += priv->images_size;
1769 *parts_count += priv->images_count;
1774 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1777 ModestMsgEditWindowPrivate *priv = NULL;
1778 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1780 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1782 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1784 return MODEST_MSG_EDIT_FORMAT_HTML;
1786 return MODEST_MSG_EDIT_FORMAT_TEXT;
1790 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1791 ModestMsgEditFormat format)
1793 ModestMsgEditWindowPrivate *priv;
1795 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1796 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1799 case MODEST_MSG_EDIT_FORMAT_HTML:
1800 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1802 case MODEST_MSG_EDIT_FORMAT_TEXT:
1803 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1806 g_return_if_reached ();
1810 ModestMsgEditFormatState *
1811 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1813 ModestMsgEditFormatState *format_state = NULL;
1814 ModestMsgEditWindowPrivate *priv;
1815 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1817 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1818 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1820 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1822 format_state = g_new0 (ModestMsgEditFormatState, 1);
1823 format_state->bold = buffer_format->bold&0x1;
1824 format_state->italics = buffer_format->italic&0x1;
1825 format_state->bullet = buffer_format->bullet&0x1;
1826 format_state->color = buffer_format->color;
1827 format_state->font_size = buffer_format->font_size;
1828 format_state->font_family = wp_get_font_name (buffer_format->font);
1829 format_state->justification = buffer_format->justification;
1830 g_free (buffer_format);
1832 return format_state;
1837 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1838 const ModestMsgEditFormatState *format_state)
1840 ModestMsgEditWindowPrivate *priv;
1841 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1842 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1843 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1844 g_return_if_fail (format_state != NULL);
1846 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1847 gtk_widget_grab_focus (priv->msg_body);
1848 buffer_format->bold = (format_state->bold != FALSE);
1849 buffer_format->italic = (format_state->italics != FALSE);
1850 buffer_format->color = format_state->color;
1851 buffer_format->font_size = format_state->font_size;
1852 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1853 buffer_format->justification = format_state->justification;
1854 buffer_format->bullet = format_state->bullet;
1856 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1858 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1859 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1860 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1861 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1862 buffer_format->cs.font = (buffer_format->font != current_format->font);
1863 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1864 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1866 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1867 if (buffer_format->cs.bold) {
1868 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
1869 GINT_TO_POINTER (buffer_format->bold&0x1));
1871 if (buffer_format->cs.italic) {
1872 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
1873 GINT_TO_POINTER (buffer_format->italic&0x1));
1875 if (buffer_format->cs.color) {
1876 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1877 GINT_TO_POINTER (&(buffer_format->color)));
1879 if (buffer_format->cs.font_size) {
1880 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1881 GINT_TO_POINTER (buffer_format->font_size));
1883 if (buffer_format->cs.justification) {
1884 switch (buffer_format->justification) {
1885 case GTK_JUSTIFY_LEFT:
1886 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
1887 GINT_TO_POINTER(TRUE));
1889 case GTK_JUSTIFY_CENTER:
1890 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
1891 GINT_TO_POINTER(TRUE));
1893 case GTK_JUSTIFY_RIGHT:
1894 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
1895 GINT_TO_POINTER(TRUE));
1902 if (buffer_format->cs.font) {
1903 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1904 GINT_TO_POINTER (buffer_format->font));
1906 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1907 if (buffer_format->cs.bullet) {
1908 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
1909 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
1911 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1913 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
1915 g_free (buffer_format);
1916 g_free (current_format);
1918 /* Check dimming rules */
1919 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1920 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1924 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1926 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1928 ModestWindowPrivate *parent_priv;
1929 ModestMsgEditWindowPrivate *priv;
1930 GtkWidget *new_size_menuitem;
1931 GtkWidget *new_font_menuitem;
1933 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1934 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1936 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1937 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu");
1938 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1939 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1941 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatPlainTextMenu");
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);
1946 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1948 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1949 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1951 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1952 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1954 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
1955 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
1958 switch (buffer_format->justification)
1960 case GTK_JUSTIFY_LEFT:
1961 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
1963 case GTK_JUSTIFY_CENTER:
1964 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
1966 case GTK_JUSTIFY_RIGHT:
1967 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
1974 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
1976 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1977 G_CALLBACK (modest_msg_edit_window_color_button_change),
1979 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1980 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1981 G_CALLBACK (modest_msg_edit_window_color_button_change),
1984 new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group,
1985 buffer_format->font_size))->data);
1986 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1990 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1991 markup = g_strconcat ("<span font_family='Sans'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1992 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1994 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1995 G_CALLBACK (modest_msg_edit_window_size_change),
1997 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
1998 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
1999 G_CALLBACK (modest_msg_edit_window_size_change),
2003 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
2004 buffer_format->font))->data);
2005 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
2009 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
2010 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2011 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2013 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
2014 G_CALLBACK (modest_msg_edit_window_font_change),
2016 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
2017 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
2018 G_CALLBACK (modest_msg_edit_window_font_change),
2022 g_free (buffer_format);
2026 #ifdef MODEST_HILDON_VERSION_0
2028 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2031 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2032 ModestMsgEditWindowPrivate *priv;
2033 GtkWidget *dialog = NULL;
2035 GdkColor *new_color = NULL;
2037 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2038 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2040 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2041 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
2042 g_free (buffer_format);
2044 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2045 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2046 if (new_color != NULL) {
2047 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2048 (gpointer) new_color);
2051 gtk_widget_destroy (dialog);
2056 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2059 ModestMsgEditWindowPrivate *priv;
2060 GtkWidget *dialog = NULL;
2062 GdkColor *old_color = NULL;
2063 const GdkColor *new_color = NULL;
2065 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2066 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2068 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2069 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2071 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2072 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2073 if (new_color != NULL)
2074 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2076 gtk_widget_destroy (dialog);
2082 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2085 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2086 ModestMsgEditWindowPrivate *priv;
2087 GtkWidget *dialog = NULL;
2089 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2090 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2092 dialog = hildon_color_chooser_new ();
2093 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2094 g_free (buffer_format);
2096 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2098 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2099 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2102 gtk_widget_destroy (dialog);
2107 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2110 ModestMsgEditWindowPrivate *priv;
2111 GtkWidget *dialog = NULL;
2112 GdkColor *old_color = NULL;
2114 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2115 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2117 dialog = hildon_color_chooser_new ();
2118 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2120 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2122 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2123 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2125 gtk_widget_destroy (dialog);
2128 #endif /*!MODEST_HILDON_VERSION_0*/
2133 create_stream_for_uri (const gchar* uri)
2138 TnyStream *result = NULL;
2140 GnomeVFSHandle *handle = NULL;
2141 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2142 if (test == GNOME_VFS_OK) {
2143 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2144 /* Streams over OBEX (Bluetooth) are not seekable but
2145 * we expect them to be (we might need to read them
2146 * several times). So if this is a Bluetooth URI just
2147 * read the whole file into memory (this is not a fast
2148 * protocol so we can assume that these files are not
2149 * going to be very big) */
2150 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2151 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2152 TnyStream *memstream = tny_camel_mem_stream_new ();
2153 tny_stream_write_to_stream (vfssstream, memstream);
2154 g_object_unref (vfssstream);
2157 result = vfssstream;
2165 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2168 ModestMsgEditWindowPrivate *priv;
2169 GtkWidget *dialog = NULL;
2171 GSList *uris = NULL;
2172 GSList *uri_node = NULL;
2174 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2176 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2177 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2178 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2180 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2182 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2183 GTK_WINDOW (dialog), GTK_WINDOW (window));
2185 response = gtk_dialog_run (GTK_DIALOG (dialog));
2187 case GTK_RESPONSE_OK:
2188 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2193 gtk_widget_destroy (dialog);
2195 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2197 GnomeVFSHandle *handle = NULL;
2198 GnomeVFSResult result;
2199 GtkTextIter position;
2200 GtkTextMark *insert_mark;
2202 uri = (const gchar *) uri_node->data;
2203 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2204 if (result == GNOME_VFS_OK) {
2206 GnomeVFSFileInfo *info;
2207 gchar *filename, *basename, *escaped_filename;
2208 TnyMimePart *mime_part;
2210 const gchar *mime_type = NULL;
2211 GnomeVFSURI *vfs_uri;
2212 guint64 stream_size;
2214 gnome_vfs_close (handle);
2215 vfs_uri = gnome_vfs_uri_new (uri);
2217 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2218 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2219 g_free (escaped_filename);
2220 gnome_vfs_uri_unref (vfs_uri);
2221 info = gnome_vfs_file_info_new ();
2223 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2224 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2226 mime_type = gnome_vfs_file_info_get_mime_type (info);
2228 mime_part = tny_platform_factory_new_mime_part
2229 (modest_runtime_get_platform_factory ());
2231 TnyStream *stream = create_stream_for_uri (uri);
2233 if (stream == NULL) {
2235 modest_platform_information_banner (NULL, NULL,
2236 _FM("sfil_ib_opening_not_allowed"));
2238 g_object_unref (mime_part);
2239 gnome_vfs_file_info_unref (info);
2243 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2245 content_id = g_strdup_printf ("%d", priv->next_cid);
2246 tny_mime_part_set_content_id (mime_part, content_id);
2247 g_free (content_id);
2250 basename = g_path_get_basename (filename);
2251 tny_mime_part_set_filename (mime_part, basename);
2254 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
2256 if (pixbuf != NULL) {
2257 priv->images_size += stream_size;
2258 priv->images_count ++;
2259 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2260 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2261 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
2262 g_object_unref (pixbuf);
2265 tny_list_prepend (priv->images, (GObject *) mime_part);
2266 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2268 g_object_unref (mime_part);
2269 gnome_vfs_file_info_unref (info);
2278 on_attach_file_response (GtkDialog *dialog,
2282 GSList *uris = NULL;
2284 GnomeVFSFileSize total_size, allowed_size;
2285 ModestMsgEditWindow *window;
2286 ModestMsgEditWindowPrivate *priv;
2291 case GTK_RESPONSE_OK:
2292 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2298 window = MODEST_MSG_EDIT_WINDOW (user_data);
2299 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2301 /* allowed size is the maximum size - what's already there */
2302 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2303 &att_num, &att_size);
2304 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2307 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2309 const gchar *uri = (const gchar *) uri_node->data;
2312 modest_msg_edit_window_attach_file_one (window, uri, allowed_size);
2314 if (total_size > allowed_size) {
2315 g_warning ("%s: total size: %u",
2316 __FUNCTION__, (unsigned int)total_size);
2319 allowed_size -= total_size;
2321 g_slist_foreach (uris, (GFunc) g_free, NULL);
2322 g_slist_free (uris);
2324 gtk_widget_destroy (GTK_WIDGET (dialog));
2328 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2330 GtkWidget *dialog = NULL;
2331 ModestMsgEditWindowPrivate *priv;
2333 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2335 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2337 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2340 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window),
2341 GTK_FILE_CHOOSER_ACTION_OPEN);
2342 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2343 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2344 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2345 GTK_WINDOW (dialog), GTK_WINDOW (window));
2347 /* Connect to response & show */
2348 g_signal_connect (dialog, "response",
2349 G_CALLBACK (on_attach_file_response), window);
2350 gtk_widget_show (dialog);
2355 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2357 GnomeVFSFileSize allowed_size)
2360 GnomeVFSHandle *handle = NULL;
2361 ModestMsgEditWindowPrivate *priv;
2362 GnomeVFSResult result;
2363 GnomeVFSFileSize size = 0;
2364 g_return_val_if_fail (window, 0);
2365 g_return_val_if_fail (uri, 0);
2367 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2369 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2370 if (result == GNOME_VFS_OK) {
2371 TnyMimePart *mime_part;
2373 const gchar *mime_type = NULL;
2375 gchar *escaped_filename;
2378 GnomeVFSFileInfo *info;
2379 GnomeVFSURI *vfs_uri;
2381 gnome_vfs_close (handle);
2382 vfs_uri = gnome_vfs_uri_new (uri);
2385 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2386 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2387 g_free (escaped_filename);
2388 gnome_vfs_uri_unref (vfs_uri);
2390 info = gnome_vfs_file_info_new ();
2392 if (gnome_vfs_get_file_info (uri,
2394 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2396 mime_type = gnome_vfs_file_info_get_mime_type (info);
2397 mime_part = tny_platform_factory_new_mime_part
2398 (modest_runtime_get_platform_factory ());
2400 /* try to get the attachment's size; this may fail for weird
2401 * file systems, like obex, upnp... */
2402 if (allowed_size != 0 &&
2403 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2405 if (size > allowed_size) {
2406 modest_platform_information_banner (NULL, NULL,
2407 _FM("sfil_ib_opening_not_allowed"));
2411 g_warning ("%s: could not get attachment size", __FUNCTION__);
2413 stream = create_stream_for_uri (uri);
2415 if (stream == NULL) {
2417 modest_platform_information_banner (NULL, NULL, _FM("sfil_ib_opening_not_allowed"));
2419 g_object_unref (mime_part);
2420 gnome_vfs_file_info_unref (info);
2424 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2425 g_object_unref (stream);
2427 content_id = g_strdup_printf ("%d", priv->next_cid);
2428 tny_mime_part_set_content_id (mime_part, content_id);
2429 g_free (content_id);
2432 basename = g_path_get_basename (filename);
2433 tny_mime_part_set_filename (mime_part, basename);
2436 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2437 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2439 info->size == 0, info->size);
2440 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2441 gtk_widget_show_all (priv->attachments_caption);
2442 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2444 g_object_unref (mime_part);
2445 gnome_vfs_file_info_unref (info);
2452 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2455 ModestMsgEditWindowPrivate *priv;
2458 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2459 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2461 if (att_list == NULL) {
2462 att_list = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2463 if (!modest_maemo_utils_select_attachments (GTK_WINDOW (window), att_list)) {
2464 g_object_unref (att_list);
2469 g_object_ref (att_list);
2472 if (tny_list_get_length (att_list) == 0) {
2473 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2475 gboolean dialog_response;
2476 gchar *message = NULL;
2477 gchar *filename = NULL;
2479 if (tny_list_get_length (att_list) == 1) {
2481 iter = tny_list_create_iterator (att_list);
2482 part = (TnyMimePart *) tny_iterator_get_current (iter);
2483 g_object_unref (iter);
2484 if (TNY_IS_MSG (part)) {
2485 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2487 filename = tny_header_dup_subject (header);
2488 g_object_unref (header);
2490 if (filename == NULL) {
2491 filename = g_strdup (_("mail_va_no_subject"));
2494 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2496 g_object_unref (part);
2498 filename = g_strdup ("");
2500 message = g_strdup_printf (ngettext("emev_nc_delete_attachment",
2501 "emev_nc_delete_attachments",
2502 tny_list_get_length (att_list)), filename);
2505 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
2509 if (dialog_response != GTK_RESPONSE_OK) {
2510 g_object_unref (att_list);
2514 for (iter = tny_list_create_iterator (att_list);
2515 !tny_iterator_is_done (iter);
2516 tny_iterator_next (iter)) {
2517 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2518 const gchar *att_id;
2519 tny_list_remove (priv->attachments, (GObject *) mime_part);
2521 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2523 if (tny_list_get_length (priv->attachments) == 0)
2524 gtk_widget_hide (priv->attachments_caption);
2525 att_id = tny_mime_part_get_content_id (mime_part);
2527 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2529 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2530 g_object_unref (mime_part);
2532 g_object_unref (iter);
2535 g_object_unref (att_list);
2537 /* if the last attachment has been removed, focus the Subject: field */
2538 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2539 gtk_widget_grab_focus (priv->subject_field);
2543 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2546 ModestMsgEditWindowPrivate *priv;
2547 GdkColor *new_color;
2548 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2550 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2551 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2554 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2556 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2558 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2560 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2565 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
2568 ModestMsgEditWindowPrivate *priv;
2569 gint new_size_index;
2570 ModestMsgEditWindow *window;
2573 window = MODEST_MSG_EDIT_WINDOW (userdata);
2574 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2575 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2577 if (gtk_check_menu_item_get_active (menu_item)) {
2579 WPTextBufferFormat format;
2581 memset (&format, 0, sizeof (format));
2582 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2584 label = gtk_bin_get_child (GTK_BIN (menu_item));
2586 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
2587 format.cs.font_size = TRUE;
2588 format.cs.text_position = TRUE;
2589 format.cs.font = TRUE;
2590 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
2591 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2593 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2594 GINT_TO_POINTER (wp_get_font_size_index (new_size_index, 12))))
2595 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2597 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2598 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
2599 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2605 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
2608 ModestMsgEditWindowPrivate *priv;
2609 gint new_font_index;
2610 ModestMsgEditWindow *window;
2613 window = MODEST_MSG_EDIT_WINDOW (userdata);
2614 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2615 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2617 if (gtk_check_menu_item_get_active (menu_item)) {
2620 label = gtk_bin_get_child (GTK_BIN (menu_item));
2622 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
2624 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2625 GINT_TO_POINTER(new_font_index)))
2626 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2628 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2629 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2630 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2636 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2639 ModestMsgEditWindowPrivate *priv = NULL;
2640 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2642 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2643 if (!priv->update_caption_visibility)
2646 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2648 gtk_widget_show (priv->cc_caption);
2650 gtk_widget_hide (priv->cc_caption);
2652 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2656 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2659 ModestMsgEditWindowPrivate *priv = NULL;
2660 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2662 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2663 if (!priv->update_caption_visibility)
2666 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2668 gtk_widget_show (priv->bcc_caption);
2670 gtk_widget_hide (priv->bcc_caption);
2672 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2676 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2677 ModestRecptEditor *editor)
2679 ModestMsgEditWindowPrivate *priv;
2681 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2682 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2684 /* we check for low-mem; in that case, show a warning, and don't allow
2685 * for the addressbook
2687 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2690 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2692 if (editor == NULL) {
2693 GtkWidget *view_focus;
2694 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2696 /* This code should be kept in sync with ModestRecptEditor. The
2697 textview inside the recpt editor is the one that really gets the
2698 focus. As it's inside a scrolled window, and this one inside the
2699 hbox recpt editor inherits from, we'll need to go up in the
2700 hierarchy to know if the text view is part of the recpt editor
2701 or if it's a different text entry */
2703 if (gtk_widget_get_parent (view_focus)) {
2704 GtkWidget *first_parent;
2706 first_parent = gtk_widget_get_parent (view_focus);
2707 if (gtk_widget_get_parent (first_parent) &&
2708 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2709 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2714 editor = MODEST_RECPT_EDITOR (priv->to_field);
2718 modest_address_book_select_addresses (editor);
2723 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2725 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2727 modest_msg_edit_window_open_addressbook (window, NULL);
2731 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2732 gboolean show_toolbar)
2734 ModestWindowPrivate *parent_priv;
2736 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2737 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2739 /* We can not just use the code of
2740 modest_msg_edit_window_setup_toolbar because it has a
2741 mixture of both initialization and creation code. */
2743 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2745 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2749 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2750 TnyHeaderFlags priority_flags)
2752 ModestMsgEditWindowPrivate *priv;
2753 ModestWindowPrivate *parent_priv;
2755 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2757 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2758 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2760 if (priv->priority_flags != priority_flags) {
2761 GtkAction *priority_action = NULL;
2763 priv->priority_flags = priority_flags;
2765 switch (priority_flags) {
2766 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2767 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2768 MODEST_HEADER_ICON_HIGH,
2769 HILDON_ICON_SIZE_SMALL);
2770 gtk_widget_show (priv->priority_icon);
2771 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2772 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2774 case TNY_HEADER_FLAG_LOW_PRIORITY:
2775 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2776 MODEST_HEADER_ICON_LOW,
2777 HILDON_ICON_SIZE_SMALL);
2778 gtk_widget_show (priv->priority_icon);
2779 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2780 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2783 gtk_widget_hide (priv->priority_icon);
2784 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2785 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2788 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2789 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2791 gtk_widget_queue_resize (priv->subject_box);
2795 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2798 ModestMsgEditWindowPrivate *priv;
2799 ModestWindowPrivate *parent_priv;
2800 gint current_format;
2802 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2804 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2805 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2807 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2808 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2810 if (current_format != file_format) {
2811 switch (file_format) {
2812 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2813 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2814 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
2816 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2820 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2821 response = gtk_dialog_run (GTK_DIALOG (dialog));
2822 gtk_widget_destroy (dialog);
2823 if (response == GTK_RESPONSE_OK) {
2824 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2826 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
2827 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
2832 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2833 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2834 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2839 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2842 ModestMsgEditWindowPrivate *priv;
2843 WPTextBufferFormat oldfmt, fmt;
2844 gint old_position = 0;
2848 GdkColor *color = NULL;
2849 gboolean bold, bold_set, italic, italic_set;
2850 gboolean underline, underline_set;
2851 gboolean strikethrough, strikethrough_set;
2852 gboolean position_set;
2853 gboolean font_size_set, font_set, color_set;
2856 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2857 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2859 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2860 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
2861 GTK_WINDOW(dialog), GTK_WINDOW (window));
2863 /* First we get the currently selected font information */
2864 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2866 switch (oldfmt.text_position) {
2867 case TEXT_POSITION_NORMAL:
2870 case TEXT_POSITION_SUPERSCRIPT:
2878 g_object_set (G_OBJECT (dialog),
2879 "bold", oldfmt.bold != FALSE,
2880 "bold-set", !oldfmt.cs.bold,
2881 "underline", oldfmt.underline != FALSE,
2882 "underline-set", !oldfmt.cs.underline,
2883 "italic", oldfmt.italic != FALSE,
2884 "italic-set", !oldfmt.cs.italic,
2885 "strikethrough", oldfmt.strikethrough != FALSE,
2886 "strikethrough-set", !oldfmt.cs.strikethrough,
2887 "color", &oldfmt.color,
2888 "color-set", !oldfmt.cs.color,
2889 "size", wp_font_size[oldfmt.font_size],
2890 "size-set", !oldfmt.cs.font_size,
2891 "position", old_position,
2892 "position-set", !oldfmt.cs.text_position,
2893 "family", wp_get_font_name (oldfmt.font),
2894 "family-set", !oldfmt.cs.font,
2897 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2898 GTK_WINDOW (dialog), GTK_WINDOW (window));
2899 gtk_widget_show_all (dialog);
2900 priv->font_dialog = dialog;
2901 response = gtk_dialog_run (GTK_DIALOG (dialog));
2902 priv->font_dialog = NULL;
2903 if (response == GTK_RESPONSE_OK) {
2905 g_object_get( dialog,
2907 "bold-set", &bold_set,
2908 "underline", &underline,
2909 "underline-set", &underline_set,
2911 "italic-set", &italic_set,
2912 "strikethrough", &strikethrough,
2913 "strikethrough-set", &strikethrough_set,
2915 "color-set", &color_set,
2917 "size-set", &font_size_set,
2918 "family", &font_name,
2919 "family-set", &font_set,
2920 "position", &position,
2921 "position-set", &position_set,
2926 if (response == GTK_RESPONSE_OK) {
2927 memset(&fmt, 0, sizeof(fmt));
2933 fmt.italic = italic;
2934 fmt.cs.italic = TRUE;
2936 if (underline_set) {
2937 fmt.underline = underline;
2938 fmt.cs.underline = TRUE;
2940 if (strikethrough_set) {
2941 fmt.strikethrough = strikethrough;
2942 fmt.cs.strikethrough = TRUE;
2947 ? TEXT_POSITION_NORMAL
2948 : ( ( position == 1 )
2949 ? TEXT_POSITION_SUPERSCRIPT
2950 : TEXT_POSITION_SUBSCRIPT );
2951 fmt.cs.text_position = TRUE;
2952 fmt.font_size = oldfmt.font_size;
2956 fmt.cs.color = TRUE;
2959 fmt.font = wp_get_font_index(font_name,
2964 if (font_size_set) {
2965 fmt.cs.font_size = TRUE;
2966 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
2968 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2969 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2971 gtk_widget_destroy (dialog);
2973 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2977 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2979 ModestMsgEditWindowPrivate *priv;
2981 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2982 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2984 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2986 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2987 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2991 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
2993 ModestMsgEditWindowPrivate *priv;
2995 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2996 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2998 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
3000 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3001 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3006 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
3008 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3010 priv->can_undo = can_undo;
3014 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
3016 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3018 priv->can_redo = can_redo;
3022 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3024 ModestMsgEditWindowPrivate *priv;
3025 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3026 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3028 return priv->can_undo;
3032 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3034 ModestMsgEditWindowPrivate *priv;
3035 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3036 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3038 return priv->can_redo;
3043 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3046 GtkTextIter match_start, match_end;
3048 if (image_id == NULL)
3051 gtk_text_buffer_get_start_iter (buffer, &iter);
3053 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3054 GSList *tags = gtk_text_iter_get_tags (&match_start);
3056 for (node = tags; node != NULL; node = g_slist_next (node)) {
3057 GtkTextTag *tag = (GtkTextTag *) node->data;
3058 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3059 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3060 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3062 offset = gtk_text_iter_get_offset (&match_start);
3063 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3064 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3068 gtk_text_iter_forward_char (&iter);
3073 message_is_empty (ModestMsgEditWindow *window)
3075 ModestMsgEditWindowPrivate *priv = NULL;
3077 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3078 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3080 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3081 * so we can ignore markup.
3083 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3086 count = gtk_text_buffer_get_char_count (buf);
3092 msg_body_focus (GtkWidget *focus,
3093 GdkEventFocus *event,
3097 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3098 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3099 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3104 recpt_field_changed (GtkTextBuffer *buffer,
3105 ModestMsgEditWindow *editor)
3107 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3108 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3112 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3114 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3115 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3119 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3122 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3123 GtkTextBuffer *buffer;
3125 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3126 gtk_text_buffer_set_modified (buffer, modified);
3127 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3128 gtk_text_buffer_set_modified (buffer, modified);
3129 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3130 gtk_text_buffer_set_modified (buffer, modified);
3131 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3135 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3137 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3138 const char *account_name;
3139 GtkTextBuffer *buffer;
3141 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3142 if (gtk_text_buffer_get_modified (buffer))
3144 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3145 if (gtk_text_buffer_get_modified (buffer))
3147 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3148 if (gtk_text_buffer_get_modified (buffer))
3150 if (gtk_text_buffer_get_modified (priv->text_buffer))
3152 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3153 if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3164 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3166 ModestMsgEditWindowPrivate *priv = NULL;
3168 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3169 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3171 /* check if there's no recipient added */
3172 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3173 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3174 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3175 /* no recipient contents, then select contacts */
3176 modest_msg_edit_window_open_addressbook (window, NULL);
3180 g_object_ref (window);
3181 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3182 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3183 g_object_unref (window);
3186 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3187 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3188 g_object_unref (window);
3191 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3192 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3193 g_object_unref (window);
3197 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3198 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3199 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3200 g_object_unref (window);
3207 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3208 ModestMsgEditWindow *window)
3210 modest_msg_edit_window_offer_attach_file (window);
3214 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3216 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3218 return priv->clipboard_text;
3222 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3224 ModestMsgEditWindow *window)
3226 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3227 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3229 if (!GTK_WIDGET_VISIBLE (window))
3232 g_object_ref (window);
3233 text = gtk_clipboard_wait_for_text (selection_clipboard);
3235 if (priv->clipboard_text != NULL) {
3236 g_free (priv->clipboard_text);
3238 priv->clipboard_text = text;
3240 if (GTK_WIDGET_VISIBLE (window)) {
3241 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3243 g_object_unref (window);
3246 static gboolean clipboard_owner_change_idle (gpointer userdata)
3248 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3249 ModestMsgEditWindowPrivate *priv;
3251 gdk_threads_enter ();
3252 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3253 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3255 priv->clipboard_owner_idle = 0;
3256 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3257 gdk_threads_leave ();
3263 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3265 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3266 if (priv->clipboard_owner_idle == 0) {
3267 priv->clipboard_owner_idle = g_idle_add (clipboard_owner_change_idle, window);
3272 subject_field_move_cursor (GtkEntry *entry,
3273 GtkMovementStep step,
3278 if (!GTK_WIDGET_VISIBLE (window))
3281 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3285 update_window_title (ModestMsgEditWindow *window)
3287 ModestMsgEditWindowPrivate *priv = NULL;
3288 const gchar *subject;
3290 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3291 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3292 if (subject == NULL || subject[0] == '\0')
3293 subject = _("mail_va_new_email");
3295 gtk_window_set_title (GTK_WINDOW (window), subject);
3300 subject_field_changed (GtkEditable *editable,
3301 ModestMsgEditWindow *window)
3303 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3304 update_window_title (window);
3305 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3306 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3307 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3311 subject_field_insert_text (GtkEditable *editable,
3313 gint new_text_length,
3315 ModestMsgEditWindow *window)
3317 GString *result = g_string_new ("");
3319 gint result_len = 0;
3320 const gchar *entry_text = NULL;
3323 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3324 old_length = g_utf8_strlen (entry_text, -1);
3326 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3327 gunichar c = g_utf8_get_char_validated (current, 8);
3328 /* Invalid unichar, stop */
3334 result = g_string_append_unichar (result, c);
3338 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3339 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3342 /* Prevent endless recursion */
3343 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3344 g_signal_emit_by_name (editable, "insert-text",
3345 (gpointer) result->str, (gpointer) result->len,
3346 (gpointer) position, (gpointer) window);
3347 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3351 if (result_len + old_length > 1000) {
3352 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3353 _CS("ckdg_ib_maximum_characters_reached"));
3355 g_string_free (result, TRUE);
3359 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3362 ModestMsgEditWindowPrivate *priv = NULL;
3364 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3365 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3367 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3370 gtk_widget_show_all (priv->find_toolbar);
3371 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3373 gtk_widget_hide_all (priv->find_toolbar);
3374 gtk_widget_grab_focus (priv->msg_body);
3379 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3381 GtkTextIter *match_start,
3382 GtkTextIter *match_end)
3384 GtkTextIter end_iter;
3385 gchar *str_casefold;
3388 gchar *range_casefold;
3391 gboolean result = FALSE;
3398 gtk_text_iter_forward_to_end (&end_iter);
3400 str_casefold = g_utf8_casefold (str, -1);
3401 str_chars_n = strlen (str);
3403 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3404 range_casefold = g_utf8_casefold (range_text, -1);
3405 range_chars_n = strlen (range_casefold);
3407 if (range_chars_n < str_chars_n) {
3408 g_free (str_casefold);
3409 g_free (range_text);
3410 g_free (range_casefold);
3414 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3415 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3416 if (!g_utf8_collate (range_subtext, str_casefold)) {
3417 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3419 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3420 match_start, match_end, NULL);
3421 g_free (found_text);
3423 g_free (range_subtext);
3427 g_free (str_casefold);
3428 g_free (range_text);
3429 g_free (range_casefold);
3436 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3437 ModestMsgEditWindow *window)
3439 gchar *current_search = NULL;
3440 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3442 GtkTextIter selection_start, selection_end;
3443 GtkTextIter match_start, match_end;
3444 gboolean continue_search = FALSE;
3446 if (message_is_empty (window)) {
3447 g_free (priv->last_search);
3448 priv->last_search = NULL;
3449 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3453 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3454 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3455 g_free (current_search);
3456 g_free (priv->last_search);
3457 priv->last_search = NULL;
3458 /* Information banner about empty search */
3459 hildon_banner_show_information (NULL, NULL, _CS("ecdg_ib_find_rep_enter_text"));
3463 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3464 continue_search = TRUE;
3466 g_free (priv->last_search);
3467 priv->last_search = g_strdup (current_search);
3470 if (continue_search) {
3471 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3472 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3473 &match_start, &match_end);
3475 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_search_complete"));
3477 GtkTextIter buffer_start;
3478 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3479 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3480 &match_start, &match_end);
3482 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_no_matches"));
3485 /* Mark as selected the string found in search */
3487 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3488 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3489 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3491 g_free (priv->last_search);
3492 priv->last_search = NULL;
3494 g_free (current_search);
3498 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3500 ModestMsgEditWindowPrivate *priv;
3502 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3507 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3510 ModestMsgEditWindowPrivate *priv;
3512 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3517 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3518 ModestMsgEditWindow *window)
3520 modest_msg_edit_window_toggle_find_toolbar (window, FALSE);
3524 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3527 ModestMsgEditWindowPrivate *priv;
3528 TnyHeader *header = NULL;
3530 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3531 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3533 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3534 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3536 if (priv->draft_msg != NULL) {
3537 g_object_unref (priv->draft_msg);
3540 if (draft != NULL) {
3541 g_object_ref (draft);
3542 header = tny_msg_get_header (draft);
3543 if (priv->msg_uid) {
3544 g_free (priv->msg_uid);
3545 priv->msg_uid = NULL;
3547 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3548 if (GTK_WIDGET_REALIZED (window)) {
3549 if (!modest_window_mgr_register_window (mgr, MODEST_WINDOW (window), NULL)) {
3550 gtk_widget_destroy (GTK_WIDGET (window));
3556 priv->draft_msg = draft;
3560 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3561 GtkTextIter *start, GtkTextIter *end,
3564 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3565 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3568 if (tag == NULL) return;
3569 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3570 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3571 replace_with_images (window, priv->images);
3576 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3579 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3581 g_return_if_fail (TNY_IS_MIME_PART (part));
3582 tny_list_prepend (priv->attachments, (GObject *) part);
3583 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3584 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3585 gtk_widget_show_all (priv->attachments_caption);
3586 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3590 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3592 ModestMsgEditWindowPrivate *priv;
3594 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3595 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3597 return priv->msg_uid;
3601 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3602 ModestMsgEditWindowWidgetType widget_type)
3604 ModestMsgEditWindowPrivate *priv;
3606 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3607 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3609 switch (widget_type) {
3610 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3611 return priv->msg_body;
3613 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3614 return priv->to_field;
3616 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3617 return priv->cc_field;
3619 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3620 return priv->bcc_field;
3622 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3623 return priv->subject_field;
3625 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3626 return priv->attachments_view;
3634 remove_tags (WPTextBuffer *buffer)
3636 GtkTextIter start, end;
3638 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3639 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3641 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3645 on_account_removed (TnyAccountStore *account_store,
3646 TnyAccount *account,
3649 /* Do nothing if it's a store account, because we use the
3650 transport to send the messages */
3651 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3652 const gchar *parent_acc = NULL;
3653 const gchar *our_acc = NULL;
3655 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3656 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3657 /* Close this window if I'm showing a message of the removed account */
3658 if (strcmp (parent_acc, our_acc) == 0)
3659 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3664 from_field_changed (HildonPickerButton *button,
3665 ModestMsgEditWindow *self)
3667 ModestMsgEditWindowPrivate *priv;
3668 gboolean has_old_signature, has_new_signature;
3670 GtkTextIter match_start, match_end;
3671 ModestAccountMgr *mgr;
3673 gchar *full_signature;
3675 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3677 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
3678 mgr = modest_runtime_get_account_mgr ();
3679 signature = modest_account_mgr_get_signature (mgr, priv->last_from_account, &has_old_signature);
3680 if (has_old_signature) {
3681 full_signature = g_strconcat ("\n--\n", signature, NULL);
3682 if (gtk_text_iter_forward_search (&iter, full_signature, 0, &match_start, &match_end, NULL)) {
3683 gtk_text_buffer_delete (priv->text_buffer, &match_start, &match_end);
3685 } else if (gtk_text_iter_forward_search (&iter, _("mcen_ia_editor_original_message"), 0,
3686 &match_start, &match_end, NULL)) {
3689 g_free (full_signature);
3693 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3694 signature = modest_account_mgr_get_signature (mgr, priv->last_from_account, &has_new_signature);
3695 if (has_new_signature) {
3696 full_signature = g_strconcat ("\n--\n", signature, NULL);
3697 gtk_text_buffer_insert (priv->text_buffer, &iter, full_signature, -1);
3698 g_free (full_signature);
3703 typedef struct _MessageSettingsHelper {
3704 ModestMsgEditWindow *window;
3705 GSList *priority_group;
3706 GSList *format_group;
3707 GtkToggleButton *current_priority;
3708 GtkToggleButton *current_format;
3709 } MessageSettingsHelper;
3712 on_priority_toggle (GtkToggleButton *button,
3713 MessageSettingsHelper *helper)
3716 ModestMsgEditWindowPrivate *priv;
3718 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3719 if (gtk_toggle_button_get_active (button)) {
3721 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3722 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3723 if ((node_button != button) &&
3724 gtk_toggle_button_get_active (node_button)) {
3725 gtk_toggle_button_set_active (node_button, FALSE);
3728 helper->current_priority = button;
3730 gboolean found = FALSE;
3731 /* If no one is active, activate it again */
3732 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3733 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3734 if (gtk_toggle_button_get_active (node_button)) {
3740 gtk_toggle_button_set_active (button, TRUE);
3746 on_format_toggle (GtkToggleButton *button,
3747 MessageSettingsHelper *helper)
3750 ModestMsgEditWindowPrivate *priv;
3752 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3753 if (gtk_toggle_button_get_active (button)) {
3755 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
3756 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3757 if ((node_button != button) &&
3758 gtk_toggle_button_get_active (node_button)) {
3759 gtk_toggle_button_set_active (node_button, FALSE);
3762 helper->current_format = button;
3764 gboolean found = FALSE;
3765 /* If no one is active, activate it again */
3766 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
3767 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3768 if (gtk_toggle_button_get_active (node_button)) {
3774 gtk_toggle_button_set_active (button, TRUE);
3781 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
3785 GtkWidget *priority_hbox;
3786 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
3787 GtkWidget *captioned;
3788 GtkSizeGroup *title_sizegroup, *value_sizegroup;
3789 GtkWidget *format_hbox;
3790 GtkWidget *html_toggle, *text_toggle;
3791 ModestMsgEditWindowPrivate *priv;
3792 MessageSettingsHelper helper = {0,};
3794 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3795 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3796 helper.window = window;
3797 helper.priority_group = NULL;
3799 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3800 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3802 dialog = gtk_dialog_new_with_buttons (_("mcen_me_message_settings"), NULL,
3803 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
3804 _HL("wdgt_bd_done"), GTK_RESPONSE_ACCEPT, NULL);
3805 vbox = gtk_vbox_new (FALSE, 0);
3806 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), vbox);
3807 gtk_widget_show (vbox);
3809 /* Priority toggles */
3810 priority_hbox = gtk_hbox_new (TRUE, 0);
3811 high_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3812 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
3813 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
3814 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
3815 medium_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3816 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
3817 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
3818 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
3819 low_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3820 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
3821 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
3822 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
3823 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, TRUE, TRUE, 0);
3824 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, TRUE, TRUE, 0);
3825 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, TRUE, TRUE, 0);
3826 gtk_widget_show_all (priority_hbox);
3827 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
3828 _("mcen_me_editor_message_priority"), FALSE, priority_hbox);
3829 gtk_widget_show (captioned);
3830 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
3832 /* format toggles */
3833 format_hbox = gtk_hbox_new (TRUE, 0);
3834 html_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3835 gtk_button_set_label (GTK_BUTTON (html_toggle), _("mcen_me_editor_formatted_text"));
3836 helper.format_group = g_slist_prepend (helper.format_group, html_toggle);
3837 g_object_set_data (G_OBJECT (html_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_HTML));
3838 g_object_set_data (G_OBJECT (html_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_FORMATTED_TEXT));
3839 text_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3840 gtk_button_set_label (GTK_BUTTON (text_toggle), _("mcen_me_editor_plain_text"));
3841 helper.format_group = g_slist_prepend (helper.format_group, text_toggle);
3842 g_object_set_data (G_OBJECT (text_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_TEXT));
3843 g_object_set_data (G_OBJECT (text_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_PLAIN_TEXT));
3844 gtk_box_pack_start (GTK_BOX (format_hbox), html_toggle, TRUE, TRUE, 0);
3845 gtk_box_pack_start (GTK_BOX (format_hbox), text_toggle, TRUE, TRUE, 0);
3846 gtk_widget_show_all (format_hbox);
3847 gtk_widget_show (format_hbox);
3848 gtk_box_pack_start (GTK_BOX (vbox), format_hbox, FALSE, FALSE, 0);
3851 g_object_unref (title_sizegroup);
3852 g_object_unref (value_sizegroup);
3854 /* Set current values */
3855 switch (priv->priority_flags) {
3856 case TNY_HEADER_FLAG_HIGH_PRIORITY:
3857 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (high_toggle), TRUE);
3858 helper.current_priority = GTK_TOGGLE_BUTTON (high_toggle);
3860 case TNY_HEADER_FLAG_LOW_PRIORITY:
3861 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (low_toggle), TRUE);
3862 helper.current_priority = GTK_TOGGLE_BUTTON (low_toggle);
3865 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (medium_toggle), TRUE);
3866 helper.current_priority = GTK_TOGGLE_BUTTON (medium_toggle);
3870 switch (modest_msg_edit_window_get_format (window)) {
3871 case MODEST_MSG_EDIT_FORMAT_TEXT:
3872 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_toggle), TRUE);
3873 helper.current_format = GTK_TOGGLE_BUTTON (text_toggle);
3875 case MODEST_MSG_EDIT_FORMAT_HTML:
3877 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (html_toggle), TRUE);
3878 helper.current_format = GTK_TOGGLE_BUTTON (html_toggle);
3882 /* Signal connects */
3883 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3884 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3885 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3886 g_signal_connect (G_OBJECT (html_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
3887 g_signal_connect (G_OBJECT (text_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
3889 /* Save settings if the user clicked on done */
3890 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
3891 TnyHeaderFlags flags;
3892 ModestMsgEditFormat old_format, new_format;
3894 /* Set priority flags */
3895 flags = (TnyHeaderFlags) g_object_get_data (G_OBJECT (helper.current_priority), "priority");
3896 if (priv->priority_flags != flags)
3897 modest_msg_edit_window_set_priority_flags (window, flags);
3899 /* Set edit format */
3900 old_format = modest_msg_edit_window_get_format (window);
3901 new_format = (ModestMsgEditFormat) g_object_get_data (G_OBJECT (helper.current_format), "format");
3902 if (old_format != new_format) {
3903 gint file_format = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (helper.current_format), "file-format"));
3904 modest_msg_edit_window_set_file_format (window, file_format);
3908 gtk_widget_destroy (dialog);
3909 g_slist_free (helper.priority_group);
3913 on_message_settings (GtkAction *action,
3914 ModestMsgEditWindow *window)
3916 modest_msg_edit_window_show_msg_settings_dialog (window);
3920 on_cc_button_toggled (HildonCheckButton *button,
3921 ModestMsgEditWindow *window)
3923 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
3925 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
3926 hildon_check_button_get_active (button));
3930 on_bcc_button_toggled (HildonCheckButton *button,
3931 ModestMsgEditWindow *window)
3933 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
3935 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
3936 hildon_check_button_get_active (button));
3940 setup_menu (ModestMsgEditWindow *self)
3942 ModestMsgEditWindowPrivate *priv = NULL;
3944 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
3946 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3948 /* Settings menu buttons */
3949 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_checknames"), NULL,
3950 APP_MENU_CALLBACK (modest_ui_actions_on_check_names),
3952 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_undo"), "<Ctrl>z",
3953 APP_MENU_CALLBACK (modest_ui_actions_on_undo),
3954 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_undo));
3956 priv->cc_button = hildon_check_button_new (0);
3957 gtk_button_set_label (GTK_BUTTON (priv->cc_button), _("mcen_me_editor_showcc"));
3958 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button),
3960 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->cc_button),
3962 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
3963 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
3964 priv->bcc_button = hildon_check_button_new (0);
3965 gtk_button_set_label (GTK_BUTTON (priv->bcc_button), _("mcen_me_editor_showbcc"));
3966 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button),
3968 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->bcc_button),
3970 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
3971 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
3973 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_attach_inlineimage"), NULL,
3974 APP_MENU_CALLBACK (modest_ui_actions_on_insert_image),
3975 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_set_style));
3976 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_remove_attachments"), NULL,
3977 APP_MENU_CALLBACK (modest_ui_actions_on_remove_attachments),
3978 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
3979 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_message_settings"), NULL,
3980 APP_MENU_CALLBACK (on_message_settings),
3982 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_viewer_find"), "<Ctrl>f",
3983 APP_MENU_CALLBACK (modest_ui_actions_on_toggle_find_in_page),