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
92 static gboolean is_wp_text_buffer_started = FALSE;
94 static void modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass);
95 static void modest_msg_edit_window_init (ModestMsgEditWindow *obj);
96 static void modest_msg_edit_window_finalize (GObject *obj);
98 static gboolean msg_body_focus (GtkWidget *focus, GdkEventFocus *event, gpointer userdata);
99 static void body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
100 static void recpt_field_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
102 static void text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window);
103 static void text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window);
104 static void text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window);
105 static void text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
106 GtkTextIter *start, GtkTextIter *end,
108 static void text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id);
109 static void subject_field_changed (GtkEditable *editable, ModestMsgEditWindow *window);
110 static void subject_field_insert_text (GtkEditable *editable,
112 gint new_text_length,
114 ModestMsgEditWindow *window);
115 static void modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
117 static void modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
119 static void modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
121 static void modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
123 static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
124 ModestRecptEditor *editor);
125 static void modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
126 ModestMsgEditWindow *window);
128 /* ModestWindow methods implementation */
129 static void modest_msg_edit_window_disconnect_signals (ModestWindow *window);
130 static void modest_msg_edit_window_show_toolbar (ModestWindow *window,
131 gboolean show_toolbar);
132 static void modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
134 ModestMsgEditWindow *window);
135 static void modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window);
136 static void subject_field_move_cursor (GtkEntry *entry,
137 GtkMovementStep step,
141 static void update_window_title (ModestMsgEditWindow *window);
144 static void modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
145 ModestMsgEditWindow *window);
146 static void modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
147 ModestMsgEditWindow *window);
148 static gboolean gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
150 GtkTextIter *match_start,
151 GtkTextIter *match_end);
153 static void remove_tags (WPTextBuffer *buffer);
155 static void on_account_removed (TnyAccountStore *account_store,
159 static void init_window (ModestMsgEditWindow *obj);
161 gboolean scroll_drag_timeout (gpointer userdata);
162 static void correct_scroll (ModestMsgEditWindow *w);
163 static void correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused);
164 static void text_buffer_end_user_action (GtkTextBuffer *buffer,
165 ModestMsgEditWindow *userdata);
166 static void text_buffer_mark_set (GtkTextBuffer *buffer,
169 ModestMsgEditWindow *userdata);
170 static void on_message_settings (GtkAction *action,
171 ModestMsgEditWindow *window);
172 static void setup_menu (ModestMsgEditWindow *self);
174 static void DEBUG_BUFFER (WPTextBuffer *buffer)
178 g_message ("BEGIN BUFFER OF SIZE %d", gtk_text_buffer_get_char_count (GTK_TEXT_BUFFER (buffer)));
180 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &iter);
181 while (!gtk_text_iter_is_end (&iter)) {
182 GString *output = g_string_new ("");
183 GSList *toggled_tags;
186 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
187 g_string_append_printf (output, "%d: CLOSED [ ", gtk_text_iter_get_offset (&iter));
188 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
189 GtkTextTag *tag = (GtkTextTag *) node->data;
191 g_object_get (G_OBJECT (tag), "name", &name, NULL);
192 output = g_string_append (output, name);
193 g_string_append (output, " ");
195 output = g_string_append (output, "] OPENED [ ");
196 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
197 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
198 GtkTextTag *tag = (GtkTextTag *) node->data;
200 g_object_get (G_OBJECT (tag), "name", &name, NULL);
201 output = g_string_append (output, name);
202 g_string_append (output, " ");
204 output = g_string_append (output, "]\n");
205 g_message ("%s", output->str);
206 g_string_free (output, TRUE);
207 gtk_text_iter_forward_to_tag_toggle (&iter, NULL);
209 g_message ("END BUFFER");
213 static const GtkActionEntry hildon2_msg_edit_action_entries [] = {
214 { "MessageSettings", NULL, N_("mcen_me_message_settings"), NULL, NULL, G_CALLBACK (on_message_settings)},
218 /* static gboolean */
219 /* on_key_pressed (GtkWidget *self, */
220 /* GdkEventKey *event, */
221 /* gpointer user_data); */
223 /* list my signals */
230 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
231 struct _ModestMsgEditWindowPrivate {
234 GtkWidget *header_box;
236 ModestPairList *from_field_protos;
237 GtkWidget *from_field;
238 gchar *original_account_name;
242 GtkWidget *bcc_field;
243 GtkWidget *subject_field;
244 GtkWidget *attachments_view;
245 GtkWidget *priority_icon;
246 GtkWidget *add_attachment_button;
248 GtkWidget *cc_caption;
249 GtkWidget *bcc_caption;
250 gboolean update_caption_visibility;
251 GtkWidget *attachments_caption;
253 GtkTextBuffer *text_buffer;
255 GtkWidget *font_size_toolitem;
256 GtkWidget *font_face_toolitem;
257 GtkWidget *font_color_button;
258 GtkWidget *font_color_toolitem;
259 GSList *font_items_group;
260 GtkWidget *font_tool_button_label;
261 GSList *size_items_group;
262 GtkWidget *size_tool_button_label;
264 GtkWidget *find_toolbar;
267 GtkWidget *font_dialog;
270 guint scroll_drag_timeout_id;
274 TnyList *attachments;
279 TnyHeaderFlags priority_flags;
281 gboolean can_undo, can_redo;
282 gulong clipboard_change_handler_id;
283 gulong default_clipboard_change_handler_id;
284 gulong account_removed_handler_id;
285 guint clipboard_owner_idle;
286 gchar *clipboard_text;
295 GtkWidget *cc_button;
296 GtkWidget *bcc_button;
297 GtkWidget *find_toolbar_button;
300 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
301 MODEST_TYPE_MSG_EDIT_WINDOW, \
302 ModestMsgEditWindowPrivate))
304 static GtkWindowClass *parent_class = NULL;
306 /* uncomment the following if you have defined any signals */
307 /* static guint signals[LAST_SIGNAL] = {0}; */
310 modest_msg_edit_window_get_type (void)
312 static GType my_type = 0;
314 static const GTypeInfo my_info = {
315 sizeof(ModestMsgEditWindowClass),
316 NULL, /* base init */
317 NULL, /* base finalize */
318 (GClassInitFunc) modest_msg_edit_window_class_init,
319 NULL, /* class finalize */
320 NULL, /* class data */
321 sizeof(ModestMsgEditWindow),
323 (GInstanceInitFunc) modest_msg_edit_window_init,
326 my_type = g_type_register_static (MODEST_TYPE_HILDON2_WINDOW,
327 "ModestMsgEditWindow",
335 save_state (ModestWindow *self)
337 modest_widget_memory_save (modest_runtime_get_conf(),
338 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
343 restore_settings (ModestMsgEditWindow *self)
345 ModestConf *conf = NULL;
347 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
349 conf = modest_runtime_get_conf ();
351 /* Dim at start clipboard actions */
352 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
353 gtk_action_set_sensitive (action, FALSE);
354 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
355 gtk_action_set_sensitive (action, FALSE);
356 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
357 gtk_action_set_sensitive (action, FALSE);
359 modest_widget_memory_restore (conf, G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
364 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
366 GObjectClass *gobject_class;
367 ModestWindowClass *modest_window_class;
368 gobject_class = (GObjectClass*) klass;
369 modest_window_class = (ModestWindowClass*) klass;
371 parent_class = g_type_class_peek_parent (klass);
372 gobject_class->finalize = modest_msg_edit_window_finalize;
374 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
375 modest_window_class->save_state_func = save_state;
376 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
378 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
382 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
384 ModestMsgEditWindowPrivate *priv;
385 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
387 priv->msg_body = NULL;
389 priv->from_field = NULL;
390 priv->to_field = NULL;
391 priv->cc_field = NULL;
392 priv->bcc_field = NULL;
393 priv->subject_field = NULL;
394 priv->attachments = TNY_LIST (tny_simple_list_new ());
395 priv->images = TNY_LIST (tny_simple_list_new ());
396 priv->images_size = 0;
397 priv->images_count = 0;
400 priv->cc_caption = NULL;
401 priv->bcc_caption = NULL;
402 priv->update_caption_visibility = FALSE;
404 priv->priority_flags = 0;
406 priv->find_toolbar = NULL;
407 priv->last_search = NULL;
409 priv->draft_msg = NULL;
410 priv->outbox_msg = NULL;
411 priv->msg_uid = NULL;
413 priv->can_undo = FALSE;
414 priv->can_redo = FALSE;
415 priv->clipboard_change_handler_id = 0;
416 priv->default_clipboard_change_handler_id = 0;
417 priv->account_removed_handler_id = 0;
418 priv->clipboard_owner_idle = 0;
419 priv->clipboard_text = NULL;
422 priv->scroll_drag_timeout_id = 0;
423 priv->last_upper = 0.0;
425 priv->font_dialog = NULL;
426 priv->app_menu = NULL;
428 if (!is_wp_text_buffer_started) {
429 is_wp_text_buffer_started = TRUE;
430 wp_text_buffer_library_init ();
435 hildon_program_add_window (hildon_program_get_instance(),
441 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
443 static ModestPairList*
444 get_transports (void)
446 GSList *transports = NULL;
448 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
449 GSList *accounts = modest_account_mgr_account_names (account_mgr,
450 TRUE /* only enabled accounts. */);
452 GSList *cursor = accounts;
454 gchar *account_name = cursor->data;
455 gchar *from_string = NULL;
457 from_string = modest_account_mgr_get_from_string (account_mgr,
461 if (from_string && account_name) {
462 gchar *name = account_name;
463 ModestPair *pair = modest_pair_new ((gpointer) name,
464 (gpointer) from_string , TRUE);
465 transports = g_slist_prepend (transports, pair);
468 cursor = cursor->next;
470 g_slist_free (accounts); /* only free the accounts, not the elements,
471 * because they are used in the pairlist */
475 static void window_focus (GtkWindow *window,
479 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
483 scroll_drag_timeout (gpointer userdata)
485 ModestMsgEditWindow *win = (ModestMsgEditWindow *) userdata;
486 ModestMsgEditWindowPrivate *priv;
488 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(win);
490 correct_scroll_without_drag_check (win, TRUE);
492 priv->scroll_drag_timeout_id = 0;
498 correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused)
500 ModestMsgEditWindowPrivate *priv;
503 GdkRectangle rectangle;
507 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
509 if (only_if_focused && !gtk_widget_is_focus (priv->msg_body))
512 insert = gtk_text_buffer_get_insert (priv->text_buffer);
513 gtk_text_buffer_get_iter_at_mark (priv->text_buffer, &iter, insert);
515 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &iter, &rectangle);
516 offset = priv->msg_body->allocation.y;
518 new_value = (offset + rectangle.y);
520 hildon_pannable_area_jump_to (HILDON_PANNABLE_AREA (priv->pannable), -1, new_value);
524 correct_scroll (ModestMsgEditWindow *w)
526 ModestMsgEditWindowPrivate *priv;
528 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
529 if (gtk_grab_get_current () == priv->msg_body) {
530 if (priv->scroll_drag_timeout_id == 0) {
531 priv->scroll_drag_timeout_id = g_timeout_add (500, (GSourceFunc) scroll_drag_timeout,
537 correct_scroll_without_drag_check (w, TRUE);
541 text_buffer_end_user_action (GtkTextBuffer *buffer,
542 ModestMsgEditWindow *userdata)
545 correct_scroll (userdata);
549 text_buffer_mark_set (GtkTextBuffer *buffer,
552 ModestMsgEditWindow *userdata)
554 gtk_text_buffer_begin_user_action (buffer);
555 gtk_text_buffer_end_user_action (buffer);
559 cut_clipboard_check (GtkTextView *text_view,
562 GtkTextBuffer *buffer;
564 buffer = gtk_text_view_get_buffer (text_view);
565 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
566 g_signal_stop_emission_by_name ((gpointer )text_view, "cut-clipboard");
571 copy_clipboard_check (GtkTextView *text_view,
574 GtkTextBuffer *buffer;
576 buffer = gtk_text_view_get_buffer (text_view);
577 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
578 g_signal_stop_emission_by_name ((gpointer )text_view, "copy-clipboard");
583 attachment_deleted (ModestAttachmentsView *attachments_view,
586 modest_msg_edit_window_remove_attachments (MODEST_MSG_EDIT_WINDOW (user_data),
591 connect_signals (ModestMsgEditWindow *obj)
593 ModestMsgEditWindowPrivate *priv;
595 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
597 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
598 G_CALLBACK (text_buffer_refresh_attributes), obj);
599 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
600 G_CALLBACK (text_buffer_can_undo), obj);
601 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
602 G_CALLBACK (text_buffer_can_redo), obj);
603 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
604 G_CALLBACK (body_changed), obj);
605 g_signal_connect (G_OBJECT (priv->text_buffer), "modified-changed",
606 G_CALLBACK (body_changed), obj);
607 g_signal_connect (G_OBJECT (priv->text_buffer), "end-user-action",
608 G_CALLBACK (text_buffer_end_user_action), obj);
609 g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
610 G_CALLBACK (text_buffer_mark_set), obj);
611 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
612 G_CALLBACK (text_buffer_apply_tag), obj);
613 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
614 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
615 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
616 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
617 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
618 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
620 g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
621 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
623 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
624 G_CALLBACK (msg_body_focus), obj);
625 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
626 G_CALLBACK (msg_body_focus), obj);
627 g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
628 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
629 "changed", G_CALLBACK (recpt_field_changed), obj);
630 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
631 "changed", G_CALLBACK (recpt_field_changed), obj);
632 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
633 "changed", G_CALLBACK (recpt_field_changed), obj);
634 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
635 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
636 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
638 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
639 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
641 priv->clipboard_change_handler_id =
642 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
643 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
644 priv->default_clipboard_change_handler_id =
645 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
646 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
648 g_signal_connect (G_OBJECT (priv->msg_body), "cut-clipboard", G_CALLBACK (cut_clipboard_check), NULL);
649 g_signal_connect (G_OBJECT (priv->msg_body), "copy-clipboard", G_CALLBACK (copy_clipboard_check), NULL);
650 g_signal_connect (G_OBJECT (priv->attachments_view), "delete", G_CALLBACK (attachment_deleted), obj);
654 init_wp_text_view_style ()
656 static gboolean initialized = FALSE;
659 gtk_rc_parse_string ("class \"WPTextView\" style \"fremantle-textview\"");
665 init_window (ModestMsgEditWindow *obj)
667 GtkWidget *to_caption, *subject_caption;
668 GtkWidget *main_vbox;
669 ModestMsgEditWindowPrivate *priv;
670 GtkActionGroup *action_group;
671 ModestWindowPrivate *parent_priv;
672 GdkPixbuf *window_icon = NULL;
673 GError *error = NULL;
675 GtkSizeGroup *title_size_group;
676 GtkSizeGroup *value_size_group;
677 GtkWidget *subject_box;
678 GtkWidget *attachment_icon;
679 GtkWidget *window_box;
680 #if (GTK_MINOR_VERSION >= 10)
681 GdkAtom deserialize_type;
684 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
685 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
687 parent_priv->ui_manager = gtk_ui_manager_new();
688 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
689 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
691 /* Add common actions */
692 gtk_action_group_add_actions (action_group,
693 modest_msg_edit_action_entries,
694 G_N_ELEMENTS (modest_msg_edit_action_entries),
696 gtk_action_group_add_actions (action_group,
697 hildon2_msg_edit_action_entries,
698 G_N_ELEMENTS (hildon2_msg_edit_action_entries),
700 gtk_action_group_add_toggle_actions (action_group,
701 modest_msg_edit_toggle_action_entries,
702 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
704 gtk_action_group_add_radio_actions (action_group,
705 modest_msg_edit_alignment_radio_action_entries,
706 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
708 G_CALLBACK (modest_ui_actions_on_change_justify),
710 gtk_action_group_add_radio_actions (action_group,
711 modest_msg_edit_priority_action_entries,
712 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
714 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
716 gtk_action_group_add_radio_actions (action_group,
717 modest_msg_edit_file_format_action_entries,
718 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
719 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
720 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
722 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
723 g_object_unref (action_group);
725 /* Load the UI definition */
726 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
729 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
730 g_clear_error (&error);
733 /* Add accelerators */
734 gtk_window_add_accel_group (GTK_WINDOW (obj),
735 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
737 parent_priv->menubar = NULL;
739 title_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
740 value_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
742 /* Note: This ModestPairList* must exist for as long as the picker
743 * that uses it, because the ModestSelectorPicker uses the ID opaquely,
744 * so it can't know how to manage its memory. */
745 priv->from_field = modest_selector_picker_new (MODEST_EDITABLE_SIZE,
746 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL,
748 modest_maemo_utils_set_hbutton_layout (title_size_group, value_size_group,
749 _("mail_va_from"), priv->from_field);
751 priv->to_field = modest_recpt_editor_new ();
752 priv->cc_field = modest_recpt_editor_new ();
753 priv->bcc_field = modest_recpt_editor_new ();
754 subject_box = gtk_hbox_new (FALSE, 0);
755 priv->priority_icon = gtk_image_new ();
756 gtk_box_pack_start (GTK_BOX (subject_box), priv->priority_icon, FALSE, FALSE, 0);
757 priv->subject_field = hildon_entry_new (MODEST_EDITABLE_SIZE);
758 gtk_entry_set_max_length (GTK_ENTRY (priv->subject_field) ,SUBJECT_MAX_LENGTH);
759 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
760 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
761 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
762 gtk_box_pack_start (GTK_BOX (subject_box), priv->subject_field, TRUE, TRUE, 0);
763 priv->add_attachment_button = gtk_button_new ();
764 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
765 gtk_button_set_relief (GTK_BUTTON (priv->add_attachment_button), GTK_RELIEF_NONE);
766 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
767 gtk_button_set_alignment (GTK_BUTTON (priv->add_attachment_button), 1.0, 0.5);
768 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, HILDON_ICON_SIZE_FINGER);
769 gtk_container_add (GTK_CONTAINER (priv->add_attachment_button), attachment_icon);
770 gtk_box_pack_start (GTK_BOX (subject_box), priv->add_attachment_button, FALSE, FALSE, 0);
771 priv->attachments_view = modest_attachments_view_new (NULL);
773 priv->header_box = gtk_vbox_new (FALSE, 0);
775 to_caption = modest_maemo_utils_create_captioned_with_size_type
776 (title_size_group, value_size_group,
777 _("mail_va_to"), priv->to_field,
778 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
779 priv->cc_caption = modest_maemo_utils_create_captioned_with_size_type
780 (title_size_group, value_size_group,
781 _("mail_va_cc"), priv->cc_field,
782 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
783 priv->bcc_caption = modest_maemo_utils_create_captioned_with_size_type
784 (title_size_group, value_size_group,
785 _("mail_va_hotfix1"), priv->bcc_field,
786 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
787 subject_caption = modest_maemo_utils_create_captioned (title_size_group, value_size_group,
788 _("mail_va_subject"), subject_box);
789 priv->attachments_caption = modest_maemo_utils_create_captioned_with_size_type (title_size_group, value_size_group,
790 _("mail_va_attachment"),
791 priv->attachments_view,
792 HILDON_SIZE_AUTO_WIDTH |
793 HILDON_SIZE_AUTO_HEIGHT);
794 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), value_size_group); */
795 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), value_size_group); */
796 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), value_size_group); */
797 g_object_unref (title_size_group);
798 g_object_unref (value_size_group);
800 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->from_field, FALSE, FALSE, 0);
801 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
802 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
803 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
804 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
805 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
806 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
808 init_wp_text_view_style ();
810 priv->msg_body = wp_text_view_new ();
813 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
814 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
815 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
816 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
817 #if (GTK_MINOR_VERSION >= 10)
818 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
819 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
821 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
822 deserialize_type, TRUE);
824 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
826 priv->find_toolbar = hildon_find_toolbar_new (NULL);
827 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
829 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
831 priv->pannable = hildon_pannable_area_new ();
833 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
835 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
836 priv->frame = gtk_frame_new (NULL);
837 gtk_box_pack_start (GTK_BOX(main_vbox), priv->frame, TRUE, TRUE, 0);
839 hildon_pannable_area_add_with_viewport (HILDON_PANNABLE_AREA (priv->pannable), main_vbox);
840 gtk_widget_show_all (GTK_WIDGET(priv->pannable));
842 window_box = gtk_vbox_new (FALSE, 0);
843 gtk_container_add (GTK_CONTAINER(obj), window_box);
845 gtk_box_pack_start (GTK_BOX (window_box), priv->pannable, TRUE, TRUE, 0);
847 gtk_container_add (GTK_CONTAINER (priv->frame), priv->msg_body);
849 /* Set window icon */
850 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
852 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
853 g_object_unref (window_icon);
858 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
860 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
862 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
863 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
864 priv->clipboard_change_handler_id))
865 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
866 priv->clipboard_change_handler_id);
867 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
868 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
869 priv->default_clipboard_change_handler_id))
870 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
871 priv->default_clipboard_change_handler_id);
873 if (priv->account_removed_handler_id &&
874 g_signal_handler_is_connected (modest_runtime_get_account_store (),
875 priv->account_removed_handler_id))
876 g_signal_handler_disconnect(modest_runtime_get_account_store (),
877 priv->account_removed_handler_id);
881 modest_msg_edit_window_finalize (GObject *obj)
883 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
885 /* Sanity check: shouldn't be needed, the window mgr should
886 call this function before */
887 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
889 if (priv->font_dialog != NULL) {
890 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
893 if (priv->clipboard_text != NULL) {
894 g_free (priv->clipboard_text);
895 priv->clipboard_text = NULL;
898 if (priv->draft_msg != NULL) {
899 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
900 if (TNY_IS_HEADER (header)) {
901 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
902 modest_window_mgr_unregister_header (mgr, header);
904 g_object_unref (priv->draft_msg);
905 priv->draft_msg = NULL;
907 if (priv->outbox_msg != NULL) {
908 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
909 if (TNY_IS_HEADER (header)) {
910 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
911 modest_window_mgr_unregister_header (mgr, header);
913 g_object_unref (priv->outbox_msg);
914 priv->outbox_msg = NULL;
916 if (priv->scroll_drag_timeout_id > 0) {
917 g_source_remove (priv->scroll_drag_timeout_id);
918 priv->scroll_drag_timeout_id = 0;
920 if (priv->clipboard_owner_idle > 0) {
921 g_source_remove (priv->clipboard_owner_idle);
922 priv->clipboard_owner_idle = 0;
924 if (priv->original_account_name)
925 g_free (priv->original_account_name);
926 g_free (priv->msg_uid);
927 g_free (priv->last_search);
928 g_slist_free (priv->font_items_group);
929 g_slist_free (priv->size_items_group);
930 g_object_unref (priv->attachments);
931 g_object_unref (priv->images);
933 /* This had to stay alive for as long as the picker that used it: */
934 modest_pair_list_free (priv->from_field_protos);
936 G_OBJECT_CLASS(parent_class)->finalize (obj);
940 pixbuf_from_stream (TnyStream *stream, const gchar *mime_type, guint64 *stream_size)
942 GdkPixbufLoader *loader;
948 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
950 if (loader == NULL) {
956 tny_stream_reset (TNY_STREAM (stream));
957 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
958 GError *error = NULL;
959 unsigned char read_buffer[128];
961 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
963 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
965 g_error_free (error);
970 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
972 g_object_ref (pixbuf);
973 gdk_pixbuf_loader_close (loader, NULL);
974 g_object_unref (loader);
979 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
980 GdkPixbuf *new_pixbuf;
982 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
983 gdk_pixbuf_get_width (pixbuf);
984 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
985 g_object_unref (pixbuf);
996 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
998 ModestMsgEditWindowPrivate *priv;
1001 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1003 for (iter = tny_list_create_iterator (attachments);
1004 !tny_iterator_is_done (iter);
1005 tny_iterator_next (iter)) {
1006 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1007 const gchar *cid = tny_mime_part_get_content_id (part);
1008 const gchar *mime_type = tny_mime_part_get_content_type (part);
1009 if ((cid != NULL)&&(mime_type != NULL)) {
1010 guint64 stream_size;
1011 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1012 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
1015 g_object_unref (stream);
1017 if (pixbuf != NULL) {
1018 priv->images_count ++;
1019 priv->images_size += stream_size;
1020 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1021 g_object_unref (pixbuf);
1024 g_object_unref (part);
1026 g_object_unref (iter);
1030 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1032 TnyMimePart *parent = NULL;
1033 const gchar *content_type = NULL;
1034 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1036 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1038 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1039 parent = g_object_ref (msg);
1040 } else if (content_type && !g_strcasecmp (content_type, "multipart/mixed")) {
1041 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1044 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1045 iter = tny_list_create_iterator (parts);
1046 while (!tny_iterator_is_done (iter)) {
1048 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1049 content_type = tny_mime_part_get_content_type (part);
1050 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1054 g_object_unref (part);
1056 tny_iterator_next (iter);
1058 g_object_unref (iter);
1059 g_object_unref (parts);
1062 if (parent != NULL) {
1063 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1066 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1067 iter = tny_list_create_iterator (parts);
1068 while (!tny_iterator_is_done (iter)) {
1070 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1071 content_type = tny_mime_part_get_content_type (part);
1072 if (content_type && g_str_has_prefix (content_type, "image/")) {
1073 tny_list_prepend (priv->images, (GObject *) part);
1075 g_object_unref (part);
1076 tny_iterator_next (iter);
1078 g_object_unref (iter);
1079 g_object_unref (parts);
1080 g_object_unref (parent);
1085 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1088 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1090 for (iter = tny_list_create_iterator (attachments) ;
1091 !tny_iterator_is_done (iter);
1092 tny_iterator_next (iter)) {
1093 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1094 const gchar *cid = tny_mime_part_get_content_id (part);
1096 char *invalid = NULL;
1097 gint int_cid = strtol (cid, &invalid, 10);
1098 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1099 priv->next_cid = int_cid + 1;
1102 g_object_unref (part);
1104 g_object_unref (iter);
1108 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1111 gchar *to, *cc, *bcc, *subject;
1113 ModestMsgEditWindowPrivate *priv;
1114 ModestWindowPrivate *parent_priv;
1116 TnyHeaderFlags priority_flags;
1117 TnyFolder *msg_folder;
1118 gboolean is_html = FALSE;
1119 gboolean field_view_set;
1121 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1122 g_return_if_fail (TNY_IS_MSG (msg));
1124 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1125 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1127 header = tny_msg_get_header (msg);
1128 to = tny_header_dup_to (header);
1129 cc = tny_header_dup_cc (header);
1130 bcc = tny_header_dup_bcc (header);
1131 subject = tny_header_dup_subject (header);
1132 priority_flags = tny_header_get_priority (header);
1135 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
1137 field_view_set = TRUE;
1139 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
1140 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1141 gtk_widget_show (priv->cc_caption);
1142 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1143 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1144 gtk_widget_hide (priv->cc_caption);
1145 field_view_set = FALSE;
1147 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button), field_view_set);
1149 field_view_set = TRUE;
1151 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
1152 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1153 gtk_widget_show (priv->bcc_caption);
1154 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1155 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1156 gtk_widget_hide (priv->bcc_caption);
1157 field_view_set = FALSE;
1159 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button), field_view_set);
1163 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1164 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1167 update_window_title (self);
1169 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1170 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1172 if ((body == NULL)||(body[0] == '\0')) {
1174 body = modest_text_utils_convert_to_html ("");
1177 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1178 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1181 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1184 /* Add attachments to the view */
1185 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1186 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1187 if (tny_list_get_length (priv->attachments) == 0) {
1188 gtk_widget_hide (priv->attachments_caption);
1190 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1191 gtk_widget_show_all (priv->attachments_caption);
1193 get_related_images (self, msg);
1194 update_next_cid (self, priv->attachments);
1195 update_next_cid (self, priv->images);
1196 replace_with_images (self, priv->images);
1198 if (preserve_is_rich && !is_html) {
1199 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1200 /* Get the default format required from configuration */
1201 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1202 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1205 /* Set the default focus depending on having already a To: field or not */
1206 if ((!to)||(*to == '\0')) {
1207 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1209 gtk_widget_grab_focus (priv->msg_body);
1212 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1214 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1215 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1217 modest_msg_edit_window_set_modified (self, FALSE);
1219 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1220 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1221 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1222 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1224 if (priv->msg_uid) {
1225 g_free (priv->msg_uid);
1226 priv->msg_uid = NULL;
1229 /* we should set a reference to the incoming message if it is a draft */
1230 msg_folder = tny_msg_get_folder (msg);
1232 if (modest_tny_folder_is_local_folder (msg_folder)) {
1233 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1234 if (type == TNY_FOLDER_TYPE_INVALID)
1235 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1237 if (type == TNY_FOLDER_TYPE_DRAFTS)
1238 priv->draft_msg = g_object_ref(msg);
1239 if (type == TNY_FOLDER_TYPE_OUTBOX)
1240 priv->outbox_msg = g_object_ref(msg);
1241 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1243 g_object_unref (msg_folder);
1253 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
1256 GList *item_children, *node;
1257 GtkWidget *bin_child;
1259 bin_child = gtk_bin_get_child (GTK_BIN(item));
1261 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
1263 for (node = item_children; node != NULL; node = g_list_next (node)) {
1264 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
1265 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
1268 g_list_free (item_children);
1272 menu_tool_button_dont_expand (GtkMenuToolButton *item)
1275 GList *item_children, *node;
1277 box = gtk_bin_get_child (GTK_BIN (item));
1278 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
1279 item_children = gtk_container_get_children (GTK_CONTAINER (box));
1281 for (node = item_children; node != NULL; node = g_list_next (node)) {
1282 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
1283 if (GTK_IS_TOGGLE_BUTTON (node->data))
1284 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
1285 else if (GTK_IS_BUTTON (node->data))
1286 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
1288 g_list_free (item_children);
1293 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1295 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1296 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1297 GtkWidget *placeholder;
1298 GtkWidget *tool_item;
1303 GtkWidget *sizes_menu;
1304 GtkWidget *fonts_menu;
1305 GSList *radio_group = NULL;
1306 GSList *node = NULL;
1310 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1311 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1313 /* Font color placeholder */
1314 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1315 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1318 priv->font_color_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1319 priv->font_color_button = hildon_color_button_new ();
1320 GTK_WIDGET_UNSET_FLAGS (priv->font_color_toolitem, GTK_CAN_FOCUS);
1321 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1322 gtk_container_add (GTK_CONTAINER (priv->font_color_toolitem), priv->font_color_button);
1323 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1324 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1325 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->font_color_toolitem), insert_index);
1326 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1328 G_CALLBACK (modest_msg_edit_window_color_button_change),
1331 /* Font size and face placeholder */
1332 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1333 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1335 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1336 priv->size_tool_button_label = gtk_label_new (NULL);
1337 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1338 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1339 size_text,"</span>", NULL);
1340 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1342 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
1343 sizes_menu = gtk_menu_new ();
1344 priv->size_items_group = NULL;
1346 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1347 GtkWidget *size_menu_item;
1349 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1350 size_menu_item = gtk_radio_menu_item_new_with_label (radio_group, size_text);
1351 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (size_menu_item));
1352 gtk_menu_shell_append (GTK_MENU_SHELL (sizes_menu), size_menu_item);
1353 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (size_menu_item), (wp_font_size[size_index] == 12));
1354 gtk_widget_show (size_menu_item);
1356 priv->size_items_group = g_slist_prepend (priv->size_items_group, size_menu_item);
1360 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1361 GtkWidget *item = (GtkWidget *) node->data;
1362 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_size_change),
1366 priv->size_items_group = g_slist_reverse (priv->size_items_group);
1367 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), sizes_menu);
1368 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1369 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1370 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1371 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1372 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1373 priv->font_size_toolitem = tool_item;
1376 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1377 priv->font_tool_button_label = gtk_label_new (NULL);
1378 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1379 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1381 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
1382 fonts_menu = gtk_menu_new ();
1383 priv->font_items_group = NULL;
1385 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1386 GtkWidget *font_menu_item;
1387 GtkWidget *child_label;
1389 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
1390 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
1391 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
1392 wp_get_font_name (font_index), "</span>", NULL);
1393 gtk_label_set_markup (GTK_LABEL (child_label), markup);
1396 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
1397 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
1398 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
1399 gtk_widget_show (font_menu_item);
1401 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
1404 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1405 GtkWidget *item = (GtkWidget *) node->data;
1406 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
1409 priv->font_items_group = g_slist_reverse (priv->font_items_group);
1410 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
1411 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1412 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1413 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1414 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1415 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1416 priv->font_face_toolitem = tool_item;
1418 /* Set expand and homogeneous for remaining items */
1419 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
1420 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1421 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1422 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1423 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1424 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1425 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1426 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1427 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1429 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1430 will not show the tool items added to the placeholders) */
1431 gtk_widget_show_all (parent_priv->toolbar);
1433 /* Set the no show all *after* showing all items. We do not
1434 want the toolbar to be shown with a show all because it
1435 could go agains the gconf setting regarding showing or not
1436 the toolbar of the editor window */
1437 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1443 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, gboolean preserve_is_rich)
1446 ModestWindowPrivate *parent_priv;
1447 ModestMsgEditWindowPrivate *priv;
1448 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1449 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1450 ModestWindowMgr *mgr = NULL;
1452 g_return_val_if_fail (msg, NULL);
1453 g_return_val_if_fail (account_name, NULL);
1455 mgr = modest_runtime_get_window_mgr ();
1457 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1459 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1460 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1462 /* Menubar. Update the state of some toggles */
1463 priv->from_field_protos = get_transports ();
1464 modest_selector_picker_set_pair_list (MODEST_SELECTOR_PICKER (priv->from_field), priv->from_field_protos);
1465 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1466 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1468 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1469 hildon_touch_selector_get_current_text
1470 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1471 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1472 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1475 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1477 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1479 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1481 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1483 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1484 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1485 /* Add common dimming rules */
1486 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1487 modest_msg_edit_window_toolbar_dimming_entries,
1488 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1489 MODEST_WINDOW (obj));
1490 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_toolitem,
1491 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1492 MODEST_WINDOW (obj));
1493 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1494 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1495 MODEST_WINDOW (obj));
1496 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1497 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1498 MODEST_WINDOW (obj));
1499 /* Insert dimming rules group for this window */
1500 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1501 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1503 /* Setup app menu */
1504 setup_menu (MODEST_MSG_EDIT_WINDOW (obj));
1506 /* Checks the dimming rules */
1507 g_object_unref (toolbar_rules_group);
1508 g_object_unref (clipboard_rules_group);
1509 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1511 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1513 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1514 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1515 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1516 priv->update_caption_visibility = TRUE;
1518 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1520 /* Track account-removed signal, this window should be closed
1521 in the case we're creating a mail associated to the account
1523 priv->account_removed_handler_id =
1524 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1526 G_CALLBACK(on_account_removed),
1529 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1531 return (ModestWindow*) obj;
1535 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1537 GString **string_buffer = (GString **) user_data;
1539 *string_buffer = g_string_append (*string_buffer, buffer);
1545 * @result: A new string which should be freed with g_free().
1548 get_formatted_data (ModestMsgEditWindow *edit_window)
1550 ModestMsgEditWindowPrivate *priv;
1551 GString *string_buffer = g_string_new ("");
1553 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1555 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1557 modest_text_utils_hyperlinkify (string_buffer);
1559 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1561 return g_string_free (string_buffer, FALSE);
1566 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1569 const gchar *account_name;
1570 ModestMsgEditWindowPrivate *priv;
1571 TnyIterator *att_iter;
1573 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1575 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1577 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1578 g_return_val_if_fail (account_name, NULL);
1581 /* don't free these (except from) */
1582 data = g_slice_new0 (MsgData);
1583 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1585 data->account_name = g_strdup (account_name);
1586 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1587 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1588 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1589 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1590 if (priv->draft_msg) {
1591 data->draft_msg = g_object_ref (priv->draft_msg);
1592 } else if (priv->outbox_msg) {
1593 data->draft_msg = g_object_ref (priv->outbox_msg);
1595 data->draft_msg = NULL;
1598 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1600 gtk_text_buffer_get_bounds (buf, &b, &e);
1601 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1603 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1604 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1606 data->html_body = NULL;
1608 /* deep-copy the data */
1609 att_iter = tny_list_create_iterator (priv->attachments);
1610 data->attachments = NULL;
1611 while (!tny_iterator_is_done (att_iter)) {
1612 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1613 if (!(TNY_IS_MIME_PART(part))) {
1614 g_warning ("strange data in attachment list");
1615 g_object_unref (part);
1616 tny_iterator_next (att_iter);
1619 data->attachments = g_list_append (data->attachments,
1621 tny_iterator_next (att_iter);
1623 g_object_unref (att_iter);
1625 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1626 att_iter = tny_list_create_iterator (priv->images);
1627 data->images = NULL;
1628 while (!tny_iterator_is_done (att_iter)) {
1629 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1631 if (!(TNY_IS_MIME_PART(part))) {
1632 g_warning ("strange data in attachment list");
1633 g_object_unref (part);
1634 tny_iterator_next (att_iter);
1637 cid = tny_mime_part_get_content_id (part);
1639 gchar *image_tag_id;
1640 GtkTextTag *image_tag;
1642 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1643 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1644 g_free (image_tag_id);
1646 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1648 ((gtk_text_iter_has_tag (&iter, image_tag))||
1649 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1650 data->images = g_list_append (data->images,
1651 g_object_ref (part));
1653 g_object_unref (part);
1654 tny_iterator_next (att_iter);
1656 g_object_unref (att_iter);
1658 data->priority_flags = priv->priority_flags;
1665 unref_gobject (GObject *obj, gpointer data)
1667 if (!G_IS_OBJECT(obj))
1669 g_object_unref (obj);
1673 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1676 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1684 g_free (data->from);
1685 g_free (data->subject);
1686 g_free (data->plain_body);
1687 g_free (data->html_body);
1688 g_free (data->account_name);
1690 if (data->draft_msg != NULL) {
1691 g_object_unref (data->draft_msg);
1692 data->draft_msg = NULL;
1695 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1696 g_list_free (data->attachments);
1697 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1698 g_list_free (data->images);
1700 g_slice_free (MsgData, data);
1704 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1706 guint64 *parts_size)
1708 ModestMsgEditWindowPrivate *priv;
1710 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1712 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1714 /* TODO: add images */
1715 *parts_size += priv->images_size;
1716 *parts_count += priv->images_count;
1721 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1724 ModestMsgEditWindowPrivate *priv = NULL;
1725 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1727 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1729 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1731 return MODEST_MSG_EDIT_FORMAT_HTML;
1733 return MODEST_MSG_EDIT_FORMAT_TEXT;
1737 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1738 ModestMsgEditFormat format)
1740 ModestMsgEditWindowPrivate *priv;
1742 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1743 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1746 case MODEST_MSG_EDIT_FORMAT_HTML:
1747 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1749 case MODEST_MSG_EDIT_FORMAT_TEXT:
1750 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1753 g_return_if_reached ();
1757 ModestMsgEditFormatState *
1758 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1760 ModestMsgEditFormatState *format_state = NULL;
1761 ModestMsgEditWindowPrivate *priv;
1762 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1764 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1765 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1767 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1769 format_state = g_new0 (ModestMsgEditFormatState, 1);
1770 format_state->bold = buffer_format->bold&0x1;
1771 format_state->italics = buffer_format->italic&0x1;
1772 format_state->bullet = buffer_format->bullet&0x1;
1773 format_state->color = buffer_format->color;
1774 format_state->font_size = buffer_format->font_size;
1775 format_state->font_family = wp_get_font_name (buffer_format->font);
1776 format_state->justification = buffer_format->justification;
1777 g_free (buffer_format);
1779 return format_state;
1784 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1785 const ModestMsgEditFormatState *format_state)
1787 ModestMsgEditWindowPrivate *priv;
1788 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1789 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1790 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1791 g_return_if_fail (format_state != NULL);
1793 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1794 gtk_widget_grab_focus (priv->msg_body);
1795 buffer_format->bold = (format_state->bold != FALSE);
1796 buffer_format->italic = (format_state->italics != FALSE);
1797 buffer_format->color = format_state->color;
1798 buffer_format->font_size = format_state->font_size;
1799 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1800 buffer_format->justification = format_state->justification;
1801 buffer_format->bullet = format_state->bullet;
1803 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1805 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1806 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1807 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1808 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1809 buffer_format->cs.font = (buffer_format->font != current_format->font);
1810 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1811 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1813 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1814 if (buffer_format->cs.bold) {
1815 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
1816 GINT_TO_POINTER (buffer_format->bold&0x1));
1818 if (buffer_format->cs.italic) {
1819 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
1820 GINT_TO_POINTER (buffer_format->italic&0x1));
1822 if (buffer_format->cs.color) {
1823 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1824 GINT_TO_POINTER (&(buffer_format->color)));
1826 if (buffer_format->cs.font_size) {
1827 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1828 GINT_TO_POINTER (buffer_format->font_size));
1830 if (buffer_format->cs.justification) {
1831 switch (buffer_format->justification) {
1832 case GTK_JUSTIFY_LEFT:
1833 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
1834 GINT_TO_POINTER(TRUE));
1836 case GTK_JUSTIFY_CENTER:
1837 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
1838 GINT_TO_POINTER(TRUE));
1840 case GTK_JUSTIFY_RIGHT:
1841 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
1842 GINT_TO_POINTER(TRUE));
1849 if (buffer_format->cs.font) {
1850 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1851 GINT_TO_POINTER (buffer_format->font));
1853 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1854 if (buffer_format->cs.bullet) {
1855 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
1856 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
1858 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1860 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
1862 g_free (buffer_format);
1863 g_free (current_format);
1865 /* Check dimming rules */
1866 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1867 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1871 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1873 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1875 ModestWindowPrivate *parent_priv;
1876 ModestMsgEditWindowPrivate *priv;
1877 GtkWidget *new_size_menuitem;
1878 GtkWidget *new_font_menuitem;
1880 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1881 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1883 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1884 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu");
1885 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1886 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1888 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatPlainTextMenu");
1889 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1890 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1893 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1895 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1896 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1898 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1899 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1901 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
1902 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
1905 switch (buffer_format->justification)
1907 case GTK_JUSTIFY_LEFT:
1908 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
1910 case GTK_JUSTIFY_CENTER:
1911 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
1913 case GTK_JUSTIFY_RIGHT:
1914 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
1921 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
1923 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1924 G_CALLBACK (modest_msg_edit_window_color_button_change),
1926 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1927 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1928 G_CALLBACK (modest_msg_edit_window_color_button_change),
1931 new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group,
1932 buffer_format->font_size))->data);
1933 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1937 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1938 markup = g_strconcat ("<span font_family='Sans'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1939 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1941 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1942 G_CALLBACK (modest_msg_edit_window_size_change),
1944 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
1945 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
1946 G_CALLBACK (modest_msg_edit_window_size_change),
1950 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
1951 buffer_format->font))->data);
1952 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
1956 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
1957 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1958 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1960 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
1961 G_CALLBACK (modest_msg_edit_window_font_change),
1963 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
1964 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
1965 G_CALLBACK (modest_msg_edit_window_font_change),
1969 g_free (buffer_format);
1973 #ifdef MODEST_HILDON_VERSION_0
1975 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
1978 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1979 ModestMsgEditWindowPrivate *priv;
1980 GtkWidget *dialog = NULL;
1982 GdkColor *new_color = NULL;
1984 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1985 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1987 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1988 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
1989 g_free (buffer_format);
1991 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
1992 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1993 if (new_color != NULL) {
1994 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1995 (gpointer) new_color);
1998 gtk_widget_destroy (dialog);
2003 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2006 ModestMsgEditWindowPrivate *priv;
2007 GtkWidget *dialog = NULL;
2009 GdkColor *old_color = NULL;
2010 const GdkColor *new_color = NULL;
2012 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2013 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2015 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2016 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2018 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2019 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2020 if (new_color != NULL)
2021 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2023 gtk_widget_destroy (dialog);
2029 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2032 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2033 ModestMsgEditWindowPrivate *priv;
2034 GtkWidget *dialog = NULL;
2036 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2037 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2039 dialog = hildon_color_chooser_new ();
2040 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2041 g_free (buffer_format);
2043 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2045 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2046 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2049 gtk_widget_destroy (dialog);
2054 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2057 ModestMsgEditWindowPrivate *priv;
2058 GtkWidget *dialog = NULL;
2059 GdkColor *old_color = NULL;
2061 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2062 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2064 dialog = hildon_color_chooser_new ();
2065 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2067 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2069 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2070 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2072 gtk_widget_destroy (dialog);
2075 #endif /*!MODEST_HILDON_VERSION_0*/
2080 create_stream_for_uri (const gchar* uri)
2085 TnyStream *result = NULL;
2087 GnomeVFSHandle *handle = NULL;
2088 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2089 if (test == GNOME_VFS_OK) {
2090 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2091 /* Streams over OBEX (Bluetooth) are not seekable but
2092 * we expect them to be (we might need to read them
2093 * several times). So if this is a Bluetooth URI just
2094 * read the whole file into memory (this is not a fast
2095 * protocol so we can assume that these files are not
2096 * going to be very big) */
2097 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2098 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2099 TnyStream *memstream = tny_camel_mem_stream_new ();
2100 tny_stream_write_to_stream (vfssstream, memstream);
2101 g_object_unref (vfssstream);
2104 result = vfssstream;
2112 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2115 ModestMsgEditWindowPrivate *priv;
2116 GtkWidget *dialog = NULL;
2118 GSList *uris = NULL;
2119 GSList *uri_node = NULL;
2121 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2123 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2124 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2125 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2127 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2129 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2130 GTK_WINDOW (dialog), GTK_WINDOW (window));
2132 response = gtk_dialog_run (GTK_DIALOG (dialog));
2134 case GTK_RESPONSE_OK:
2135 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2140 gtk_widget_destroy (dialog);
2142 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2144 GnomeVFSHandle *handle = NULL;
2145 GnomeVFSResult result;
2146 GtkTextIter position;
2147 GtkTextMark *insert_mark;
2149 uri = (const gchar *) uri_node->data;
2150 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2151 if (result == GNOME_VFS_OK) {
2153 GnomeVFSFileInfo *info;
2154 gchar *filename, *basename, *escaped_filename;
2155 TnyMimePart *mime_part;
2157 const gchar *mime_type = NULL;
2158 GnomeVFSURI *vfs_uri;
2159 guint64 stream_size;
2161 gnome_vfs_close (handle);
2162 vfs_uri = gnome_vfs_uri_new (uri);
2164 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2165 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2166 g_free (escaped_filename);
2167 gnome_vfs_uri_unref (vfs_uri);
2168 info = gnome_vfs_file_info_new ();
2170 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2171 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2173 mime_type = gnome_vfs_file_info_get_mime_type (info);
2175 mime_part = tny_platform_factory_new_mime_part
2176 (modest_runtime_get_platform_factory ());
2178 TnyStream *stream = create_stream_for_uri (uri);
2180 if (stream == NULL) {
2182 modest_platform_information_banner (NULL, NULL, dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2184 g_object_unref (mime_part);
2185 gnome_vfs_file_info_unref (info);
2189 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2191 content_id = g_strdup_printf ("%d", priv->next_cid);
2192 tny_mime_part_set_content_id (mime_part, content_id);
2193 g_free (content_id);
2196 basename = g_path_get_basename (filename);
2197 tny_mime_part_set_filename (mime_part, basename);
2200 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
2202 if (pixbuf != NULL) {
2203 priv->images_size += stream_size;
2204 priv->images_count ++;
2205 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2206 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2207 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
2208 g_object_unref (pixbuf);
2211 tny_list_prepend (priv->images, (GObject *) mime_part);
2212 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2214 g_object_unref (mime_part);
2215 gnome_vfs_file_info_unref (info);
2224 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2226 GtkWidget *dialog = NULL;
2228 GSList *uris = NULL;
2230 GnomeVFSFileSize total_size, allowed_size;
2231 ModestMsgEditWindowPrivate *priv;
2235 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2237 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2239 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2242 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2243 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2244 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2245 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), GTK_WINDOW (dialog), GTK_WINDOW (window));
2247 response = gtk_dialog_run (GTK_DIALOG (dialog));
2249 case GTK_RESPONSE_OK:
2250 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2255 gtk_widget_destroy (dialog);
2257 /* allowed size is the maximum size - what's already there */
2258 modest_attachments_view_get_sizes (
2259 MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2260 &att_num, &att_size);
2261 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2264 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2266 const gchar *uri = (const gchar *) uri_node->data;
2268 total_size += modest_msg_edit_window_attach_file_one
2269 (window, uri, allowed_size);
2271 if (total_size > allowed_size) {
2272 g_warning ("%s: total size: %u",
2273 __FUNCTION__, (unsigned int)total_size);
2277 allowed_size -= total_size;
2281 g_slist_foreach (uris, (GFunc) g_free, NULL);
2282 g_slist_free (uris);
2287 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2289 GnomeVFSFileSize allowed_size)
2292 GnomeVFSHandle *handle = NULL;
2293 ModestMsgEditWindowPrivate *priv;
2294 GnomeVFSResult result;
2295 GnomeVFSFileSize size = 0;
2296 g_return_val_if_fail (window, 0);
2297 g_return_val_if_fail (uri, 0);
2299 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2301 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2302 if (result == GNOME_VFS_OK) {
2303 TnyMimePart *mime_part;
2305 const gchar *mime_type = NULL;
2307 gchar *escaped_filename;
2310 GnomeVFSFileInfo *info;
2311 GnomeVFSURI *vfs_uri;
2313 gnome_vfs_close (handle);
2314 vfs_uri = gnome_vfs_uri_new (uri);
2317 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2318 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2319 g_free (escaped_filename);
2320 gnome_vfs_uri_unref (vfs_uri);
2322 info = gnome_vfs_file_info_new ();
2324 if (gnome_vfs_get_file_info (uri,
2326 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2328 mime_type = gnome_vfs_file_info_get_mime_type (info);
2329 mime_part = tny_platform_factory_new_mime_part
2330 (modest_runtime_get_platform_factory ());
2332 /* try to get the attachment's size; this may fail for weird
2333 * file systems, like obex, upnp... */
2334 if (allowed_size != 0 &&
2335 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2337 if (size > allowed_size) {
2338 modest_platform_information_banner (NULL, NULL,
2339 dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2343 g_warning ("%s: could not get attachment size", __FUNCTION__);
2345 stream = create_stream_for_uri (uri);
2347 if (stream == NULL) {
2349 modest_platform_information_banner (NULL, NULL, dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2351 g_object_unref (mime_part);
2352 gnome_vfs_file_info_unref (info);
2356 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2357 g_object_unref (stream);
2359 content_id = g_strdup_printf ("%d", priv->next_cid);
2360 tny_mime_part_set_content_id (mime_part, content_id);
2361 g_free (content_id);
2364 basename = g_path_get_basename (filename);
2365 tny_mime_part_set_filename (mime_part, basename);
2368 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2369 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2371 info->size == 0, info->size);
2372 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2373 gtk_widget_show_all (priv->attachments_caption);
2374 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2376 g_object_unref (mime_part);
2377 gnome_vfs_file_info_unref (info);
2384 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2387 ModestMsgEditWindowPrivate *priv;
2390 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2391 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2393 if (att_list == NULL) {
2394 att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2396 g_object_ref (att_list);
2399 if (tny_list_get_length (att_list) == 0) {
2400 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2402 gboolean dialog_response;
2403 gchar *message = NULL;
2404 gchar *filename = NULL;
2406 if (tny_list_get_length (att_list) == 1) {
2408 iter = tny_list_create_iterator (att_list);
2409 part = (TnyMimePart *) tny_iterator_get_current (iter);
2410 g_object_unref (iter);
2411 if (TNY_IS_MSG (part)) {
2412 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2414 filename = tny_header_dup_subject (header);
2415 g_object_unref (header);
2417 if (filename == NULL) {
2418 filename = g_strdup (_("mail_va_no_subject"));
2421 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2423 g_object_unref (part);
2425 filename = g_strdup ("");
2427 message = g_strdup_printf (ngettext("emev_nc_delete_attachment", "emev_nc_delete_attachments",
2428 tny_list_get_length (att_list)), filename);
2431 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window), message);
2434 if (dialog_response != GTK_RESPONSE_OK) {
2435 g_object_unref (att_list);
2438 hildon_banner_show_information (NULL, NULL, _("mcen_me_inbox_remove_attachments"));
2440 for (iter = tny_list_create_iterator (att_list);
2441 !tny_iterator_is_done (iter);
2442 tny_iterator_next (iter)) {
2443 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2444 const gchar *att_id;
2445 tny_list_remove (priv->attachments, (GObject *) mime_part);
2447 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2449 if (tny_list_get_length (priv->attachments) == 0)
2450 gtk_widget_hide (priv->attachments_caption);
2451 att_id = tny_mime_part_get_content_id (mime_part);
2453 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2455 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2456 g_object_unref (mime_part);
2458 g_object_unref (iter);
2461 g_object_unref (att_list);
2463 /* if the last attachment has been removed, focus the Subject: field */
2464 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2465 gtk_widget_grab_focus (priv->subject_field);
2469 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2472 ModestMsgEditWindowPrivate *priv;
2473 GdkColor *new_color;
2474 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2476 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2477 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2480 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2482 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2484 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2486 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2491 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
2494 ModestMsgEditWindowPrivate *priv;
2495 gint new_size_index;
2496 ModestMsgEditWindow *window;
2499 window = MODEST_MSG_EDIT_WINDOW (userdata);
2500 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2501 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2503 if (gtk_check_menu_item_get_active (menu_item)) {
2505 WPTextBufferFormat format;
2507 memset (&format, 0, sizeof (format));
2508 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2510 label = gtk_bin_get_child (GTK_BIN (menu_item));
2512 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
2513 format.cs.font_size = TRUE;
2514 format.cs.text_position = TRUE;
2515 format.cs.font = TRUE;
2516 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
2517 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2519 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2520 GINT_TO_POINTER (wp_get_font_size_index (new_size_index, 12))))
2521 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2523 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2524 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
2525 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2531 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
2534 ModestMsgEditWindowPrivate *priv;
2535 gint new_font_index;
2536 ModestMsgEditWindow *window;
2539 window = MODEST_MSG_EDIT_WINDOW (userdata);
2540 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2541 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2543 if (gtk_check_menu_item_get_active (menu_item)) {
2546 label = gtk_bin_get_child (GTK_BIN (menu_item));
2548 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
2550 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2551 GINT_TO_POINTER(new_font_index)))
2552 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2554 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2555 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2556 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2562 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2565 ModestMsgEditWindowPrivate *priv = NULL;
2566 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2568 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2569 if (!priv->update_caption_visibility)
2572 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2574 gtk_widget_show (priv->cc_caption);
2576 gtk_widget_hide (priv->cc_caption);
2578 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2582 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2585 ModestMsgEditWindowPrivate *priv = NULL;
2586 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2588 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2589 if (!priv->update_caption_visibility)
2592 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2594 gtk_widget_show (priv->bcc_caption);
2596 gtk_widget_hide (priv->bcc_caption);
2598 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2602 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2603 ModestRecptEditor *editor)
2605 ModestMsgEditWindowPrivate *priv;
2607 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2608 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2610 /* we check for low-mem; in that case, show a warning, and don't allow
2611 * for the addressbook
2613 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2616 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2618 if (editor == NULL) {
2619 GtkWidget *view_focus;
2620 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2622 /* This code should be kept in sync with ModestRecptEditor. The
2623 textview inside the recpt editor is the one that really gets the
2624 focus. As it's inside a scrolled window, and this one inside the
2625 hbox recpt editor inherits from, we'll need to go up in the
2626 hierarchy to know if the text view is part of the recpt editor
2627 or if it's a different text entry */
2629 if (gtk_widget_get_parent (view_focus)) {
2630 GtkWidget *first_parent;
2632 first_parent = gtk_widget_get_parent (view_focus);
2633 if (gtk_widget_get_parent (first_parent) &&
2634 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2635 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2640 editor = MODEST_RECPT_EDITOR (priv->to_field);
2644 modest_address_book_select_addresses (editor);
2649 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2651 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2653 modest_msg_edit_window_open_addressbook (window, NULL);
2657 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2658 gboolean show_toolbar)
2660 ModestWindowPrivate *parent_priv;
2662 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2663 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2665 /* We can not just use the code of
2666 modest_msg_edit_window_setup_toolbar because it has a
2667 mixture of both initialization and creation code. */
2669 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2671 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2675 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2676 TnyHeaderFlags priority_flags)
2678 ModestMsgEditWindowPrivate *priv;
2679 ModestWindowPrivate *parent_priv;
2681 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2683 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2684 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2686 if (priv->priority_flags != priority_flags) {
2687 GtkAction *priority_action = NULL;
2689 priv->priority_flags = priority_flags;
2691 switch (priority_flags) {
2692 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2693 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2694 MODEST_HEADER_ICON_HIGH,
2695 HILDON_ICON_SIZE_XSMALL);
2696 gtk_widget_show (priv->priority_icon);
2697 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2698 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2700 case TNY_HEADER_FLAG_LOW_PRIORITY:
2701 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2702 MODEST_HEADER_ICON_LOW,
2703 HILDON_ICON_SIZE_XSMALL);
2704 gtk_widget_show (priv->priority_icon);
2705 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2706 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2709 gtk_widget_hide (priv->priority_icon);
2710 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2711 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2714 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2715 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2720 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2723 ModestMsgEditWindowPrivate *priv;
2724 ModestWindowPrivate *parent_priv;
2725 gint current_format;
2727 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2729 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2730 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2732 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2733 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2735 if (current_format != file_format) {
2736 switch (file_format) {
2737 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2738 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2739 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
2741 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2745 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2746 response = gtk_dialog_run (GTK_DIALOG (dialog));
2747 gtk_widget_destroy (dialog);
2748 if (response == GTK_RESPONSE_OK) {
2749 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2751 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
2752 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
2757 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2758 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2759 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2764 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2767 ModestMsgEditWindowPrivate *priv;
2768 WPTextBufferFormat oldfmt, fmt;
2769 gint old_position = 0;
2773 GdkColor *color = NULL;
2774 gboolean bold, bold_set, italic, italic_set;
2775 gboolean underline, underline_set;
2776 gboolean strikethrough, strikethrough_set;
2777 gboolean position_set;
2778 gboolean font_size_set, font_set, color_set;
2781 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2782 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2784 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2785 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
2786 GTK_WINDOW(dialog), GTK_WINDOW (window));
2788 /* First we get the currently selected font information */
2789 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2791 switch (oldfmt.text_position) {
2792 case TEXT_POSITION_NORMAL:
2795 case TEXT_POSITION_SUPERSCRIPT:
2803 g_object_set (G_OBJECT (dialog),
2804 "bold", oldfmt.bold != FALSE,
2805 "bold-set", !oldfmt.cs.bold,
2806 "underline", oldfmt.underline != FALSE,
2807 "underline-set", !oldfmt.cs.underline,
2808 "italic", oldfmt.italic != FALSE,
2809 "italic-set", !oldfmt.cs.italic,
2810 "strikethrough", oldfmt.strikethrough != FALSE,
2811 "strikethrough-set", !oldfmt.cs.strikethrough,
2812 "color", &oldfmt.color,
2813 "color-set", !oldfmt.cs.color,
2814 "size", wp_font_size[oldfmt.font_size],
2815 "size-set", !oldfmt.cs.font_size,
2816 "position", old_position,
2817 "position-set", !oldfmt.cs.text_position,
2818 "family", wp_get_font_name (oldfmt.font),
2819 "family-set", !oldfmt.cs.font,
2822 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2823 GTK_WINDOW (dialog), GTK_WINDOW (window));
2824 gtk_widget_show_all (dialog);
2825 priv->font_dialog = dialog;
2826 response = gtk_dialog_run (GTK_DIALOG (dialog));
2827 priv->font_dialog = NULL;
2828 if (response == GTK_RESPONSE_OK) {
2830 g_object_get( dialog,
2832 "bold-set", &bold_set,
2833 "underline", &underline,
2834 "underline-set", &underline_set,
2836 "italic-set", &italic_set,
2837 "strikethrough", &strikethrough,
2838 "strikethrough-set", &strikethrough_set,
2840 "color-set", &color_set,
2842 "size-set", &font_size_set,
2843 "family", &font_name,
2844 "family-set", &font_set,
2845 "position", &position,
2846 "position-set", &position_set,
2851 if (response == GTK_RESPONSE_OK) {
2852 memset(&fmt, 0, sizeof(fmt));
2858 fmt.italic = italic;
2859 fmt.cs.italic = TRUE;
2861 if (underline_set) {
2862 fmt.underline = underline;
2863 fmt.cs.underline = TRUE;
2865 if (strikethrough_set) {
2866 fmt.strikethrough = strikethrough;
2867 fmt.cs.strikethrough = TRUE;
2872 ? TEXT_POSITION_NORMAL
2873 : ( ( position == 1 )
2874 ? TEXT_POSITION_SUPERSCRIPT
2875 : TEXT_POSITION_SUBSCRIPT );
2876 fmt.cs.text_position = TRUE;
2877 fmt.font_size = oldfmt.font_size;
2881 fmt.cs.color = TRUE;
2884 fmt.font = wp_get_font_index(font_name,
2889 if (font_size_set) {
2890 fmt.cs.font_size = TRUE;
2891 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
2893 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2894 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2896 gtk_widget_destroy (dialog);
2898 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2902 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2904 ModestMsgEditWindowPrivate *priv;
2906 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2907 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2909 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2911 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2912 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2916 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
2918 ModestMsgEditWindowPrivate *priv;
2920 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2921 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2923 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
2925 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2926 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2931 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
2933 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2935 priv->can_undo = can_undo;
2939 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
2941 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2943 priv->can_redo = can_redo;
2947 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
2949 ModestMsgEditWindowPrivate *priv;
2950 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2951 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2953 return priv->can_undo;
2957 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
2959 ModestMsgEditWindowPrivate *priv;
2960 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2961 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2963 return priv->can_redo;
2968 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
2971 GtkTextIter match_start, match_end;
2973 if (image_id == NULL)
2976 gtk_text_buffer_get_start_iter (buffer, &iter);
2978 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
2979 GSList *tags = gtk_text_iter_get_tags (&match_start);
2981 for (node = tags; node != NULL; node = g_slist_next (node)) {
2982 GtkTextTag *tag = (GtkTextTag *) node->data;
2983 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
2984 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
2985 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
2987 offset = gtk_text_iter_get_offset (&match_start);
2988 gtk_text_buffer_delete (buffer, &match_start, &match_end);
2989 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
2993 gtk_text_iter_forward_char (&iter);
2998 message_is_empty (ModestMsgEditWindow *window)
3000 ModestMsgEditWindowPrivate *priv = NULL;
3002 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3003 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3005 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3006 * so we can ignore markup.
3008 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3011 count = gtk_text_buffer_get_char_count (buf);
3017 msg_body_focus (GtkWidget *focus,
3018 GdkEventFocus *event,
3022 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3023 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3024 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3029 recpt_field_changed (GtkTextBuffer *buffer,
3030 ModestMsgEditWindow *editor)
3032 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3033 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3037 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3039 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3040 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3044 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3047 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3048 GtkTextBuffer *buffer;
3050 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3051 gtk_text_buffer_set_modified (buffer, modified);
3052 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3053 gtk_text_buffer_set_modified (buffer, modified);
3054 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3055 gtk_text_buffer_set_modified (buffer, modified);
3056 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3060 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3062 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3063 const char *account_name;
3064 GtkTextBuffer *buffer;
3066 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3067 if (gtk_text_buffer_get_modified (buffer))
3069 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3070 if (gtk_text_buffer_get_modified (buffer))
3072 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3073 if (gtk_text_buffer_get_modified (buffer))
3075 if (gtk_text_buffer_get_modified (priv->text_buffer))
3077 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3078 if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3089 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3091 ModestMsgEditWindowPrivate *priv = NULL;
3093 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3094 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3096 /* check if there's no recipient added */
3097 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3098 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3099 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3100 /* no recipient contents, then select contacts */
3101 modest_msg_edit_window_open_addressbook (window, NULL);
3105 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3106 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3109 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3110 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3113 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3114 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3118 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3119 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3120 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3127 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3128 ModestMsgEditWindow *window)
3130 modest_msg_edit_window_offer_attach_file (window);
3134 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3136 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3138 return priv->clipboard_text;
3142 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3144 ModestMsgEditWindow *window)
3146 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3147 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3149 if (!GTK_WIDGET_VISIBLE (window))
3152 g_object_ref (window);
3153 text = gtk_clipboard_wait_for_text (selection_clipboard);
3155 if (priv->clipboard_text != NULL) {
3156 g_free (priv->clipboard_text);
3158 priv->clipboard_text = text;
3160 if (GTK_WIDGET_VISIBLE (window)) {
3161 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3163 g_object_unref (window);
3166 static gboolean clipboard_owner_change_idle (gpointer userdata)
3168 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3169 ModestMsgEditWindowPrivate *priv;
3171 gdk_threads_enter ();
3172 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3173 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3175 priv->clipboard_owner_idle = 0;
3176 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3177 gdk_threads_leave ();
3183 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3185 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3186 if (priv->clipboard_owner_idle == 0) {
3187 priv->clipboard_owner_idle = g_idle_add (clipboard_owner_change_idle, window);
3192 subject_field_move_cursor (GtkEntry *entry,
3193 GtkMovementStep step,
3198 if (!GTK_WIDGET_VISIBLE (window))
3201 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3205 update_window_title (ModestMsgEditWindow *window)
3207 ModestMsgEditWindowPrivate *priv = NULL;
3208 const gchar *subject;
3210 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3211 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3212 if (subject == NULL || subject[0] == '\0')
3213 subject = _("mail_va_new_email");
3215 gtk_window_set_title (GTK_WINDOW (window), subject);
3220 subject_field_changed (GtkEditable *editable,
3221 ModestMsgEditWindow *window)
3223 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3224 update_window_title (window);
3225 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3226 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3227 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3231 subject_field_insert_text (GtkEditable *editable,
3233 gint new_text_length,
3235 ModestMsgEditWindow *window)
3237 GString *result = g_string_new ("");
3239 gint result_len = 0;
3240 const gchar *entry_text = NULL;
3243 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3244 old_length = g_utf8_strlen (entry_text, -1);
3246 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3247 gunichar c = g_utf8_get_char_validated (current, 8);
3248 /* Invalid unichar, stop */
3254 result = g_string_append_unichar (result, c);
3258 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3259 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3262 /* Prevent endless recursion */
3263 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3264 g_signal_emit_by_name (editable, "insert-text",
3265 (gpointer) result->str, (gpointer) result->len,
3266 (gpointer) position, (gpointer) window);
3267 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3271 if (result_len + old_length > 1000) {
3272 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3273 dgettext("hildon-common-strings",
3274 "ckdg_ib_maximum_characters_reached"));
3277 g_string_free (result, TRUE);
3281 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3284 ModestMsgEditWindowPrivate *priv = NULL;
3286 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3287 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3289 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3292 gtk_widget_show_all (priv->find_toolbar);
3293 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3295 gtk_widget_hide_all (priv->find_toolbar);
3296 gtk_widget_grab_focus (priv->msg_body);
3302 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3304 GtkTextIter *match_start,
3305 GtkTextIter *match_end)
3307 GtkTextIter end_iter;
3308 gchar *str_casefold;
3311 gchar *range_casefold;
3314 gboolean result = FALSE;
3321 gtk_text_iter_forward_to_end (&end_iter);
3323 str_casefold = g_utf8_casefold (str, -1);
3324 str_chars_n = strlen (str);
3326 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3327 range_casefold = g_utf8_casefold (range_text, -1);
3328 range_chars_n = strlen (range_casefold);
3330 if (range_chars_n < str_chars_n) {
3331 g_free (str_casefold);
3332 g_free (range_text);
3333 g_free (range_casefold);
3337 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3338 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3339 if (!g_utf8_collate (range_subtext, str_casefold)) {
3340 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3342 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3343 match_start, match_end, NULL);
3344 g_free (found_text);
3346 g_free (range_subtext);
3350 g_free (str_casefold);
3351 g_free (range_text);
3352 g_free (range_casefold);
3359 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3360 ModestMsgEditWindow *window)
3362 gchar *current_search = NULL;
3363 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3365 GtkTextIter selection_start, selection_end;
3366 GtkTextIter match_start, match_end;
3367 gboolean continue_search = FALSE;
3369 if (message_is_empty (window)) {
3370 g_free (priv->last_search);
3371 priv->last_search = NULL;
3372 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3376 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3377 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3378 g_free (current_search);
3379 g_free (priv->last_search);
3380 priv->last_search = NULL;
3381 /* Information banner about empty search */
3382 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-common-strings", "ecdg_ib_find_rep_enter_text"));
3386 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3387 continue_search = TRUE;
3389 g_free (priv->last_search);
3390 priv->last_search = g_strdup (current_search);
3393 if (continue_search) {
3394 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3395 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3396 &match_start, &match_end);
3398 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_search_complete"));
3400 GtkTextIter buffer_start;
3401 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3402 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3403 &match_start, &match_end);
3405 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_no_matches"));
3408 /* Mark as selected the string found in search */
3410 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3411 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3412 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3414 g_free (priv->last_search);
3415 priv->last_search = NULL;
3417 g_free (current_search);
3421 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3422 ModestMsgEditWindow *window)
3424 ModestMsgEditWindowPrivate *priv;
3426 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3428 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->find_toolbar_button), FALSE);
3432 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3434 ModestMsgEditWindowPrivate *priv;
3436 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3441 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3444 ModestMsgEditWindowPrivate *priv;
3446 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3452 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3455 ModestMsgEditWindowPrivate *priv;
3456 TnyHeader *header = NULL;
3458 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3459 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3461 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3462 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3464 if (priv->draft_msg != NULL) {
3465 g_object_unref (priv->draft_msg);
3468 if (draft != NULL) {
3469 g_object_ref (draft);
3470 header = tny_msg_get_header (draft);
3471 if (priv->msg_uid) {
3472 g_free (priv->msg_uid);
3473 priv->msg_uid = NULL;
3475 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3476 if (GTK_WIDGET_REALIZED (window)) {
3477 if (!modest_window_mgr_register_window (mgr, MODEST_WINDOW (window), NULL)) {
3478 gtk_widget_destroy (GTK_WIDGET (window));
3484 priv->draft_msg = draft;
3488 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3489 GtkTextIter *start, GtkTextIter *end,
3492 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3493 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3496 if (tag == NULL) return;
3497 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3498 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3499 replace_with_images (window, priv->images);
3504 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3507 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3509 g_return_if_fail (TNY_IS_MIME_PART (part));
3510 tny_list_prepend (priv->attachments, (GObject *) part);
3511 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3512 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3513 gtk_widget_show_all (priv->attachments_caption);
3514 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3518 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3520 ModestMsgEditWindowPrivate *priv;
3522 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3523 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3525 return priv->msg_uid;
3529 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3530 ModestMsgEditWindowWidgetType widget_type)
3532 ModestMsgEditWindowPrivate *priv;
3534 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3535 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3537 switch (widget_type) {
3538 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3539 return priv->msg_body;
3541 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3542 return priv->to_field;
3544 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3545 return priv->cc_field;
3547 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3548 return priv->bcc_field;
3550 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3551 return priv->subject_field;
3553 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3554 return priv->attachments_view;
3562 remove_tags (WPTextBuffer *buffer)
3564 GtkTextIter start, end;
3566 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3567 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3569 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3573 on_account_removed (TnyAccountStore *account_store,
3574 TnyAccount *account,
3577 /* Do nothing if it's a store account, because we use the
3578 transport to send the messages */
3579 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3580 const gchar *parent_acc = NULL;
3581 const gchar *our_acc = NULL;
3583 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3584 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3585 /* Close this window if I'm showing a message of the removed account */
3586 if (strcmp (parent_acc, our_acc) == 0)
3587 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3591 typedef struct _MessageSettingsHelper {
3592 ModestMsgEditWindow *window;
3593 GSList *priority_group;
3594 GtkWidget *align_picker;
3595 } MessageSettingsHelper;
3598 on_priority_toggle (HildonCheckButton *button,
3599 MessageSettingsHelper *helper)
3602 ModestMsgEditWindowPrivate *priv;
3604 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3605 if (hildon_check_button_get_active (button)) {
3607 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3608 HildonCheckButton *node_button = (HildonCheckButton *) node->data;
3609 if ((node_button != button) &&
3610 hildon_check_button_get_active (node_button)) {
3611 hildon_check_button_set_active (node_button, FALSE);
3613 if (priv->priority_flags != (TnyHeaderFlags) g_object_get_data (G_OBJECT (button), "priority"))
3614 modest_msg_edit_window_set_priority_flags (helper->window,
3616 g_object_get_data (G_OBJECT (button),
3622 gboolean found = FALSE;
3623 /* If no one is active, activate it again */
3624 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3625 HildonCheckButton *node_button = (HildonCheckButton *) node->data;
3626 if (hildon_check_button_get_active (node_button)) {
3632 hildon_check_button_set_active (button, TRUE);
3638 on_format_picker_value_changed (HildonPickerButton *button,
3639 MessageSettingsHelper *helper)
3641 ModestMsgEditFormat new_format, old_format;
3644 switch (hildon_picker_button_get_active (button)) {
3646 new_format = MODEST_MSG_EDIT_FORMAT_HTML;
3647 file_format = MODEST_FILE_FORMAT_FORMATTED_TEXT;
3651 new_format = MODEST_MSG_EDIT_FORMAT_TEXT;
3652 file_format = MODEST_FILE_FORMAT_PLAIN_TEXT;
3656 old_format = modest_msg_edit_window_get_format (helper->window);
3657 if (new_format != old_format) {
3658 modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (helper->window), file_format);
3660 switch (modest_msg_edit_window_get_format (helper->window)) {
3661 case MODEST_MSG_EDIT_FORMAT_TEXT:
3662 hildon_picker_button_set_active (button, 0);
3663 gtk_widget_set_sensitive (helper->align_picker, FALSE);
3665 case MODEST_MSG_EDIT_FORMAT_HTML:
3667 hildon_picker_button_set_active (button, 1);
3668 gtk_widget_set_sensitive (helper->align_picker, TRUE);
3675 on_align_picker_value_changed (HildonPickerButton *button,
3676 MessageSettingsHelper *helper)
3678 GtkJustification new_justify;
3679 ModestMsgEditFormatState *format_state = NULL;
3681 switch (hildon_picker_button_get_active (button)) {
3683 new_justify = GTK_JUSTIFY_CENTER;
3686 new_justify = GTK_JUSTIFY_RIGHT;
3690 new_justify = GTK_JUSTIFY_LEFT;
3694 format_state = modest_msg_edit_window_get_format_state (helper->window);
3695 if (format_state->justification != new_justify)
3696 format_state->justification = new_justify;
3697 modest_msg_edit_window_set_format_state (helper->window, format_state);
3698 g_free (format_state);
3702 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
3706 GtkWidget *priority_hbox;
3707 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
3708 GtkWidget *captioned;
3709 GtkSizeGroup *title_sizegroup, *value_sizegroup;
3710 GtkWidget *format_picker;
3711 GtkWidget *format_selector;
3712 ModestMsgEditWindowPrivate *priv;
3713 MessageSettingsHelper helper = {0,};
3714 ModestMsgEditFormatState *format_state = NULL;
3716 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3717 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3718 helper.window = window;
3719 helper.priority_group = NULL;
3721 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3722 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3724 dialog = gtk_dialog_new ();
3725 vbox = gtk_vbox_new (FALSE, 0);
3726 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), vbox);
3727 gtk_widget_show (vbox);
3729 /* Priority toggles */
3730 priority_hbox = gtk_hbox_new (TRUE, 0);
3731 high_toggle = hildon_check_button_new (HILDON_SIZE_FINGER_HEIGHT);
3732 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
3733 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
3734 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
3735 medium_toggle = hildon_check_button_new (HILDON_SIZE_FINGER_HEIGHT);
3736 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
3737 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
3738 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
3739 low_toggle = hildon_check_button_new (HILDON_SIZE_FINGER_HEIGHT);
3740 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
3741 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
3742 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
3743 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, FALSE, FALSE, 0);
3744 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, FALSE, FALSE, 0);
3745 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, FALSE, FALSE, 0);
3746 gtk_widget_show_all (priority_hbox);
3747 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
3748 _("mcen_me_editor_message_priority"), priority_hbox);
3749 gtk_widget_show (captioned);
3750 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
3752 /* format selector */
3753 format_selector = hildon_touch_selector_new_text ();
3754 hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (format_selector), _("mcen_me_editor_plain_text"));
3755 hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (format_selector), _("mcen_me_editor_formatted_text"));
3756 format_picker = hildon_picker_button_new (MODEST_EDITABLE_SIZE,
3757 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL);
3758 hildon_picker_button_set_selector (HILDON_PICKER_BUTTON (format_picker), HILDON_TOUCH_SELECTOR (format_selector));
3759 modest_maemo_utils_set_hbutton_layout (title_sizegroup, value_sizegroup,
3760 _("mcen_me_editor_format"), format_picker);
3761 gtk_widget_show_all (format_picker);
3762 gtk_box_pack_start (GTK_BOX (vbox), format_picker, FALSE, FALSE, 0);
3765 g_object_unref (title_sizegroup);
3766 g_object_unref (value_sizegroup);
3767 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_me_message_settings"));
3769 /* Set current values */
3770 switch (priv->priority_flags) {
3771 case TNY_HEADER_FLAG_HIGH_PRIORITY:
3772 hildon_check_button_set_active (HILDON_CHECK_BUTTON (high_toggle), TRUE);
3774 case TNY_HEADER_FLAG_LOW_PRIORITY:
3775 hildon_check_button_set_active (HILDON_CHECK_BUTTON (low_toggle), TRUE);
3778 hildon_check_button_set_active (HILDON_CHECK_BUTTON (medium_toggle), TRUE);
3782 switch (modest_msg_edit_window_get_format (window)) {
3783 case MODEST_MSG_EDIT_FORMAT_TEXT:
3784 hildon_picker_button_set_active (HILDON_PICKER_BUTTON (format_picker), 0);
3785 gtk_widget_set_sensitive (helper.align_picker, FALSE);
3787 case MODEST_MSG_EDIT_FORMAT_HTML:
3789 hildon_picker_button_set_active (HILDON_PICKER_BUTTON (format_picker), 1);
3790 gtk_widget_set_sensitive (helper.align_picker, TRUE);
3794 format_state = modest_msg_edit_window_get_format_state (window);
3795 switch (format_state->justification) {
3796 case GTK_JUSTIFY_RIGHT:
3797 hildon_picker_button_set_active (HILDON_PICKER_BUTTON (helper.align_picker), 2);
3799 case GTK_JUSTIFY_CENTER:
3800 hildon_picker_button_set_active (HILDON_PICKER_BUTTON (helper.align_picker), 1);
3803 hildon_picker_button_set_active (HILDON_PICKER_BUTTON (helper.align_picker), 0);
3807 g_free (format_state);
3809 /* Signal connects */
3810 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3811 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3812 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3813 g_signal_connect (G_OBJECT (format_picker), "value-changed", G_CALLBACK (on_format_picker_value_changed), &helper);
3814 g_signal_connect (G_OBJECT (helper.align_picker), "value-changed",
3815 G_CALLBACK (on_align_picker_value_changed), &helper);
3817 gtk_dialog_run (GTK_DIALOG (dialog));
3819 /* Read new values */
3821 gtk_widget_destroy (dialog);
3822 g_slist_free (helper.priority_group);
3826 static void on_message_settings (GtkAction *action,
3827 ModestMsgEditWindow *window)
3829 modest_msg_edit_window_show_msg_settings_dialog (window);
3833 on_cc_button_toggled (HildonCheckButton *button,
3834 ModestMsgEditWindow *window)
3836 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
3838 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
3839 hildon_check_button_get_active (button));
3843 on_bcc_button_toggled (HildonCheckButton *button,
3844 ModestMsgEditWindow *window)
3846 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
3848 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
3849 hildon_check_button_get_active (button));
3853 on_find_toolbar_button_toggled (HildonCheckButton *button,
3854 ModestMsgEditWindow *window)
3856 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
3857 modest_msg_edit_window_toggle_find_toolbar (MODEST_MSG_EDIT_WINDOW (window),
3858 hildon_check_button_get_active (button));
3863 setup_menu (ModestMsgEditWindow *self)
3865 ModestMsgEditWindowPrivate *priv = NULL;
3867 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
3869 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3871 /* Settings menu buttons */
3872 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_checknames"),
3873 APP_MENU_CALLBACK (modest_ui_actions_on_check_names),
3875 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_undo"),
3876 APP_MENU_CALLBACK (modest_ui_actions_on_undo),
3877 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_undo));
3879 priv->cc_button = hildon_check_button_new (0);
3880 gtk_button_set_label (GTK_BUTTON (priv->cc_button), _("mcen_me_editor_showcc"));
3881 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button),
3883 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->cc_button),
3885 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
3886 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
3887 priv->bcc_button = hildon_check_button_new (0);
3888 gtk_button_set_label (GTK_BUTTON (priv->bcc_button), _("mcen_me_editor_showbcc"));
3889 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button),
3891 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->bcc_button),
3893 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
3894 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
3896 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_attach_inlineimage"),
3897 APP_MENU_CALLBACK (modest_ui_actions_on_insert_image),
3898 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_set_style));
3899 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_remove_attachments"),
3900 APP_MENU_CALLBACK (modest_ui_actions_on_remove_attachments),
3901 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
3902 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_message_settings"),
3903 APP_MENU_CALLBACK (on_message_settings),
3905 priv->find_toolbar_button = hildon_check_button_new (0);
3906 gtk_button_set_label (GTK_BUTTON (priv->find_toolbar_button), _("mcen_me_viewer_find"));
3907 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->find_toolbar_button),
3909 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->find_toolbar_button),
3911 g_signal_connect (G_OBJECT (priv->find_toolbar_button), "toggled",
3912 G_CALLBACK (on_find_toolbar_button_toggled), (gpointer) self);