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;
299 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
300 MODEST_TYPE_MSG_EDIT_WINDOW, \
301 ModestMsgEditWindowPrivate))
303 static GtkWindowClass *parent_class = NULL;
305 /* uncomment the following if you have defined any signals */
306 /* static guint signals[LAST_SIGNAL] = {0}; */
309 modest_msg_edit_window_get_type (void)
311 static GType my_type = 0;
313 static const GTypeInfo my_info = {
314 sizeof(ModestMsgEditWindowClass),
315 NULL, /* base init */
316 NULL, /* base finalize */
317 (GClassInitFunc) modest_msg_edit_window_class_init,
318 NULL, /* class finalize */
319 NULL, /* class data */
320 sizeof(ModestMsgEditWindow),
322 (GInstanceInitFunc) modest_msg_edit_window_init,
325 my_type = g_type_register_static (MODEST_TYPE_HILDON2_WINDOW,
326 "ModestMsgEditWindow",
334 save_state (ModestWindow *self)
336 modest_widget_memory_save (modest_runtime_get_conf(),
337 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
342 restore_settings (ModestMsgEditWindow *self)
344 ModestConf *conf = NULL;
346 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
348 conf = modest_runtime_get_conf ();
350 /* Dim at start clipboard actions */
351 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
352 gtk_action_set_sensitive (action, FALSE);
353 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
354 gtk_action_set_sensitive (action, FALSE);
355 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
356 gtk_action_set_sensitive (action, FALSE);
358 modest_widget_memory_restore (conf, G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
363 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
365 GObjectClass *gobject_class;
366 ModestWindowClass *modest_window_class;
367 gobject_class = (GObjectClass*) klass;
368 modest_window_class = (ModestWindowClass*) klass;
370 parent_class = g_type_class_peek_parent (klass);
371 gobject_class->finalize = modest_msg_edit_window_finalize;
373 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
374 modest_window_class->save_state_func = save_state;
375 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
377 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
381 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
383 ModestMsgEditWindowPrivate *priv;
384 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
386 priv->msg_body = NULL;
388 priv->from_field = NULL;
389 priv->to_field = NULL;
390 priv->cc_field = NULL;
391 priv->bcc_field = NULL;
392 priv->subject_field = NULL;
393 priv->attachments = TNY_LIST (tny_simple_list_new ());
394 priv->images = TNY_LIST (tny_simple_list_new ());
395 priv->images_size = 0;
396 priv->images_count = 0;
399 priv->cc_caption = NULL;
400 priv->bcc_caption = NULL;
401 priv->update_caption_visibility = FALSE;
403 priv->priority_flags = 0;
405 priv->find_toolbar = NULL;
406 priv->last_search = NULL;
408 priv->draft_msg = NULL;
409 priv->outbox_msg = NULL;
410 priv->msg_uid = NULL;
412 priv->can_undo = FALSE;
413 priv->can_redo = FALSE;
414 priv->clipboard_change_handler_id = 0;
415 priv->default_clipboard_change_handler_id = 0;
416 priv->account_removed_handler_id = 0;
417 priv->clipboard_owner_idle = 0;
418 priv->clipboard_text = NULL;
421 priv->scroll_drag_timeout_id = 0;
422 priv->last_upper = 0.0;
424 priv->font_dialog = NULL;
425 priv->app_menu = NULL;
427 if (!is_wp_text_buffer_started) {
428 is_wp_text_buffer_started = TRUE;
429 wp_text_buffer_library_init ();
434 hildon_program_add_window (hildon_program_get_instance(),
440 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
442 static ModestPairList*
443 get_transports (void)
445 GSList *transports = NULL;
447 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
448 GSList *accounts = modest_account_mgr_account_names (account_mgr,
449 TRUE /* only enabled accounts. */);
451 GSList *cursor = accounts;
453 gchar *account_name = cursor->data;
454 gchar *from_string = NULL;
456 from_string = modest_account_mgr_get_from_string (account_mgr,
460 if (from_string && account_name) {
461 gchar *name = account_name;
462 ModestPair *pair = modest_pair_new ((gpointer) name,
463 (gpointer) from_string , TRUE);
464 transports = g_slist_prepend (transports, pair);
467 cursor = cursor->next;
469 g_slist_free (accounts); /* only free the accounts, not the elements,
470 * because they are used in the pairlist */
474 static void window_focus (GtkWindow *window,
478 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
482 scroll_drag_timeout (gpointer userdata)
484 ModestMsgEditWindow *win = (ModestMsgEditWindow *) userdata;
485 ModestMsgEditWindowPrivate *priv;
487 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(win);
489 correct_scroll_without_drag_check (win, TRUE);
491 priv->scroll_drag_timeout_id = 0;
497 correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused)
499 ModestMsgEditWindowPrivate *priv;
502 GdkRectangle rectangle;
506 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
508 if (only_if_focused && !gtk_widget_is_focus (priv->msg_body))
511 insert = gtk_text_buffer_get_insert (priv->text_buffer);
512 gtk_text_buffer_get_iter_at_mark (priv->text_buffer, &iter, insert);
514 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &iter, &rectangle);
515 offset = priv->msg_body->allocation.y;
517 new_value = (offset + rectangle.y);
519 hildon_pannable_area_jump_to (HILDON_PANNABLE_AREA (priv->pannable), -1, new_value);
523 correct_scroll (ModestMsgEditWindow *w)
525 ModestMsgEditWindowPrivate *priv;
527 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
528 if (gtk_grab_get_current () == priv->msg_body) {
529 if (priv->scroll_drag_timeout_id == 0) {
530 priv->scroll_drag_timeout_id = g_timeout_add (500, (GSourceFunc) scroll_drag_timeout,
536 correct_scroll_without_drag_check (w, TRUE);
540 text_buffer_end_user_action (GtkTextBuffer *buffer,
541 ModestMsgEditWindow *userdata)
544 correct_scroll (userdata);
548 text_buffer_mark_set (GtkTextBuffer *buffer,
551 ModestMsgEditWindow *userdata)
553 gtk_text_buffer_begin_user_action (buffer);
554 gtk_text_buffer_end_user_action (buffer);
558 cut_clipboard_check (GtkTextView *text_view,
561 GtkTextBuffer *buffer;
563 buffer = gtk_text_view_get_buffer (text_view);
564 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
565 g_signal_stop_emission_by_name ((gpointer )text_view, "cut-clipboard");
570 copy_clipboard_check (GtkTextView *text_view,
573 GtkTextBuffer *buffer;
575 buffer = gtk_text_view_get_buffer (text_view);
576 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
577 g_signal_stop_emission_by_name ((gpointer )text_view, "copy-clipboard");
582 attachment_deleted (ModestAttachmentsView *attachments_view,
585 modest_msg_edit_window_remove_attachments (MODEST_MSG_EDIT_WINDOW (user_data),
590 connect_signals (ModestMsgEditWindow *obj)
592 ModestMsgEditWindowPrivate *priv;
594 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
596 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
597 G_CALLBACK (text_buffer_refresh_attributes), obj);
598 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
599 G_CALLBACK (text_buffer_can_undo), obj);
600 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
601 G_CALLBACK (text_buffer_can_redo), obj);
602 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
603 G_CALLBACK (body_changed), obj);
604 g_signal_connect (G_OBJECT (priv->text_buffer), "modified-changed",
605 G_CALLBACK (body_changed), obj);
606 g_signal_connect (G_OBJECT (priv->text_buffer), "end-user-action",
607 G_CALLBACK (text_buffer_end_user_action), obj);
608 g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
609 G_CALLBACK (text_buffer_mark_set), obj);
610 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
611 G_CALLBACK (text_buffer_apply_tag), obj);
612 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
613 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
614 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
615 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
616 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
617 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
619 g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
620 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
622 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
623 G_CALLBACK (msg_body_focus), obj);
624 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
625 G_CALLBACK (msg_body_focus), obj);
626 g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
627 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
628 "changed", G_CALLBACK (recpt_field_changed), obj);
629 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
630 "changed", G_CALLBACK (recpt_field_changed), obj);
631 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
632 "changed", G_CALLBACK (recpt_field_changed), obj);
633 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
634 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
635 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
637 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
638 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
640 priv->clipboard_change_handler_id =
641 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
642 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
643 priv->default_clipboard_change_handler_id =
644 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
645 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
647 g_signal_connect (G_OBJECT (priv->msg_body), "cut-clipboard", G_CALLBACK (cut_clipboard_check), NULL);
648 g_signal_connect (G_OBJECT (priv->msg_body), "copy-clipboard", G_CALLBACK (copy_clipboard_check), NULL);
649 g_signal_connect (G_OBJECT (priv->attachments_view), "delete", G_CALLBACK (attachment_deleted), obj);
653 init_wp_text_view_style ()
655 static gboolean initialized = FALSE;
658 gtk_rc_parse_string ("class \"WPTextView\" style \"fremantle-textview\"");
664 init_window (ModestMsgEditWindow *obj)
666 GtkWidget *to_caption, *subject_caption;
667 GtkWidget *main_vbox;
668 ModestMsgEditWindowPrivate *priv;
669 GtkActionGroup *action_group;
670 ModestWindowPrivate *parent_priv;
671 GdkPixbuf *window_icon = NULL;
672 GError *error = NULL;
674 GtkSizeGroup *title_size_group;
675 GtkSizeGroup *value_size_group;
676 GtkWidget *subject_box;
677 GtkWidget *attachment_icon;
678 GtkWidget *window_box;
679 #if (GTK_MINOR_VERSION >= 10)
680 GdkAtom deserialize_type;
683 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
684 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
686 parent_priv->ui_manager = gtk_ui_manager_new();
687 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
688 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
690 /* Add common actions */
691 gtk_action_group_add_actions (action_group,
692 modest_msg_edit_action_entries,
693 G_N_ELEMENTS (modest_msg_edit_action_entries),
695 gtk_action_group_add_actions (action_group,
696 hildon2_msg_edit_action_entries,
697 G_N_ELEMENTS (hildon2_msg_edit_action_entries),
699 gtk_action_group_add_toggle_actions (action_group,
700 modest_msg_edit_toggle_action_entries,
701 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
703 gtk_action_group_add_radio_actions (action_group,
704 modest_msg_edit_alignment_radio_action_entries,
705 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
707 G_CALLBACK (modest_ui_actions_on_change_justify),
709 gtk_action_group_add_radio_actions (action_group,
710 modest_msg_edit_priority_action_entries,
711 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
713 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
715 gtk_action_group_add_radio_actions (action_group,
716 modest_msg_edit_file_format_action_entries,
717 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
718 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
719 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
721 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
722 g_object_unref (action_group);
724 /* Load the UI definition */
725 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
728 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
729 g_clear_error (&error);
732 /* Add accelerators */
733 gtk_window_add_accel_group (GTK_WINDOW (obj),
734 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
736 parent_priv->menubar = NULL;
738 title_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
739 value_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
741 /* Note: This ModestPairList* must exist for as long as the picker
742 * that uses it, because the ModestSelectorPicker uses the ID opaquely,
743 * so it can't know how to manage its memory. */
744 priv->from_field = modest_selector_picker_new (MODEST_EDITABLE_SIZE,
745 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL,
747 modest_maemo_utils_set_hbutton_layout (title_size_group, value_size_group,
748 _("mail_va_from"), priv->from_field);
750 priv->to_field = modest_recpt_editor_new ();
751 priv->cc_field = modest_recpt_editor_new ();
752 priv->bcc_field = modest_recpt_editor_new ();
753 subject_box = gtk_hbox_new (FALSE, 0);
754 priv->priority_icon = gtk_image_new ();
755 gtk_box_pack_start (GTK_BOX (subject_box), priv->priority_icon, FALSE, FALSE, 0);
756 priv->subject_field = hildon_entry_new (MODEST_EDITABLE_SIZE);
757 gtk_entry_set_max_length (GTK_ENTRY (priv->subject_field) ,SUBJECT_MAX_LENGTH);
758 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
759 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
760 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
761 gtk_box_pack_start (GTK_BOX (subject_box), priv->subject_field, TRUE, TRUE, 0);
762 priv->add_attachment_button = gtk_button_new ();
763 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
764 gtk_button_set_relief (GTK_BUTTON (priv->add_attachment_button), GTK_RELIEF_NONE);
765 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
766 gtk_button_set_alignment (GTK_BUTTON (priv->add_attachment_button), 1.0, 0.5);
767 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, HILDON_ICON_SIZE_FINGER);
768 gtk_container_add (GTK_CONTAINER (priv->add_attachment_button), attachment_icon);
769 gtk_box_pack_start (GTK_BOX (subject_box), priv->add_attachment_button, FALSE, FALSE, 0);
770 priv->attachments_view = modest_attachments_view_new (NULL);
772 priv->header_box = gtk_vbox_new (FALSE, 0);
774 to_caption = modest_maemo_utils_create_captioned_with_size_type
775 (title_size_group, value_size_group,
776 _("mail_va_to"), priv->to_field,
777 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
778 priv->cc_caption = modest_maemo_utils_create_captioned_with_size_type
779 (title_size_group, value_size_group,
780 _("mail_va_cc"), priv->cc_field,
781 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
782 priv->bcc_caption = modest_maemo_utils_create_captioned_with_size_type
783 (title_size_group, value_size_group,
784 _("mail_va_hotfix1"), priv->bcc_field,
785 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
786 subject_caption = modest_maemo_utils_create_captioned (title_size_group, value_size_group,
787 _("mail_va_subject"), subject_box);
788 priv->attachments_caption = modest_maemo_utils_create_captioned_with_size_type (title_size_group, value_size_group,
789 _("mail_va_attachment"),
790 priv->attachments_view,
791 HILDON_SIZE_AUTO_WIDTH |
792 HILDON_SIZE_AUTO_HEIGHT);
793 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), value_size_group); */
794 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), value_size_group); */
795 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), value_size_group); */
796 g_object_unref (title_size_group);
797 g_object_unref (value_size_group);
799 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->from_field, FALSE, FALSE, 0);
800 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
801 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
802 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
803 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
804 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
805 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
807 init_wp_text_view_style ();
809 priv->msg_body = wp_text_view_new ();
812 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
813 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
814 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
815 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
816 #if (GTK_MINOR_VERSION >= 10)
817 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
818 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
820 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
821 deserialize_type, TRUE);
823 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
825 priv->find_toolbar = hildon_find_toolbar_new (NULL);
826 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
828 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
830 priv->pannable = hildon_pannable_area_new ();
832 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
834 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
835 priv->frame = gtk_frame_new (NULL);
836 gtk_box_pack_start (GTK_BOX(main_vbox), priv->frame, TRUE, TRUE, 0);
838 hildon_pannable_area_add_with_viewport (HILDON_PANNABLE_AREA (priv->pannable), main_vbox);
839 gtk_widget_show_all (GTK_WIDGET(priv->pannable));
841 window_box = gtk_vbox_new (FALSE, 0);
842 gtk_container_add (GTK_CONTAINER(obj), window_box);
844 gtk_box_pack_start (GTK_BOX (window_box), priv->pannable, TRUE, TRUE, 0);
846 gtk_container_add (GTK_CONTAINER (priv->frame), priv->msg_body);
848 /* Set window icon */
849 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
851 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
852 g_object_unref (window_icon);
857 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
859 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
861 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
862 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
863 priv->clipboard_change_handler_id))
864 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
865 priv->clipboard_change_handler_id);
866 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
867 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
868 priv->default_clipboard_change_handler_id))
869 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
870 priv->default_clipboard_change_handler_id);
872 if (priv->account_removed_handler_id &&
873 g_signal_handler_is_connected (modest_runtime_get_account_store (),
874 priv->account_removed_handler_id))
875 g_signal_handler_disconnect(modest_runtime_get_account_store (),
876 priv->account_removed_handler_id);
880 modest_msg_edit_window_finalize (GObject *obj)
882 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
884 /* Sanity check: shouldn't be needed, the window mgr should
885 call this function before */
886 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
888 if (priv->font_dialog != NULL) {
889 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
892 if (priv->clipboard_text != NULL) {
893 g_free (priv->clipboard_text);
894 priv->clipboard_text = NULL;
897 if (priv->draft_msg != NULL) {
898 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
899 if (TNY_IS_HEADER (header)) {
900 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
901 modest_window_mgr_unregister_header (mgr, header);
903 g_object_unref (priv->draft_msg);
904 priv->draft_msg = NULL;
906 if (priv->outbox_msg != NULL) {
907 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
908 if (TNY_IS_HEADER (header)) {
909 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
910 modest_window_mgr_unregister_header (mgr, header);
912 g_object_unref (priv->outbox_msg);
913 priv->outbox_msg = NULL;
915 if (priv->scroll_drag_timeout_id > 0) {
916 g_source_remove (priv->scroll_drag_timeout_id);
917 priv->scroll_drag_timeout_id = 0;
919 if (priv->clipboard_owner_idle > 0) {
920 g_source_remove (priv->clipboard_owner_idle);
921 priv->clipboard_owner_idle = 0;
923 if (priv->original_account_name)
924 g_free (priv->original_account_name);
925 g_free (priv->msg_uid);
926 g_free (priv->last_search);
927 g_slist_free (priv->font_items_group);
928 g_slist_free (priv->size_items_group);
929 g_object_unref (priv->attachments);
930 g_object_unref (priv->images);
932 /* This had to stay alive for as long as the picker that used it: */
933 modest_pair_list_free (priv->from_field_protos);
935 G_OBJECT_CLASS(parent_class)->finalize (obj);
939 pixbuf_from_stream (TnyStream *stream, const gchar *mime_type, guint64 *stream_size)
941 GdkPixbufLoader *loader;
947 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
949 if (loader == NULL) {
955 tny_stream_reset (TNY_STREAM (stream));
956 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
957 GError *error = NULL;
958 unsigned char read_buffer[128];
960 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
962 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
964 g_error_free (error);
969 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
971 g_object_ref (pixbuf);
972 gdk_pixbuf_loader_close (loader, NULL);
973 g_object_unref (loader);
978 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
979 GdkPixbuf *new_pixbuf;
981 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
982 gdk_pixbuf_get_width (pixbuf);
983 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
984 g_object_unref (pixbuf);
995 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
997 ModestMsgEditWindowPrivate *priv;
1000 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1002 for (iter = tny_list_create_iterator (attachments);
1003 !tny_iterator_is_done (iter);
1004 tny_iterator_next (iter)) {
1005 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1006 const gchar *cid = tny_mime_part_get_content_id (part);
1007 const gchar *mime_type = tny_mime_part_get_content_type (part);
1008 if ((cid != NULL)&&(mime_type != NULL)) {
1009 guint64 stream_size;
1010 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1011 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
1014 g_object_unref (stream);
1016 if (pixbuf != NULL) {
1017 priv->images_count ++;
1018 priv->images_size += stream_size;
1019 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1020 g_object_unref (pixbuf);
1023 g_object_unref (part);
1025 g_object_unref (iter);
1029 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1031 TnyMimePart *parent = NULL;
1032 const gchar *content_type = NULL;
1033 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1035 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1037 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1038 parent = g_object_ref (msg);
1039 } else if (content_type && !g_strcasecmp (content_type, "multipart/mixed")) {
1040 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1043 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1044 iter = tny_list_create_iterator (parts);
1045 while (!tny_iterator_is_done (iter)) {
1047 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1048 content_type = tny_mime_part_get_content_type (part);
1049 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1053 g_object_unref (part);
1055 tny_iterator_next (iter);
1057 g_object_unref (iter);
1058 g_object_unref (parts);
1061 if (parent != NULL) {
1062 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1065 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1066 iter = tny_list_create_iterator (parts);
1067 while (!tny_iterator_is_done (iter)) {
1069 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1070 content_type = tny_mime_part_get_content_type (part);
1071 if (content_type && g_str_has_prefix (content_type, "image/")) {
1072 tny_list_prepend (priv->images, (GObject *) part);
1074 g_object_unref (part);
1075 tny_iterator_next (iter);
1077 g_object_unref (iter);
1078 g_object_unref (parts);
1079 g_object_unref (parent);
1084 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1087 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1089 for (iter = tny_list_create_iterator (attachments) ;
1090 !tny_iterator_is_done (iter);
1091 tny_iterator_next (iter)) {
1092 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1093 const gchar *cid = tny_mime_part_get_content_id (part);
1095 char *invalid = NULL;
1096 gint int_cid = strtol (cid, &invalid, 10);
1097 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1098 priv->next_cid = int_cid + 1;
1101 g_object_unref (part);
1103 g_object_unref (iter);
1107 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1110 gchar *to, *cc, *bcc, *subject;
1112 ModestMsgEditWindowPrivate *priv;
1113 ModestWindowPrivate *parent_priv;
1115 TnyHeaderFlags priority_flags;
1116 TnyFolder *msg_folder;
1117 gboolean is_html = FALSE;
1118 gboolean field_view_set;
1120 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1121 g_return_if_fail (TNY_IS_MSG (msg));
1123 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1124 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1126 header = tny_msg_get_header (msg);
1127 to = tny_header_dup_to (header);
1128 cc = tny_header_dup_cc (header);
1129 bcc = tny_header_dup_bcc (header);
1130 subject = tny_header_dup_subject (header);
1131 priority_flags = tny_header_get_priority (header);
1134 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
1136 field_view_set = TRUE;
1138 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
1139 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1140 gtk_widget_show (priv->cc_caption);
1141 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1142 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1143 gtk_widget_hide (priv->cc_caption);
1144 field_view_set = FALSE;
1146 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button), field_view_set);
1148 field_view_set = TRUE;
1150 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
1151 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1152 gtk_widget_show (priv->bcc_caption);
1153 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1154 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1155 gtk_widget_hide (priv->bcc_caption);
1156 field_view_set = FALSE;
1158 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button), field_view_set);
1162 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1163 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1166 update_window_title (self);
1168 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1169 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1171 if ((body == NULL)||(body[0] == '\0')) {
1173 body = modest_text_utils_convert_to_html ("");
1176 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1177 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1180 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1183 /* Add attachments to the view */
1184 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1185 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1186 if (tny_list_get_length (priv->attachments) == 0) {
1187 gtk_widget_hide (priv->attachments_caption);
1189 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1190 gtk_widget_show_all (priv->attachments_caption);
1192 get_related_images (self, msg);
1193 update_next_cid (self, priv->attachments);
1194 update_next_cid (self, priv->images);
1195 replace_with_images (self, priv->images);
1197 if (preserve_is_rich && !is_html) {
1198 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1199 /* Get the default format required from configuration */
1200 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1201 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1204 /* Set the default focus depending on having already a To: field or not */
1205 if ((!to)||(*to == '\0')) {
1206 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1208 gtk_widget_grab_focus (priv->msg_body);
1211 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1213 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1214 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1216 modest_msg_edit_window_set_modified (self, FALSE);
1218 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1219 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1220 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1221 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1223 if (priv->msg_uid) {
1224 g_free (priv->msg_uid);
1225 priv->msg_uid = NULL;
1228 /* we should set a reference to the incoming message if it is a draft */
1229 msg_folder = tny_msg_get_folder (msg);
1231 if (modest_tny_folder_is_local_folder (msg_folder)) {
1232 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1233 if (type == TNY_FOLDER_TYPE_INVALID)
1234 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1236 if (type == TNY_FOLDER_TYPE_DRAFTS)
1237 priv->draft_msg = g_object_ref(msg);
1238 if (type == TNY_FOLDER_TYPE_OUTBOX)
1239 priv->outbox_msg = g_object_ref(msg);
1240 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1242 g_object_unref (msg_folder);
1252 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
1255 GList *item_children, *node;
1256 GtkWidget *bin_child;
1258 bin_child = gtk_bin_get_child (GTK_BIN(item));
1260 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
1262 for (node = item_children; node != NULL; node = g_list_next (node)) {
1263 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
1264 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
1267 g_list_free (item_children);
1271 menu_tool_button_dont_expand (GtkMenuToolButton *item)
1274 GList *item_children, *node;
1276 box = gtk_bin_get_child (GTK_BIN (item));
1277 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
1278 item_children = gtk_container_get_children (GTK_CONTAINER (box));
1280 for (node = item_children; node != NULL; node = g_list_next (node)) {
1281 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
1282 if (GTK_IS_TOGGLE_BUTTON (node->data))
1283 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
1284 else if (GTK_IS_BUTTON (node->data))
1285 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
1287 g_list_free (item_children);
1292 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1294 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1295 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1296 GtkWidget *placeholder;
1297 GtkWidget *tool_item;
1302 GtkWidget *sizes_menu;
1303 GtkWidget *fonts_menu;
1304 GSList *radio_group = NULL;
1305 GSList *node = NULL;
1309 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1310 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1312 /* Font color placeholder */
1313 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1314 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1317 priv->font_color_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1318 priv->font_color_button = hildon_color_button_new ();
1319 GTK_WIDGET_UNSET_FLAGS (priv->font_color_toolitem, GTK_CAN_FOCUS);
1320 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1321 gtk_container_add (GTK_CONTAINER (priv->font_color_toolitem), priv->font_color_button);
1322 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1323 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1324 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->font_color_toolitem), insert_index);
1325 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1327 G_CALLBACK (modest_msg_edit_window_color_button_change),
1330 /* Font size and face placeholder */
1331 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1332 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1334 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1335 priv->size_tool_button_label = gtk_label_new (NULL);
1336 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1337 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1338 size_text,"</span>", NULL);
1339 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1341 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
1342 sizes_menu = gtk_menu_new ();
1343 priv->size_items_group = NULL;
1345 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1346 GtkWidget *size_menu_item;
1348 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1349 size_menu_item = gtk_radio_menu_item_new_with_label (radio_group, size_text);
1350 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (size_menu_item));
1351 gtk_menu_shell_append (GTK_MENU_SHELL (sizes_menu), size_menu_item);
1352 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (size_menu_item), (wp_font_size[size_index] == 12));
1353 gtk_widget_show (size_menu_item);
1355 priv->size_items_group = g_slist_prepend (priv->size_items_group, size_menu_item);
1359 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1360 GtkWidget *item = (GtkWidget *) node->data;
1361 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_size_change),
1365 priv->size_items_group = g_slist_reverse (priv->size_items_group);
1366 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), sizes_menu);
1367 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1368 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1369 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1370 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1371 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1372 priv->font_size_toolitem = tool_item;
1375 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1376 priv->font_tool_button_label = gtk_label_new (NULL);
1377 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1378 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1380 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
1381 fonts_menu = gtk_menu_new ();
1382 priv->font_items_group = NULL;
1384 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1385 GtkWidget *font_menu_item;
1386 GtkWidget *child_label;
1388 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
1389 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
1390 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
1391 wp_get_font_name (font_index), "</span>", NULL);
1392 gtk_label_set_markup (GTK_LABEL (child_label), markup);
1395 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
1396 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
1397 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
1398 gtk_widget_show (font_menu_item);
1400 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
1403 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1404 GtkWidget *item = (GtkWidget *) node->data;
1405 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
1408 priv->font_items_group = g_slist_reverse (priv->font_items_group);
1409 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
1410 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1411 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1412 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1413 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1414 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1415 priv->font_face_toolitem = tool_item;
1417 /* Set expand and homogeneous for remaining items */
1418 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
1419 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1420 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1421 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1422 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1423 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1424 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1425 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1426 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1428 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1429 will not show the tool items added to the placeholders) */
1430 gtk_widget_show_all (parent_priv->toolbar);
1432 /* Set the no show all *after* showing all items. We do not
1433 want the toolbar to be shown with a show all because it
1434 could go agains the gconf setting regarding showing or not
1435 the toolbar of the editor window */
1436 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1442 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, gboolean preserve_is_rich)
1445 ModestWindowPrivate *parent_priv;
1446 ModestMsgEditWindowPrivate *priv;
1447 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1448 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1449 ModestWindowMgr *mgr = NULL;
1451 g_return_val_if_fail (msg, NULL);
1452 g_return_val_if_fail (account_name, NULL);
1454 mgr = modest_runtime_get_window_mgr ();
1456 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1458 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1459 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1461 /* Menubar. Update the state of some toggles */
1462 priv->from_field_protos = get_transports ();
1463 modest_selector_picker_set_pair_list (MODEST_SELECTOR_PICKER (priv->from_field), priv->from_field_protos);
1464 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1465 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1467 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1468 hildon_touch_selector_get_current_text
1469 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1470 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1471 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1474 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1476 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1478 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1480 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1482 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1483 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1484 /* Add common dimming rules */
1485 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1486 modest_msg_edit_window_toolbar_dimming_entries,
1487 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1488 MODEST_WINDOW (obj));
1489 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_toolitem,
1490 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1491 MODEST_WINDOW (obj));
1492 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1493 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1494 MODEST_WINDOW (obj));
1495 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1496 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1497 MODEST_WINDOW (obj));
1498 /* Insert dimming rules group for this window */
1499 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1500 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1502 /* Setup app menu */
1503 setup_menu (MODEST_MSG_EDIT_WINDOW (obj));
1505 /* Checks the dimming rules */
1506 g_object_unref (toolbar_rules_group);
1507 g_object_unref (clipboard_rules_group);
1508 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1510 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1512 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1513 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1514 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1515 priv->update_caption_visibility = TRUE;
1517 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1519 /* Track account-removed signal, this window should be closed
1520 in the case we're creating a mail associated to the account
1522 priv->account_removed_handler_id =
1523 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1525 G_CALLBACK(on_account_removed),
1528 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1530 return (ModestWindow*) obj;
1534 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1536 GString **string_buffer = (GString **) user_data;
1538 *string_buffer = g_string_append (*string_buffer, buffer);
1544 * @result: A new string which should be freed with g_free().
1547 get_formatted_data (ModestMsgEditWindow *edit_window)
1549 ModestMsgEditWindowPrivate *priv;
1550 GString *string_buffer = g_string_new ("");
1552 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1554 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1556 modest_text_utils_hyperlinkify (string_buffer);
1558 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1560 return g_string_free (string_buffer, FALSE);
1565 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1568 const gchar *account_name;
1569 ModestMsgEditWindowPrivate *priv;
1570 TnyIterator *att_iter;
1572 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1574 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1576 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1577 g_return_val_if_fail (account_name, NULL);
1580 /* don't free these (except from) */
1581 data = g_slice_new0 (MsgData);
1582 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1584 data->account_name = g_strdup (account_name);
1585 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1586 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1587 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1588 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1589 if (priv->draft_msg) {
1590 data->draft_msg = g_object_ref (priv->draft_msg);
1591 } else if (priv->outbox_msg) {
1592 data->draft_msg = g_object_ref (priv->outbox_msg);
1594 data->draft_msg = NULL;
1597 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1599 gtk_text_buffer_get_bounds (buf, &b, &e);
1600 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1602 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1603 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1605 data->html_body = NULL;
1607 /* deep-copy the data */
1608 att_iter = tny_list_create_iterator (priv->attachments);
1609 data->attachments = NULL;
1610 while (!tny_iterator_is_done (att_iter)) {
1611 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1612 if (!(TNY_IS_MIME_PART(part))) {
1613 g_warning ("strange data in attachment list");
1614 g_object_unref (part);
1615 tny_iterator_next (att_iter);
1618 data->attachments = g_list_append (data->attachments,
1620 tny_iterator_next (att_iter);
1622 g_object_unref (att_iter);
1624 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1625 att_iter = tny_list_create_iterator (priv->images);
1626 data->images = NULL;
1627 while (!tny_iterator_is_done (att_iter)) {
1628 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1630 if (!(TNY_IS_MIME_PART(part))) {
1631 g_warning ("strange data in attachment list");
1632 g_object_unref (part);
1633 tny_iterator_next (att_iter);
1636 cid = tny_mime_part_get_content_id (part);
1638 gchar *image_tag_id;
1639 GtkTextTag *image_tag;
1641 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1642 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1643 g_free (image_tag_id);
1645 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1647 ((gtk_text_iter_has_tag (&iter, image_tag))||
1648 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1649 data->images = g_list_append (data->images,
1650 g_object_ref (part));
1652 g_object_unref (part);
1653 tny_iterator_next (att_iter);
1655 g_object_unref (att_iter);
1657 data->priority_flags = priv->priority_flags;
1664 unref_gobject (GObject *obj, gpointer data)
1666 if (!G_IS_OBJECT(obj))
1668 g_object_unref (obj);
1672 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1675 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1683 g_free (data->from);
1684 g_free (data->subject);
1685 g_free (data->plain_body);
1686 g_free (data->html_body);
1687 g_free (data->account_name);
1689 if (data->draft_msg != NULL) {
1690 g_object_unref (data->draft_msg);
1691 data->draft_msg = NULL;
1694 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1695 g_list_free (data->attachments);
1696 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1697 g_list_free (data->images);
1699 g_slice_free (MsgData, data);
1703 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1705 guint64 *parts_size)
1707 ModestMsgEditWindowPrivate *priv;
1709 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1711 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1713 /* TODO: add images */
1714 *parts_size += priv->images_size;
1715 *parts_count += priv->images_count;
1720 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1723 ModestMsgEditWindowPrivate *priv = NULL;
1724 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1726 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1728 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1730 return MODEST_MSG_EDIT_FORMAT_HTML;
1732 return MODEST_MSG_EDIT_FORMAT_TEXT;
1736 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1737 ModestMsgEditFormat format)
1739 ModestMsgEditWindowPrivate *priv;
1741 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1742 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1745 case MODEST_MSG_EDIT_FORMAT_HTML:
1746 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1748 case MODEST_MSG_EDIT_FORMAT_TEXT:
1749 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1752 g_return_if_reached ();
1756 ModestMsgEditFormatState *
1757 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1759 ModestMsgEditFormatState *format_state = NULL;
1760 ModestMsgEditWindowPrivate *priv;
1761 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1763 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1764 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1766 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1768 format_state = g_new0 (ModestMsgEditFormatState, 1);
1769 format_state->bold = buffer_format->bold&0x1;
1770 format_state->italics = buffer_format->italic&0x1;
1771 format_state->bullet = buffer_format->bullet&0x1;
1772 format_state->color = buffer_format->color;
1773 format_state->font_size = buffer_format->font_size;
1774 format_state->font_family = wp_get_font_name (buffer_format->font);
1775 format_state->justification = buffer_format->justification;
1776 g_free (buffer_format);
1778 return format_state;
1783 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1784 const ModestMsgEditFormatState *format_state)
1786 ModestMsgEditWindowPrivate *priv;
1787 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1788 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1789 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1790 g_return_if_fail (format_state != NULL);
1792 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1793 gtk_widget_grab_focus (priv->msg_body);
1794 buffer_format->bold = (format_state->bold != FALSE);
1795 buffer_format->italic = (format_state->italics != FALSE);
1796 buffer_format->color = format_state->color;
1797 buffer_format->font_size = format_state->font_size;
1798 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1799 buffer_format->justification = format_state->justification;
1800 buffer_format->bullet = format_state->bullet;
1802 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1804 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1805 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1806 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1807 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1808 buffer_format->cs.font = (buffer_format->font != current_format->font);
1809 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1810 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1812 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1813 if (buffer_format->cs.bold) {
1814 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
1815 GINT_TO_POINTER (buffer_format->bold&0x1));
1817 if (buffer_format->cs.italic) {
1818 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
1819 GINT_TO_POINTER (buffer_format->italic&0x1));
1821 if (buffer_format->cs.color) {
1822 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1823 GINT_TO_POINTER (&(buffer_format->color)));
1825 if (buffer_format->cs.font_size) {
1826 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1827 GINT_TO_POINTER (buffer_format->font_size));
1829 if (buffer_format->cs.justification) {
1830 switch (buffer_format->justification) {
1831 case GTK_JUSTIFY_LEFT:
1832 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
1833 GINT_TO_POINTER(TRUE));
1835 case GTK_JUSTIFY_CENTER:
1836 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
1837 GINT_TO_POINTER(TRUE));
1839 case GTK_JUSTIFY_RIGHT:
1840 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
1841 GINT_TO_POINTER(TRUE));
1848 if (buffer_format->cs.font) {
1849 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1850 GINT_TO_POINTER (buffer_format->font));
1852 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1853 if (buffer_format->cs.bullet) {
1854 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
1855 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
1857 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1859 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
1861 g_free (buffer_format);
1862 g_free (current_format);
1864 /* Check dimming rules */
1865 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1866 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1870 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1872 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1874 ModestWindowPrivate *parent_priv;
1875 ModestMsgEditWindowPrivate *priv;
1876 GtkWidget *new_size_menuitem;
1877 GtkWidget *new_font_menuitem;
1879 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1880 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1882 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1883 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu");
1884 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1885 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1887 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatPlainTextMenu");
1888 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1889 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1892 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1894 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1895 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1897 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1898 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1900 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
1901 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
1904 switch (buffer_format->justification)
1906 case GTK_JUSTIFY_LEFT:
1907 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
1909 case GTK_JUSTIFY_CENTER:
1910 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
1912 case GTK_JUSTIFY_RIGHT:
1913 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
1920 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
1922 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1923 G_CALLBACK (modest_msg_edit_window_color_button_change),
1925 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1926 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1927 G_CALLBACK (modest_msg_edit_window_color_button_change),
1930 new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group,
1931 buffer_format->font_size))->data);
1932 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1936 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1937 markup = g_strconcat ("<span font_family='Sans'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1938 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1940 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1941 G_CALLBACK (modest_msg_edit_window_size_change),
1943 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
1944 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
1945 G_CALLBACK (modest_msg_edit_window_size_change),
1949 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
1950 buffer_format->font))->data);
1951 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
1955 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
1956 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1957 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1959 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
1960 G_CALLBACK (modest_msg_edit_window_font_change),
1962 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
1963 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
1964 G_CALLBACK (modest_msg_edit_window_font_change),
1968 g_free (buffer_format);
1972 #ifdef MODEST_HILDON_VERSION_0
1974 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
1977 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1978 ModestMsgEditWindowPrivate *priv;
1979 GtkWidget *dialog = NULL;
1981 GdkColor *new_color = NULL;
1983 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1984 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1986 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1987 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
1988 g_free (buffer_format);
1990 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
1991 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1992 if (new_color != NULL) {
1993 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1994 (gpointer) new_color);
1997 gtk_widget_destroy (dialog);
2002 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2005 ModestMsgEditWindowPrivate *priv;
2006 GtkWidget *dialog = NULL;
2008 GdkColor *old_color = NULL;
2009 const GdkColor *new_color = NULL;
2011 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2012 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2014 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2015 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2017 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2018 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2019 if (new_color != NULL)
2020 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2022 gtk_widget_destroy (dialog);
2028 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2031 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2032 ModestMsgEditWindowPrivate *priv;
2033 GtkWidget *dialog = NULL;
2035 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2036 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2038 dialog = hildon_color_chooser_new ();
2039 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2040 g_free (buffer_format);
2042 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2044 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2045 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2048 gtk_widget_destroy (dialog);
2053 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2056 ModestMsgEditWindowPrivate *priv;
2057 GtkWidget *dialog = NULL;
2058 GdkColor *old_color = NULL;
2060 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2061 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2063 dialog = hildon_color_chooser_new ();
2064 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2066 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2068 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2069 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2071 gtk_widget_destroy (dialog);
2074 #endif /*!MODEST_HILDON_VERSION_0*/
2079 create_stream_for_uri (const gchar* uri)
2084 TnyStream *result = NULL;
2086 GnomeVFSHandle *handle = NULL;
2087 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2088 if (test == GNOME_VFS_OK) {
2089 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2090 /* Streams over OBEX (Bluetooth) are not seekable but
2091 * we expect them to be (we might need to read them
2092 * several times). So if this is a Bluetooth URI just
2093 * read the whole file into memory (this is not a fast
2094 * protocol so we can assume that these files are not
2095 * going to be very big) */
2096 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2097 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2098 TnyStream *memstream = tny_camel_mem_stream_new ();
2099 tny_stream_write_to_stream (vfssstream, memstream);
2100 g_object_unref (vfssstream);
2103 result = vfssstream;
2111 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2114 ModestMsgEditWindowPrivate *priv;
2115 GtkWidget *dialog = NULL;
2117 GSList *uris = NULL;
2118 GSList *uri_node = NULL;
2120 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2122 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2123 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2124 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2126 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2128 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2129 GTK_WINDOW (dialog), GTK_WINDOW (window));
2131 response = gtk_dialog_run (GTK_DIALOG (dialog));
2133 case GTK_RESPONSE_OK:
2134 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2139 gtk_widget_destroy (dialog);
2141 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2143 GnomeVFSHandle *handle = NULL;
2144 GnomeVFSResult result;
2145 GtkTextIter position;
2146 GtkTextMark *insert_mark;
2148 uri = (const gchar *) uri_node->data;
2149 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2150 if (result == GNOME_VFS_OK) {
2152 GnomeVFSFileInfo *info;
2153 gchar *filename, *basename, *escaped_filename;
2154 TnyMimePart *mime_part;
2156 const gchar *mime_type = NULL;
2157 GnomeVFSURI *vfs_uri;
2158 guint64 stream_size;
2160 gnome_vfs_close (handle);
2161 vfs_uri = gnome_vfs_uri_new (uri);
2163 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2164 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2165 g_free (escaped_filename);
2166 gnome_vfs_uri_unref (vfs_uri);
2167 info = gnome_vfs_file_info_new ();
2169 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2170 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2172 mime_type = gnome_vfs_file_info_get_mime_type (info);
2174 mime_part = tny_platform_factory_new_mime_part
2175 (modest_runtime_get_platform_factory ());
2177 TnyStream *stream = create_stream_for_uri (uri);
2179 if (stream == NULL) {
2181 modest_platform_information_banner (NULL, NULL, dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2183 g_object_unref (mime_part);
2184 gnome_vfs_file_info_unref (info);
2188 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2190 content_id = g_strdup_printf ("%d", priv->next_cid);
2191 tny_mime_part_set_content_id (mime_part, content_id);
2192 g_free (content_id);
2195 basename = g_path_get_basename (filename);
2196 tny_mime_part_set_filename (mime_part, basename);
2199 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
2201 if (pixbuf != NULL) {
2202 priv->images_size += stream_size;
2203 priv->images_count ++;
2204 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2205 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2206 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
2207 g_object_unref (pixbuf);
2210 tny_list_prepend (priv->images, (GObject *) mime_part);
2211 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2213 g_object_unref (mime_part);
2214 gnome_vfs_file_info_unref (info);
2223 on_attach_file_response (GtkDialog *dialog,
2227 GSList *uris = NULL;
2229 GnomeVFSFileSize total_size, allowed_size;
2230 ModestMsgEditWindow *window;
2231 ModestMsgEditWindowPrivate *priv;
2236 case GTK_RESPONSE_OK:
2237 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2243 window = MODEST_MSG_EDIT_WINDOW (user_data);
2244 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2246 /* allowed size is the maximum size - what's already there */
2247 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2248 &att_num, &att_size);
2249 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2252 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2254 const gchar *uri = (const gchar *) uri_node->data;
2257 modest_msg_edit_window_attach_file_one (window, uri, allowed_size);
2259 if (total_size > allowed_size) {
2260 g_warning ("%s: total size: %u",
2261 __FUNCTION__, (unsigned int)total_size);
2264 allowed_size -= total_size;
2266 g_slist_foreach (uris, (GFunc) g_free, NULL);
2267 g_slist_free (uris);
2269 gtk_widget_destroy (GTK_WIDGET (dialog));
2273 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2275 GtkWidget *dialog = NULL;
2276 ModestMsgEditWindowPrivate *priv;
2278 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2280 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2282 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2285 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window),
2286 GTK_FILE_CHOOSER_ACTION_OPEN);
2287 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2288 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2289 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2290 GTK_WINDOW (dialog), GTK_WINDOW (window));
2292 /* Connect to response & show */
2293 g_signal_connect (dialog, "response",
2294 G_CALLBACK (on_attach_file_response), window);
2295 gtk_widget_show (dialog);
2300 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2302 GnomeVFSFileSize allowed_size)
2305 GnomeVFSHandle *handle = NULL;
2306 ModestMsgEditWindowPrivate *priv;
2307 GnomeVFSResult result;
2308 GnomeVFSFileSize size = 0;
2309 g_return_val_if_fail (window, 0);
2310 g_return_val_if_fail (uri, 0);
2312 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2314 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2315 if (result == GNOME_VFS_OK) {
2316 TnyMimePart *mime_part;
2318 const gchar *mime_type = NULL;
2320 gchar *escaped_filename;
2323 GnomeVFSFileInfo *info;
2324 GnomeVFSURI *vfs_uri;
2326 gnome_vfs_close (handle);
2327 vfs_uri = gnome_vfs_uri_new (uri);
2330 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2331 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2332 g_free (escaped_filename);
2333 gnome_vfs_uri_unref (vfs_uri);
2335 info = gnome_vfs_file_info_new ();
2337 if (gnome_vfs_get_file_info (uri,
2339 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2341 mime_type = gnome_vfs_file_info_get_mime_type (info);
2342 mime_part = tny_platform_factory_new_mime_part
2343 (modest_runtime_get_platform_factory ());
2345 /* try to get the attachment's size; this may fail for weird
2346 * file systems, like obex, upnp... */
2347 if (allowed_size != 0 &&
2348 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2350 if (size > allowed_size) {
2351 modest_platform_information_banner (NULL, NULL,
2352 dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2356 g_warning ("%s: could not get attachment size", __FUNCTION__);
2358 stream = create_stream_for_uri (uri);
2360 if (stream == NULL) {
2362 modest_platform_information_banner (NULL, NULL, dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2364 g_object_unref (mime_part);
2365 gnome_vfs_file_info_unref (info);
2369 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2370 g_object_unref (stream);
2372 content_id = g_strdup_printf ("%d", priv->next_cid);
2373 tny_mime_part_set_content_id (mime_part, content_id);
2374 g_free (content_id);
2377 basename = g_path_get_basename (filename);
2378 tny_mime_part_set_filename (mime_part, basename);
2381 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2382 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2384 info->size == 0, info->size);
2385 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2386 gtk_widget_show_all (priv->attachments_caption);
2387 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2389 g_object_unref (mime_part);
2390 gnome_vfs_file_info_unref (info);
2397 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2400 ModestMsgEditWindowPrivate *priv;
2403 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2404 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2406 if (att_list == NULL) {
2407 att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2409 g_object_ref (att_list);
2412 if (tny_list_get_length (att_list) == 0) {
2413 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2415 gboolean dialog_response;
2416 gchar *message = NULL;
2417 gchar *filename = NULL;
2419 if (tny_list_get_length (att_list) == 1) {
2421 iter = tny_list_create_iterator (att_list);
2422 part = (TnyMimePart *) tny_iterator_get_current (iter);
2423 g_object_unref (iter);
2424 if (TNY_IS_MSG (part)) {
2425 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2427 filename = tny_header_dup_subject (header);
2428 g_object_unref (header);
2430 if (filename == NULL) {
2431 filename = g_strdup (_("mail_va_no_subject"));
2434 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2436 g_object_unref (part);
2438 filename = g_strdup ("");
2440 message = g_strdup_printf (ngettext("emev_nc_delete_attachment",
2441 "emev_nc_delete_attachments",
2442 tny_list_get_length (att_list)), filename);
2445 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
2449 if (dialog_response != GTK_RESPONSE_OK) {
2450 g_object_unref (att_list);
2454 for (iter = tny_list_create_iterator (att_list);
2455 !tny_iterator_is_done (iter);
2456 tny_iterator_next (iter)) {
2457 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2458 const gchar *att_id;
2459 tny_list_remove (priv->attachments, (GObject *) mime_part);
2461 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2463 if (tny_list_get_length (priv->attachments) == 0)
2464 gtk_widget_hide (priv->attachments_caption);
2465 att_id = tny_mime_part_get_content_id (mime_part);
2467 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2469 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2470 g_object_unref (mime_part);
2472 g_object_unref (iter);
2475 g_object_unref (att_list);
2477 /* if the last attachment has been removed, focus the Subject: field */
2478 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2479 gtk_widget_grab_focus (priv->subject_field);
2483 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2486 ModestMsgEditWindowPrivate *priv;
2487 GdkColor *new_color;
2488 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2490 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2491 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2494 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2496 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2498 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2500 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2505 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
2508 ModestMsgEditWindowPrivate *priv;
2509 gint new_size_index;
2510 ModestMsgEditWindow *window;
2513 window = MODEST_MSG_EDIT_WINDOW (userdata);
2514 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2515 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2517 if (gtk_check_menu_item_get_active (menu_item)) {
2519 WPTextBufferFormat format;
2521 memset (&format, 0, sizeof (format));
2522 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2524 label = gtk_bin_get_child (GTK_BIN (menu_item));
2526 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
2527 format.cs.font_size = TRUE;
2528 format.cs.text_position = TRUE;
2529 format.cs.font = TRUE;
2530 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
2531 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2533 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2534 GINT_TO_POINTER (wp_get_font_size_index (new_size_index, 12))))
2535 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2537 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2538 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
2539 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2545 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
2548 ModestMsgEditWindowPrivate *priv;
2549 gint new_font_index;
2550 ModestMsgEditWindow *window;
2553 window = MODEST_MSG_EDIT_WINDOW (userdata);
2554 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2555 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2557 if (gtk_check_menu_item_get_active (menu_item)) {
2560 label = gtk_bin_get_child (GTK_BIN (menu_item));
2562 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
2564 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2565 GINT_TO_POINTER(new_font_index)))
2566 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2568 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2569 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2570 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2576 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2579 ModestMsgEditWindowPrivate *priv = NULL;
2580 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2582 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2583 if (!priv->update_caption_visibility)
2586 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2588 gtk_widget_show (priv->cc_caption);
2590 gtk_widget_hide (priv->cc_caption);
2592 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2596 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2599 ModestMsgEditWindowPrivate *priv = NULL;
2600 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2602 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2603 if (!priv->update_caption_visibility)
2606 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2608 gtk_widget_show (priv->bcc_caption);
2610 gtk_widget_hide (priv->bcc_caption);
2612 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2616 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2617 ModestRecptEditor *editor)
2619 ModestMsgEditWindowPrivate *priv;
2621 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2622 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2624 /* we check for low-mem; in that case, show a warning, and don't allow
2625 * for the addressbook
2627 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2630 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2632 if (editor == NULL) {
2633 GtkWidget *view_focus;
2634 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2636 /* This code should be kept in sync with ModestRecptEditor. The
2637 textview inside the recpt editor is the one that really gets the
2638 focus. As it's inside a scrolled window, and this one inside the
2639 hbox recpt editor inherits from, we'll need to go up in the
2640 hierarchy to know if the text view is part of the recpt editor
2641 or if it's a different text entry */
2643 if (gtk_widget_get_parent (view_focus)) {
2644 GtkWidget *first_parent;
2646 first_parent = gtk_widget_get_parent (view_focus);
2647 if (gtk_widget_get_parent (first_parent) &&
2648 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2649 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2654 editor = MODEST_RECPT_EDITOR (priv->to_field);
2658 modest_address_book_select_addresses (editor);
2663 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2665 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2667 modest_msg_edit_window_open_addressbook (window, NULL);
2671 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2672 gboolean show_toolbar)
2674 ModestWindowPrivate *parent_priv;
2676 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2677 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2679 /* We can not just use the code of
2680 modest_msg_edit_window_setup_toolbar because it has a
2681 mixture of both initialization and creation code. */
2683 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2685 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2689 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2690 TnyHeaderFlags priority_flags)
2692 ModestMsgEditWindowPrivate *priv;
2693 ModestWindowPrivate *parent_priv;
2695 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2697 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2698 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2700 if (priv->priority_flags != priority_flags) {
2701 GtkAction *priority_action = NULL;
2703 priv->priority_flags = priority_flags;
2705 switch (priority_flags) {
2706 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2707 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2708 MODEST_HEADER_ICON_HIGH,
2709 HILDON_ICON_SIZE_XSMALL);
2710 gtk_widget_show (priv->priority_icon);
2711 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2712 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2714 case TNY_HEADER_FLAG_LOW_PRIORITY:
2715 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2716 MODEST_HEADER_ICON_LOW,
2717 HILDON_ICON_SIZE_XSMALL);
2718 gtk_widget_show (priv->priority_icon);
2719 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2720 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2723 gtk_widget_hide (priv->priority_icon);
2724 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2725 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2728 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2729 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2734 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2737 ModestMsgEditWindowPrivate *priv;
2738 ModestWindowPrivate *parent_priv;
2739 gint current_format;
2741 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2743 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2744 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2746 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2747 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2749 if (current_format != file_format) {
2750 switch (file_format) {
2751 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2752 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2753 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
2755 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2759 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2760 response = gtk_dialog_run (GTK_DIALOG (dialog));
2761 gtk_widget_destroy (dialog);
2762 if (response == GTK_RESPONSE_OK) {
2763 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2765 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
2766 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
2771 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2772 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2773 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2778 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2781 ModestMsgEditWindowPrivate *priv;
2782 WPTextBufferFormat oldfmt, fmt;
2783 gint old_position = 0;
2787 GdkColor *color = NULL;
2788 gboolean bold, bold_set, italic, italic_set;
2789 gboolean underline, underline_set;
2790 gboolean strikethrough, strikethrough_set;
2791 gboolean position_set;
2792 gboolean font_size_set, font_set, color_set;
2795 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2796 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2798 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2799 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
2800 GTK_WINDOW(dialog), GTK_WINDOW (window));
2802 /* First we get the currently selected font information */
2803 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2805 switch (oldfmt.text_position) {
2806 case TEXT_POSITION_NORMAL:
2809 case TEXT_POSITION_SUPERSCRIPT:
2817 g_object_set (G_OBJECT (dialog),
2818 "bold", oldfmt.bold != FALSE,
2819 "bold-set", !oldfmt.cs.bold,
2820 "underline", oldfmt.underline != FALSE,
2821 "underline-set", !oldfmt.cs.underline,
2822 "italic", oldfmt.italic != FALSE,
2823 "italic-set", !oldfmt.cs.italic,
2824 "strikethrough", oldfmt.strikethrough != FALSE,
2825 "strikethrough-set", !oldfmt.cs.strikethrough,
2826 "color", &oldfmt.color,
2827 "color-set", !oldfmt.cs.color,
2828 "size", wp_font_size[oldfmt.font_size],
2829 "size-set", !oldfmt.cs.font_size,
2830 "position", old_position,
2831 "position-set", !oldfmt.cs.text_position,
2832 "family", wp_get_font_name (oldfmt.font),
2833 "family-set", !oldfmt.cs.font,
2836 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2837 GTK_WINDOW (dialog), GTK_WINDOW (window));
2838 gtk_widget_show_all (dialog);
2839 priv->font_dialog = dialog;
2840 response = gtk_dialog_run (GTK_DIALOG (dialog));
2841 priv->font_dialog = NULL;
2842 if (response == GTK_RESPONSE_OK) {
2844 g_object_get( dialog,
2846 "bold-set", &bold_set,
2847 "underline", &underline,
2848 "underline-set", &underline_set,
2850 "italic-set", &italic_set,
2851 "strikethrough", &strikethrough,
2852 "strikethrough-set", &strikethrough_set,
2854 "color-set", &color_set,
2856 "size-set", &font_size_set,
2857 "family", &font_name,
2858 "family-set", &font_set,
2859 "position", &position,
2860 "position-set", &position_set,
2865 if (response == GTK_RESPONSE_OK) {
2866 memset(&fmt, 0, sizeof(fmt));
2872 fmt.italic = italic;
2873 fmt.cs.italic = TRUE;
2875 if (underline_set) {
2876 fmt.underline = underline;
2877 fmt.cs.underline = TRUE;
2879 if (strikethrough_set) {
2880 fmt.strikethrough = strikethrough;
2881 fmt.cs.strikethrough = TRUE;
2886 ? TEXT_POSITION_NORMAL
2887 : ( ( position == 1 )
2888 ? TEXT_POSITION_SUPERSCRIPT
2889 : TEXT_POSITION_SUBSCRIPT );
2890 fmt.cs.text_position = TRUE;
2891 fmt.font_size = oldfmt.font_size;
2895 fmt.cs.color = TRUE;
2898 fmt.font = wp_get_font_index(font_name,
2903 if (font_size_set) {
2904 fmt.cs.font_size = TRUE;
2905 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
2907 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2908 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2910 gtk_widget_destroy (dialog);
2912 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2916 modest_msg_edit_window_undo (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_undo (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));
2930 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
2932 ModestMsgEditWindowPrivate *priv;
2934 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2935 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2937 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
2939 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2940 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2945 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
2947 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2949 priv->can_undo = can_undo;
2953 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
2955 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2957 priv->can_redo = can_redo;
2961 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
2963 ModestMsgEditWindowPrivate *priv;
2964 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2965 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2967 return priv->can_undo;
2971 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
2973 ModestMsgEditWindowPrivate *priv;
2974 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2975 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2977 return priv->can_redo;
2982 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
2985 GtkTextIter match_start, match_end;
2987 if (image_id == NULL)
2990 gtk_text_buffer_get_start_iter (buffer, &iter);
2992 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
2993 GSList *tags = gtk_text_iter_get_tags (&match_start);
2995 for (node = tags; node != NULL; node = g_slist_next (node)) {
2996 GtkTextTag *tag = (GtkTextTag *) node->data;
2997 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
2998 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
2999 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3001 offset = gtk_text_iter_get_offset (&match_start);
3002 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3003 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3007 gtk_text_iter_forward_char (&iter);
3012 message_is_empty (ModestMsgEditWindow *window)
3014 ModestMsgEditWindowPrivate *priv = NULL;
3016 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3017 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3019 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3020 * so we can ignore markup.
3022 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3025 count = gtk_text_buffer_get_char_count (buf);
3031 msg_body_focus (GtkWidget *focus,
3032 GdkEventFocus *event,
3036 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3037 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3038 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3043 recpt_field_changed (GtkTextBuffer *buffer,
3044 ModestMsgEditWindow *editor)
3046 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3047 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3051 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3053 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3054 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3058 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3061 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3062 GtkTextBuffer *buffer;
3064 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3065 gtk_text_buffer_set_modified (buffer, modified);
3066 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3067 gtk_text_buffer_set_modified (buffer, modified);
3068 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3069 gtk_text_buffer_set_modified (buffer, modified);
3070 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3074 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3076 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3077 const char *account_name;
3078 GtkTextBuffer *buffer;
3080 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3081 if (gtk_text_buffer_get_modified (buffer))
3083 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3084 if (gtk_text_buffer_get_modified (buffer))
3086 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3087 if (gtk_text_buffer_get_modified (buffer))
3089 if (gtk_text_buffer_get_modified (priv->text_buffer))
3091 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3092 if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3103 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3105 ModestMsgEditWindowPrivate *priv = NULL;
3107 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3108 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3110 /* check if there's no recipient added */
3111 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3112 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3113 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3114 /* no recipient contents, then select contacts */
3115 modest_msg_edit_window_open_addressbook (window, NULL);
3119 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3120 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3123 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3124 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3127 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3128 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3132 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3133 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3134 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3141 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3142 ModestMsgEditWindow *window)
3144 modest_msg_edit_window_offer_attach_file (window);
3148 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3150 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3152 return priv->clipboard_text;
3156 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3158 ModestMsgEditWindow *window)
3160 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3161 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3163 if (!GTK_WIDGET_VISIBLE (window))
3166 g_object_ref (window);
3167 text = gtk_clipboard_wait_for_text (selection_clipboard);
3169 if (priv->clipboard_text != NULL) {
3170 g_free (priv->clipboard_text);
3172 priv->clipboard_text = text;
3174 if (GTK_WIDGET_VISIBLE (window)) {
3175 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3177 g_object_unref (window);
3180 static gboolean clipboard_owner_change_idle (gpointer userdata)
3182 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3183 ModestMsgEditWindowPrivate *priv;
3185 gdk_threads_enter ();
3186 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3187 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3189 priv->clipboard_owner_idle = 0;
3190 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3191 gdk_threads_leave ();
3197 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3199 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3200 if (priv->clipboard_owner_idle == 0) {
3201 priv->clipboard_owner_idle = g_idle_add (clipboard_owner_change_idle, window);
3206 subject_field_move_cursor (GtkEntry *entry,
3207 GtkMovementStep step,
3212 if (!GTK_WIDGET_VISIBLE (window))
3215 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3219 update_window_title (ModestMsgEditWindow *window)
3221 ModestMsgEditWindowPrivate *priv = NULL;
3222 const gchar *subject;
3224 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3225 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3226 if (subject == NULL || subject[0] == '\0')
3227 subject = _("mail_va_new_email");
3229 gtk_window_set_title (GTK_WINDOW (window), subject);
3234 subject_field_changed (GtkEditable *editable,
3235 ModestMsgEditWindow *window)
3237 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3238 update_window_title (window);
3239 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3240 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3241 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3245 subject_field_insert_text (GtkEditable *editable,
3247 gint new_text_length,
3249 ModestMsgEditWindow *window)
3251 GString *result = g_string_new ("");
3253 gint result_len = 0;
3254 const gchar *entry_text = NULL;
3257 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3258 old_length = g_utf8_strlen (entry_text, -1);
3260 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3261 gunichar c = g_utf8_get_char_validated (current, 8);
3262 /* Invalid unichar, stop */
3268 result = g_string_append_unichar (result, c);
3272 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3273 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3276 /* Prevent endless recursion */
3277 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3278 g_signal_emit_by_name (editable, "insert-text",
3279 (gpointer) result->str, (gpointer) result->len,
3280 (gpointer) position, (gpointer) window);
3281 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3285 if (result_len + old_length > 1000) {
3286 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3287 dgettext("hildon-common-strings",
3288 "ckdg_ib_maximum_characters_reached"));
3290 g_string_free (result, TRUE);
3294 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3297 ModestMsgEditWindowPrivate *priv = NULL;
3299 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3300 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3302 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3305 gtk_widget_show_all (priv->find_toolbar);
3306 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3308 gtk_widget_hide_all (priv->find_toolbar);
3309 gtk_widget_grab_focus (priv->msg_body);
3314 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3316 GtkTextIter *match_start,
3317 GtkTextIter *match_end)
3319 GtkTextIter end_iter;
3320 gchar *str_casefold;
3323 gchar *range_casefold;
3326 gboolean result = FALSE;
3333 gtk_text_iter_forward_to_end (&end_iter);
3335 str_casefold = g_utf8_casefold (str, -1);
3336 str_chars_n = strlen (str);
3338 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3339 range_casefold = g_utf8_casefold (range_text, -1);
3340 range_chars_n = strlen (range_casefold);
3342 if (range_chars_n < str_chars_n) {
3343 g_free (str_casefold);
3344 g_free (range_text);
3345 g_free (range_casefold);
3349 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3350 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3351 if (!g_utf8_collate (range_subtext, str_casefold)) {
3352 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3354 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3355 match_start, match_end, NULL);
3356 g_free (found_text);
3358 g_free (range_subtext);
3362 g_free (str_casefold);
3363 g_free (range_text);
3364 g_free (range_casefold);
3371 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3372 ModestMsgEditWindow *window)
3374 gchar *current_search = NULL;
3375 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3377 GtkTextIter selection_start, selection_end;
3378 GtkTextIter match_start, match_end;
3379 gboolean continue_search = FALSE;
3381 if (message_is_empty (window)) {
3382 g_free (priv->last_search);
3383 priv->last_search = NULL;
3384 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3388 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3389 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3390 g_free (current_search);
3391 g_free (priv->last_search);
3392 priv->last_search = NULL;
3393 /* Information banner about empty search */
3394 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-common-strings", "ecdg_ib_find_rep_enter_text"));
3398 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3399 continue_search = TRUE;
3401 g_free (priv->last_search);
3402 priv->last_search = g_strdup (current_search);
3405 if (continue_search) {
3406 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3407 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3408 &match_start, &match_end);
3410 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_search_complete"));
3412 GtkTextIter buffer_start;
3413 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3414 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3415 &match_start, &match_end);
3417 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_no_matches"));
3420 /* Mark as selected the string found in search */
3422 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3423 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3424 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3426 g_free (priv->last_search);
3427 priv->last_search = NULL;
3429 g_free (current_search);
3433 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3435 ModestMsgEditWindowPrivate *priv;
3437 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3442 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3445 ModestMsgEditWindowPrivate *priv;
3447 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3452 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3453 ModestMsgEditWindow *window)
3455 modest_msg_edit_window_toggle_find_toolbar (window, FALSE);
3459 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3462 ModestMsgEditWindowPrivate *priv;
3463 TnyHeader *header = NULL;
3465 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3466 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3468 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3469 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3471 if (priv->draft_msg != NULL) {
3472 g_object_unref (priv->draft_msg);
3475 if (draft != NULL) {
3476 g_object_ref (draft);
3477 header = tny_msg_get_header (draft);
3478 if (priv->msg_uid) {
3479 g_free (priv->msg_uid);
3480 priv->msg_uid = NULL;
3482 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3483 if (GTK_WIDGET_REALIZED (window)) {
3484 if (!modest_window_mgr_register_window (mgr, MODEST_WINDOW (window), NULL)) {
3485 gtk_widget_destroy (GTK_WIDGET (window));
3491 priv->draft_msg = draft;
3495 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3496 GtkTextIter *start, GtkTextIter *end,
3499 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3500 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3503 if (tag == NULL) return;
3504 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3505 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3506 replace_with_images (window, priv->images);
3511 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3514 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3516 g_return_if_fail (TNY_IS_MIME_PART (part));
3517 tny_list_prepend (priv->attachments, (GObject *) part);
3518 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3519 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3520 gtk_widget_show_all (priv->attachments_caption);
3521 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3525 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3527 ModestMsgEditWindowPrivate *priv;
3529 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3530 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3532 return priv->msg_uid;
3536 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3537 ModestMsgEditWindowWidgetType widget_type)
3539 ModestMsgEditWindowPrivate *priv;
3541 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3542 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3544 switch (widget_type) {
3545 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3546 return priv->msg_body;
3548 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3549 return priv->to_field;
3551 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3552 return priv->cc_field;
3554 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3555 return priv->bcc_field;
3557 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3558 return priv->subject_field;
3560 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3561 return priv->attachments_view;
3569 remove_tags (WPTextBuffer *buffer)
3571 GtkTextIter start, end;
3573 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3574 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3576 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3580 on_account_removed (TnyAccountStore *account_store,
3581 TnyAccount *account,
3584 /* Do nothing if it's a store account, because we use the
3585 transport to send the messages */
3586 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3587 const gchar *parent_acc = NULL;
3588 const gchar *our_acc = NULL;
3590 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3591 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3592 /* Close this window if I'm showing a message of the removed account */
3593 if (strcmp (parent_acc, our_acc) == 0)
3594 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3598 typedef struct _MessageSettingsHelper {
3599 ModestMsgEditWindow *window;
3600 GSList *priority_group;
3601 GSList *format_group;
3602 } MessageSettingsHelper;
3605 on_priority_toggle (GtkToggleButton *button,
3606 MessageSettingsHelper *helper)
3609 ModestMsgEditWindowPrivate *priv;
3611 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3612 if (gtk_toggle_button_get_active (button)) {
3614 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3615 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3616 if ((node_button != button) &&
3617 gtk_toggle_button_get_active (node_button)) {
3618 gtk_toggle_button_set_active (node_button, FALSE);
3621 if (priv->priority_flags != (TnyHeaderFlags) g_object_get_data (G_OBJECT (button), "priority"))
3622 modest_msg_edit_window_set_priority_flags (helper->window,
3624 g_object_get_data (G_OBJECT (button),
3628 gboolean found = FALSE;
3629 /* If no one is active, activate it again */
3630 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3631 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3632 if (gtk_toggle_button_get_active (node_button)) {
3638 gtk_toggle_button_set_active (button, TRUE);
3644 on_format_toggle (GtkToggleButton *button,
3645 MessageSettingsHelper *helper)
3648 ModestMsgEditWindowPrivate *priv;
3649 ModestMsgEditFormat old_format;
3651 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3652 old_format = modest_msg_edit_window_get_format (helper->window);
3653 if (gtk_toggle_button_get_active (button)) {
3655 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
3656 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3657 if ((node_button != button) &&
3658 gtk_toggle_button_get_active (node_button)) {
3659 gtk_toggle_button_set_active (node_button, FALSE);
3662 if (old_format != (ModestMsgEditFormat) g_object_get_data (G_OBJECT (button), "format")) {
3663 modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (helper->window),
3664 GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button), "file-format")));
3668 gboolean found = FALSE;
3669 /* If no one is active, activate it again */
3670 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
3671 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3672 if (gtk_toggle_button_get_active (node_button)) {
3678 gtk_toggle_button_set_active (button, TRUE);
3685 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
3689 GtkWidget *priority_hbox;
3690 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
3691 GtkWidget *captioned;
3692 GtkSizeGroup *title_sizegroup, *value_sizegroup;
3693 GtkWidget *format_hbox;
3694 GtkWidget *html_toggle, *text_toggle;
3695 ModestMsgEditWindowPrivate *priv;
3696 MessageSettingsHelper helper = {0,};
3698 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3699 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3700 helper.window = window;
3701 helper.priority_group = NULL;
3703 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3704 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3706 dialog = gtk_dialog_new ();
3707 vbox = gtk_vbox_new (FALSE, 0);
3708 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), vbox);
3709 gtk_widget_show (vbox);
3711 /* Priority toggles */
3712 priority_hbox = gtk_hbox_new (TRUE, 0);
3713 high_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3714 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
3715 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
3716 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
3717 medium_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3718 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
3719 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
3720 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
3721 low_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3722 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
3723 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
3724 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
3725 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, TRUE, TRUE, 0);
3726 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, TRUE, TRUE, 0);
3727 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, TRUE, TRUE, 0);
3728 gtk_widget_show_all (priority_hbox);
3729 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
3730 _("mcen_me_editor_message_priority"), priority_hbox);
3731 gtk_widget_show (captioned);
3732 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
3734 /* format toggles */
3735 format_hbox = gtk_hbox_new (TRUE, 0);
3736 html_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3737 gtk_button_set_label (GTK_BUTTON (html_toggle), _("mcen_me_editor_formatted_text"));
3738 helper.format_group = g_slist_prepend (helper.format_group, html_toggle);
3739 g_object_set_data (G_OBJECT (html_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_HTML));
3740 g_object_set_data (G_OBJECT (html_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_FORMATTED_TEXT));
3741 text_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3742 gtk_button_set_label (GTK_BUTTON (text_toggle), _("mcen_me_editor_plain_text"));
3743 helper.format_group = g_slist_prepend (helper.format_group, text_toggle);
3744 g_object_set_data (G_OBJECT (text_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_TEXT));
3745 g_object_set_data (G_OBJECT (text_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_PLAIN_TEXT));
3746 gtk_box_pack_start (GTK_BOX (format_hbox), html_toggle, TRUE, TRUE, 0);
3747 gtk_box_pack_start (GTK_BOX (format_hbox), text_toggle, TRUE, TRUE, 0);
3748 gtk_widget_show_all (format_hbox);
3749 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
3750 _("mcen_me_editor_format"), format_hbox);
3751 gtk_widget_show (captioned);
3752 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
3755 g_object_unref (title_sizegroup);
3756 g_object_unref (value_sizegroup);
3757 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_me_message_settings"));
3759 /* Set current values */
3760 switch (priv->priority_flags) {
3761 case TNY_HEADER_FLAG_HIGH_PRIORITY:
3762 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (high_toggle), TRUE);
3764 case TNY_HEADER_FLAG_LOW_PRIORITY:
3765 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (low_toggle), TRUE);
3768 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (medium_toggle), TRUE);
3772 switch (modest_msg_edit_window_get_format (window)) {
3773 case MODEST_MSG_EDIT_FORMAT_TEXT:
3774 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_toggle), TRUE);
3776 case MODEST_MSG_EDIT_FORMAT_HTML:
3778 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (html_toggle), TRUE);
3782 /* Signal connects */
3783 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3784 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3785 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3786 g_signal_connect (G_OBJECT (html_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
3787 g_signal_connect (G_OBJECT (text_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
3789 gtk_dialog_run (GTK_DIALOG (dialog));
3791 /* Read new values */
3793 gtk_widget_destroy (dialog);
3794 g_slist_free (helper.priority_group);
3798 static void on_message_settings (GtkAction *action,
3799 ModestMsgEditWindow *window)
3801 modest_msg_edit_window_show_msg_settings_dialog (window);
3805 on_cc_button_toggled (HildonCheckButton *button,
3806 ModestMsgEditWindow *window)
3808 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
3810 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
3811 hildon_check_button_get_active (button));
3815 on_bcc_button_toggled (HildonCheckButton *button,
3816 ModestMsgEditWindow *window)
3818 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
3820 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
3821 hildon_check_button_get_active (button));
3825 setup_menu (ModestMsgEditWindow *self)
3827 ModestMsgEditWindowPrivate *priv = NULL;
3829 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
3831 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3833 /* Settings menu buttons */
3834 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_checknames"), NULL,
3835 APP_MENU_CALLBACK (modest_ui_actions_on_check_names),
3837 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_undo"), "<Ctrl>z",
3838 APP_MENU_CALLBACK (modest_ui_actions_on_undo),
3839 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_undo));
3841 priv->cc_button = hildon_check_button_new (0);
3842 gtk_button_set_label (GTK_BUTTON (priv->cc_button), _("mcen_me_editor_showcc"));
3843 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button),
3845 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->cc_button),
3847 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
3848 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
3849 priv->bcc_button = hildon_check_button_new (0);
3850 gtk_button_set_label (GTK_BUTTON (priv->bcc_button), _("mcen_me_editor_showbcc"));
3851 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button),
3853 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->bcc_button),
3855 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
3856 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
3858 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_attach_inlineimage"), NULL,
3859 APP_MENU_CALLBACK (modest_ui_actions_on_insert_image),
3860 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_set_style));
3861 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_remove_attachments"), NULL,
3862 APP_MENU_CALLBACK (modest_ui_actions_on_remove_attachments),
3863 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
3864 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_message_settings"), NULL,
3865 APP_MENU_CALLBACK (on_message_settings),
3867 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_viewer_find"), "<Ctrl>f",
3868 APP_MENU_CALLBACK (modest_ui_actions_on_toggle_find_in_page),