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", "emev_nc_delete_attachments",
2441 tny_list_get_length (att_list)), filename);
2444 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window), message);
2447 if (dialog_response != GTK_RESPONSE_OK) {
2448 g_object_unref (att_list);
2451 hildon_banner_show_information (NULL, NULL, _("mcen_me_inbox_remove_attachments"));
2453 for (iter = tny_list_create_iterator (att_list);
2454 !tny_iterator_is_done (iter);
2455 tny_iterator_next (iter)) {
2456 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2457 const gchar *att_id;
2458 tny_list_remove (priv->attachments, (GObject *) mime_part);
2460 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2462 if (tny_list_get_length (priv->attachments) == 0)
2463 gtk_widget_hide (priv->attachments_caption);
2464 att_id = tny_mime_part_get_content_id (mime_part);
2466 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2468 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2469 g_object_unref (mime_part);
2471 g_object_unref (iter);
2474 g_object_unref (att_list);
2476 /* if the last attachment has been removed, focus the Subject: field */
2477 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2478 gtk_widget_grab_focus (priv->subject_field);
2482 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2485 ModestMsgEditWindowPrivate *priv;
2486 GdkColor *new_color;
2487 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2489 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2490 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2493 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2495 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2497 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2499 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2504 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
2507 ModestMsgEditWindowPrivate *priv;
2508 gint new_size_index;
2509 ModestMsgEditWindow *window;
2512 window = MODEST_MSG_EDIT_WINDOW (userdata);
2513 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2514 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2516 if (gtk_check_menu_item_get_active (menu_item)) {
2518 WPTextBufferFormat format;
2520 memset (&format, 0, sizeof (format));
2521 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2523 label = gtk_bin_get_child (GTK_BIN (menu_item));
2525 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
2526 format.cs.font_size = TRUE;
2527 format.cs.text_position = TRUE;
2528 format.cs.font = TRUE;
2529 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
2530 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2532 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2533 GINT_TO_POINTER (wp_get_font_size_index (new_size_index, 12))))
2534 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2536 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2537 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
2538 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2544 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
2547 ModestMsgEditWindowPrivate *priv;
2548 gint new_font_index;
2549 ModestMsgEditWindow *window;
2552 window = MODEST_MSG_EDIT_WINDOW (userdata);
2553 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2554 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2556 if (gtk_check_menu_item_get_active (menu_item)) {
2559 label = gtk_bin_get_child (GTK_BIN (menu_item));
2561 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
2563 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2564 GINT_TO_POINTER(new_font_index)))
2565 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2567 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2568 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2569 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2575 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2578 ModestMsgEditWindowPrivate *priv = NULL;
2579 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2581 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2582 if (!priv->update_caption_visibility)
2585 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2587 gtk_widget_show (priv->cc_caption);
2589 gtk_widget_hide (priv->cc_caption);
2591 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2595 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2598 ModestMsgEditWindowPrivate *priv = NULL;
2599 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2601 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2602 if (!priv->update_caption_visibility)
2605 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2607 gtk_widget_show (priv->bcc_caption);
2609 gtk_widget_hide (priv->bcc_caption);
2611 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2615 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2616 ModestRecptEditor *editor)
2618 ModestMsgEditWindowPrivate *priv;
2620 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2621 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2623 /* we check for low-mem; in that case, show a warning, and don't allow
2624 * for the addressbook
2626 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2629 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2631 if (editor == NULL) {
2632 GtkWidget *view_focus;
2633 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2635 /* This code should be kept in sync with ModestRecptEditor. The
2636 textview inside the recpt editor is the one that really gets the
2637 focus. As it's inside a scrolled window, and this one inside the
2638 hbox recpt editor inherits from, we'll need to go up in the
2639 hierarchy to know if the text view is part of the recpt editor
2640 or if it's a different text entry */
2642 if (gtk_widget_get_parent (view_focus)) {
2643 GtkWidget *first_parent;
2645 first_parent = gtk_widget_get_parent (view_focus);
2646 if (gtk_widget_get_parent (first_parent) &&
2647 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2648 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2653 editor = MODEST_RECPT_EDITOR (priv->to_field);
2657 modest_address_book_select_addresses (editor);
2662 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2664 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2666 modest_msg_edit_window_open_addressbook (window, NULL);
2670 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2671 gboolean show_toolbar)
2673 ModestWindowPrivate *parent_priv;
2675 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2676 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2678 /* We can not just use the code of
2679 modest_msg_edit_window_setup_toolbar because it has a
2680 mixture of both initialization and creation code. */
2682 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2684 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2688 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2689 TnyHeaderFlags priority_flags)
2691 ModestMsgEditWindowPrivate *priv;
2692 ModestWindowPrivate *parent_priv;
2694 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2696 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2697 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2699 if (priv->priority_flags != priority_flags) {
2700 GtkAction *priority_action = NULL;
2702 priv->priority_flags = priority_flags;
2704 switch (priority_flags) {
2705 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2706 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2707 MODEST_HEADER_ICON_HIGH,
2708 HILDON_ICON_SIZE_XSMALL);
2709 gtk_widget_show (priv->priority_icon);
2710 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2711 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2713 case TNY_HEADER_FLAG_LOW_PRIORITY:
2714 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2715 MODEST_HEADER_ICON_LOW,
2716 HILDON_ICON_SIZE_XSMALL);
2717 gtk_widget_show (priv->priority_icon);
2718 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2719 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2722 gtk_widget_hide (priv->priority_icon);
2723 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2724 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2727 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2728 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2733 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2736 ModestMsgEditWindowPrivate *priv;
2737 ModestWindowPrivate *parent_priv;
2738 gint current_format;
2740 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2742 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2743 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2745 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2746 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2748 if (current_format != file_format) {
2749 switch (file_format) {
2750 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2751 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2752 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
2754 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2758 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2759 response = gtk_dialog_run (GTK_DIALOG (dialog));
2760 gtk_widget_destroy (dialog);
2761 if (response == GTK_RESPONSE_OK) {
2762 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2764 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
2765 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
2770 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2771 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2772 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2777 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2780 ModestMsgEditWindowPrivate *priv;
2781 WPTextBufferFormat oldfmt, fmt;
2782 gint old_position = 0;
2786 GdkColor *color = NULL;
2787 gboolean bold, bold_set, italic, italic_set;
2788 gboolean underline, underline_set;
2789 gboolean strikethrough, strikethrough_set;
2790 gboolean position_set;
2791 gboolean font_size_set, font_set, color_set;
2794 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2795 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2797 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2798 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
2799 GTK_WINDOW(dialog), GTK_WINDOW (window));
2801 /* First we get the currently selected font information */
2802 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2804 switch (oldfmt.text_position) {
2805 case TEXT_POSITION_NORMAL:
2808 case TEXT_POSITION_SUPERSCRIPT:
2816 g_object_set (G_OBJECT (dialog),
2817 "bold", oldfmt.bold != FALSE,
2818 "bold-set", !oldfmt.cs.bold,
2819 "underline", oldfmt.underline != FALSE,
2820 "underline-set", !oldfmt.cs.underline,
2821 "italic", oldfmt.italic != FALSE,
2822 "italic-set", !oldfmt.cs.italic,
2823 "strikethrough", oldfmt.strikethrough != FALSE,
2824 "strikethrough-set", !oldfmt.cs.strikethrough,
2825 "color", &oldfmt.color,
2826 "color-set", !oldfmt.cs.color,
2827 "size", wp_font_size[oldfmt.font_size],
2828 "size-set", !oldfmt.cs.font_size,
2829 "position", old_position,
2830 "position-set", !oldfmt.cs.text_position,
2831 "family", wp_get_font_name (oldfmt.font),
2832 "family-set", !oldfmt.cs.font,
2835 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2836 GTK_WINDOW (dialog), GTK_WINDOW (window));
2837 gtk_widget_show_all (dialog);
2838 priv->font_dialog = dialog;
2839 response = gtk_dialog_run (GTK_DIALOG (dialog));
2840 priv->font_dialog = NULL;
2841 if (response == GTK_RESPONSE_OK) {
2843 g_object_get( dialog,
2845 "bold-set", &bold_set,
2846 "underline", &underline,
2847 "underline-set", &underline_set,
2849 "italic-set", &italic_set,
2850 "strikethrough", &strikethrough,
2851 "strikethrough-set", &strikethrough_set,
2853 "color-set", &color_set,
2855 "size-set", &font_size_set,
2856 "family", &font_name,
2857 "family-set", &font_set,
2858 "position", &position,
2859 "position-set", &position_set,
2864 if (response == GTK_RESPONSE_OK) {
2865 memset(&fmt, 0, sizeof(fmt));
2871 fmt.italic = italic;
2872 fmt.cs.italic = TRUE;
2874 if (underline_set) {
2875 fmt.underline = underline;
2876 fmt.cs.underline = TRUE;
2878 if (strikethrough_set) {
2879 fmt.strikethrough = strikethrough;
2880 fmt.cs.strikethrough = TRUE;
2885 ? TEXT_POSITION_NORMAL
2886 : ( ( position == 1 )
2887 ? TEXT_POSITION_SUPERSCRIPT
2888 : TEXT_POSITION_SUBSCRIPT );
2889 fmt.cs.text_position = TRUE;
2890 fmt.font_size = oldfmt.font_size;
2894 fmt.cs.color = TRUE;
2897 fmt.font = wp_get_font_index(font_name,
2902 if (font_size_set) {
2903 fmt.cs.font_size = TRUE;
2904 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
2906 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2907 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2909 gtk_widget_destroy (dialog);
2911 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2915 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2917 ModestMsgEditWindowPrivate *priv;
2919 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2920 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2922 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2924 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2925 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2929 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
2931 ModestMsgEditWindowPrivate *priv;
2933 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2934 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2936 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
2938 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2939 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2944 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
2946 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2948 priv->can_undo = can_undo;
2952 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
2954 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2956 priv->can_redo = can_redo;
2960 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
2962 ModestMsgEditWindowPrivate *priv;
2963 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2964 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2966 return priv->can_undo;
2970 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
2972 ModestMsgEditWindowPrivate *priv;
2973 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2974 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2976 return priv->can_redo;
2981 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
2984 GtkTextIter match_start, match_end;
2986 if (image_id == NULL)
2989 gtk_text_buffer_get_start_iter (buffer, &iter);
2991 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
2992 GSList *tags = gtk_text_iter_get_tags (&match_start);
2994 for (node = tags; node != NULL; node = g_slist_next (node)) {
2995 GtkTextTag *tag = (GtkTextTag *) node->data;
2996 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
2997 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
2998 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3000 offset = gtk_text_iter_get_offset (&match_start);
3001 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3002 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3006 gtk_text_iter_forward_char (&iter);
3011 message_is_empty (ModestMsgEditWindow *window)
3013 ModestMsgEditWindowPrivate *priv = NULL;
3015 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3016 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3018 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3019 * so we can ignore markup.
3021 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3024 count = gtk_text_buffer_get_char_count (buf);
3030 msg_body_focus (GtkWidget *focus,
3031 GdkEventFocus *event,
3035 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3036 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3037 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3042 recpt_field_changed (GtkTextBuffer *buffer,
3043 ModestMsgEditWindow *editor)
3045 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3046 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3050 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3052 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3053 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3057 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3060 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3061 GtkTextBuffer *buffer;
3063 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3064 gtk_text_buffer_set_modified (buffer, modified);
3065 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3066 gtk_text_buffer_set_modified (buffer, modified);
3067 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3068 gtk_text_buffer_set_modified (buffer, modified);
3069 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3073 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3075 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3076 const char *account_name;
3077 GtkTextBuffer *buffer;
3079 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3080 if (gtk_text_buffer_get_modified (buffer))
3082 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3083 if (gtk_text_buffer_get_modified (buffer))
3085 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3086 if (gtk_text_buffer_get_modified (buffer))
3088 if (gtk_text_buffer_get_modified (priv->text_buffer))
3090 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3091 if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3102 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3104 ModestMsgEditWindowPrivate *priv = NULL;
3106 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3107 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3109 /* check if there's no recipient added */
3110 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3111 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3112 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3113 /* no recipient contents, then select contacts */
3114 modest_msg_edit_window_open_addressbook (window, NULL);
3118 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3119 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3122 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3123 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3126 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3127 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3131 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3132 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3133 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3140 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3141 ModestMsgEditWindow *window)
3143 modest_msg_edit_window_offer_attach_file (window);
3147 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3149 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3151 return priv->clipboard_text;
3155 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3157 ModestMsgEditWindow *window)
3159 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3160 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3162 if (!GTK_WIDGET_VISIBLE (window))
3165 g_object_ref (window);
3166 text = gtk_clipboard_wait_for_text (selection_clipboard);
3168 if (priv->clipboard_text != NULL) {
3169 g_free (priv->clipboard_text);
3171 priv->clipboard_text = text;
3173 if (GTK_WIDGET_VISIBLE (window)) {
3174 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3176 g_object_unref (window);
3179 static gboolean clipboard_owner_change_idle (gpointer userdata)
3181 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3182 ModestMsgEditWindowPrivate *priv;
3184 gdk_threads_enter ();
3185 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3186 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3188 priv->clipboard_owner_idle = 0;
3189 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3190 gdk_threads_leave ();
3196 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3198 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3199 if (priv->clipboard_owner_idle == 0) {
3200 priv->clipboard_owner_idle = g_idle_add (clipboard_owner_change_idle, window);
3205 subject_field_move_cursor (GtkEntry *entry,
3206 GtkMovementStep step,
3211 if (!GTK_WIDGET_VISIBLE (window))
3214 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3218 update_window_title (ModestMsgEditWindow *window)
3220 ModestMsgEditWindowPrivate *priv = NULL;
3221 const gchar *subject;
3223 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3224 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3225 if (subject == NULL || subject[0] == '\0')
3226 subject = _("mail_va_new_email");
3228 gtk_window_set_title (GTK_WINDOW (window), subject);
3233 subject_field_changed (GtkEditable *editable,
3234 ModestMsgEditWindow *window)
3236 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3237 update_window_title (window);
3238 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3239 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3240 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3244 subject_field_insert_text (GtkEditable *editable,
3246 gint new_text_length,
3248 ModestMsgEditWindow *window)
3250 GString *result = g_string_new ("");
3252 gint result_len = 0;
3253 const gchar *entry_text = NULL;
3256 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3257 old_length = g_utf8_strlen (entry_text, -1);
3259 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3260 gunichar c = g_utf8_get_char_validated (current, 8);
3261 /* Invalid unichar, stop */
3267 result = g_string_append_unichar (result, c);
3271 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3272 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3275 /* Prevent endless recursion */
3276 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3277 g_signal_emit_by_name (editable, "insert-text",
3278 (gpointer) result->str, (gpointer) result->len,
3279 (gpointer) position, (gpointer) window);
3280 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3284 if (result_len + old_length > 1000) {
3285 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3286 dgettext("hildon-common-strings",
3287 "ckdg_ib_maximum_characters_reached"));
3289 g_string_free (result, TRUE);
3293 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3296 ModestMsgEditWindowPrivate *priv = NULL;
3298 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3299 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3301 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3304 gtk_widget_show_all (priv->find_toolbar);
3305 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3307 gtk_widget_hide_all (priv->find_toolbar);
3308 gtk_widget_grab_focus (priv->msg_body);
3313 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3315 GtkTextIter *match_start,
3316 GtkTextIter *match_end)
3318 GtkTextIter end_iter;
3319 gchar *str_casefold;
3322 gchar *range_casefold;
3325 gboolean result = FALSE;
3332 gtk_text_iter_forward_to_end (&end_iter);
3334 str_casefold = g_utf8_casefold (str, -1);
3335 str_chars_n = strlen (str);
3337 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3338 range_casefold = g_utf8_casefold (range_text, -1);
3339 range_chars_n = strlen (range_casefold);
3341 if (range_chars_n < str_chars_n) {
3342 g_free (str_casefold);
3343 g_free (range_text);
3344 g_free (range_casefold);
3348 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3349 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3350 if (!g_utf8_collate (range_subtext, str_casefold)) {
3351 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3353 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3354 match_start, match_end, NULL);
3355 g_free (found_text);
3357 g_free (range_subtext);
3361 g_free (str_casefold);
3362 g_free (range_text);
3363 g_free (range_casefold);
3370 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3371 ModestMsgEditWindow *window)
3373 gchar *current_search = NULL;
3374 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3376 GtkTextIter selection_start, selection_end;
3377 GtkTextIter match_start, match_end;
3378 gboolean continue_search = FALSE;
3380 if (message_is_empty (window)) {
3381 g_free (priv->last_search);
3382 priv->last_search = NULL;
3383 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3387 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3388 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3389 g_free (current_search);
3390 g_free (priv->last_search);
3391 priv->last_search = NULL;
3392 /* Information banner about empty search */
3393 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-common-strings", "ecdg_ib_find_rep_enter_text"));
3397 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3398 continue_search = TRUE;
3400 g_free (priv->last_search);
3401 priv->last_search = g_strdup (current_search);
3404 if (continue_search) {
3405 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3406 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3407 &match_start, &match_end);
3409 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_search_complete"));
3411 GtkTextIter buffer_start;
3412 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3413 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3414 &match_start, &match_end);
3416 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_no_matches"));
3419 /* Mark as selected the string found in search */
3421 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3422 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3423 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3425 g_free (priv->last_search);
3426 priv->last_search = NULL;
3428 g_free (current_search);
3432 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3434 ModestMsgEditWindowPrivate *priv;
3436 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3441 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3444 ModestMsgEditWindowPrivate *priv;
3446 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3451 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3452 ModestMsgEditWindow *window)
3454 modest_msg_edit_window_toggle_find_toolbar (window, FALSE);
3458 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3461 ModestMsgEditWindowPrivate *priv;
3462 TnyHeader *header = NULL;
3464 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3465 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3467 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3468 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3470 if (priv->draft_msg != NULL) {
3471 g_object_unref (priv->draft_msg);
3474 if (draft != NULL) {
3475 g_object_ref (draft);
3476 header = tny_msg_get_header (draft);
3477 if (priv->msg_uid) {
3478 g_free (priv->msg_uid);
3479 priv->msg_uid = NULL;
3481 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3482 if (GTK_WIDGET_REALIZED (window)) {
3483 if (!modest_window_mgr_register_window (mgr, MODEST_WINDOW (window), NULL)) {
3484 gtk_widget_destroy (GTK_WIDGET (window));
3490 priv->draft_msg = draft;
3494 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3495 GtkTextIter *start, GtkTextIter *end,
3498 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3499 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3502 if (tag == NULL) return;
3503 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3504 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3505 replace_with_images (window, priv->images);
3510 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3513 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3515 g_return_if_fail (TNY_IS_MIME_PART (part));
3516 tny_list_prepend (priv->attachments, (GObject *) part);
3517 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3518 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3519 gtk_widget_show_all (priv->attachments_caption);
3520 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3524 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3526 ModestMsgEditWindowPrivate *priv;
3528 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3529 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3531 return priv->msg_uid;
3535 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3536 ModestMsgEditWindowWidgetType widget_type)
3538 ModestMsgEditWindowPrivate *priv;
3540 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3541 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3543 switch (widget_type) {
3544 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3545 return priv->msg_body;
3547 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3548 return priv->to_field;
3550 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3551 return priv->cc_field;
3553 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3554 return priv->bcc_field;
3556 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3557 return priv->subject_field;
3559 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3560 return priv->attachments_view;
3568 remove_tags (WPTextBuffer *buffer)
3570 GtkTextIter start, end;
3572 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3573 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3575 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3579 on_account_removed (TnyAccountStore *account_store,
3580 TnyAccount *account,
3583 /* Do nothing if it's a store account, because we use the
3584 transport to send the messages */
3585 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3586 const gchar *parent_acc = NULL;
3587 const gchar *our_acc = NULL;
3589 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3590 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3591 /* Close this window if I'm showing a message of the removed account */
3592 if (strcmp (parent_acc, our_acc) == 0)
3593 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3597 typedef struct _MessageSettingsHelper {
3598 ModestMsgEditWindow *window;
3599 GSList *priority_group;
3600 GtkWidget *align_picker;
3601 } MessageSettingsHelper;
3604 on_priority_toggle (GtkToggleButton *button,
3605 MessageSettingsHelper *helper)
3608 ModestMsgEditWindowPrivate *priv;
3610 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3611 if (gtk_toggle_button_get_active (button)) {
3613 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3614 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3615 if ((node_button != button) &&
3616 gtk_toggle_button_get_active (node_button)) {
3617 gtk_toggle_button_set_active (node_button, FALSE);
3619 if (priv->priority_flags != (TnyHeaderFlags) g_object_get_data (G_OBJECT (button), "priority"))
3620 modest_msg_edit_window_set_priority_flags (helper->window,
3622 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_picker_value_changed (HildonPickerButton *button,
3645 MessageSettingsHelper *helper)
3647 ModestMsgEditFormat new_format, old_format;
3650 switch (hildon_picker_button_get_active (button)) {
3652 new_format = MODEST_MSG_EDIT_FORMAT_HTML;
3653 file_format = MODEST_FILE_FORMAT_FORMATTED_TEXT;
3657 new_format = MODEST_MSG_EDIT_FORMAT_TEXT;
3658 file_format = MODEST_FILE_FORMAT_PLAIN_TEXT;
3662 old_format = modest_msg_edit_window_get_format (helper->window);
3663 if (new_format != old_format) {
3664 modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (helper->window), file_format);
3666 switch (modest_msg_edit_window_get_format (helper->window)) {
3667 case MODEST_MSG_EDIT_FORMAT_TEXT:
3668 hildon_picker_button_set_active (button, 0);
3669 gtk_widget_set_sensitive (helper->align_picker, FALSE);
3671 case MODEST_MSG_EDIT_FORMAT_HTML:
3673 hildon_picker_button_set_active (button, 1);
3674 gtk_widget_set_sensitive (helper->align_picker, TRUE);
3681 on_align_picker_value_changed (HildonPickerButton *button,
3682 MessageSettingsHelper *helper)
3684 GtkJustification new_justify;
3685 ModestMsgEditFormatState *format_state = NULL;
3687 switch (hildon_picker_button_get_active (button)) {
3689 new_justify = GTK_JUSTIFY_CENTER;
3692 new_justify = GTK_JUSTIFY_RIGHT;
3696 new_justify = GTK_JUSTIFY_LEFT;
3700 format_state = modest_msg_edit_window_get_format_state (helper->window);
3701 if (format_state->justification != new_justify)
3702 format_state->justification = new_justify;
3703 modest_msg_edit_window_set_format_state (helper->window, format_state);
3704 g_free (format_state);
3708 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
3712 GtkWidget *priority_hbox;
3713 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
3714 GtkWidget *captioned;
3715 GtkSizeGroup *title_sizegroup, *value_sizegroup;
3716 GtkWidget *format_picker;
3717 GtkWidget *format_selector;
3718 ModestMsgEditWindowPrivate *priv;
3719 MessageSettingsHelper helper = {0,};
3720 ModestMsgEditFormatState *format_state = NULL;
3722 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3723 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3724 helper.window = window;
3725 helper.priority_group = NULL;
3727 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3728 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3730 dialog = gtk_dialog_new ();
3731 vbox = gtk_vbox_new (FALSE, 0);
3732 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), vbox);
3733 gtk_widget_show (vbox);
3735 /* Priority toggles */
3736 priority_hbox = gtk_hbox_new (TRUE, 0);
3737 high_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3738 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
3739 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
3740 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
3741 medium_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3742 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
3743 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
3744 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
3745 low_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3746 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
3747 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
3748 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
3749 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, TRUE, TRUE, 0);
3750 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, TRUE, TRUE, 0);
3751 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, TRUE, TRUE, 0);
3752 gtk_widget_show_all (priority_hbox);
3753 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
3754 _("mcen_me_editor_message_priority"), priority_hbox);
3755 gtk_widget_show (captioned);
3756 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
3758 /* format selector */
3759 format_selector = hildon_touch_selector_new_text ();
3760 hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (format_selector), _("mcen_me_editor_plain_text"));
3761 hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (format_selector), _("mcen_me_editor_formatted_text"));
3762 format_picker = hildon_picker_button_new (MODEST_EDITABLE_SIZE,
3763 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL);
3764 hildon_picker_button_set_selector (HILDON_PICKER_BUTTON (format_picker), HILDON_TOUCH_SELECTOR (format_selector));
3765 modest_maemo_utils_set_hbutton_layout (title_sizegroup, value_sizegroup,
3766 _("mcen_me_editor_format"), format_picker);
3767 gtk_widget_show_all (format_picker);
3768 gtk_box_pack_start (GTK_BOX (vbox), format_picker, FALSE, FALSE, 0);
3771 g_object_unref (title_sizegroup);
3772 g_object_unref (value_sizegroup);
3773 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_me_message_settings"));
3775 /* Set current values */
3776 switch (priv->priority_flags) {
3777 case TNY_HEADER_FLAG_HIGH_PRIORITY:
3778 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (high_toggle), TRUE);
3780 case TNY_HEADER_FLAG_LOW_PRIORITY:
3781 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (low_toggle), TRUE);
3784 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (medium_toggle), TRUE);
3788 switch (modest_msg_edit_window_get_format (window)) {
3789 case MODEST_MSG_EDIT_FORMAT_TEXT:
3790 hildon_picker_button_set_active (HILDON_PICKER_BUTTON (format_picker), 0);
3791 gtk_widget_set_sensitive (helper.align_picker, FALSE);
3793 case MODEST_MSG_EDIT_FORMAT_HTML:
3795 hildon_picker_button_set_active (HILDON_PICKER_BUTTON (format_picker), 1);
3796 gtk_widget_set_sensitive (helper.align_picker, TRUE);
3800 format_state = modest_msg_edit_window_get_format_state (window);
3801 switch (format_state->justification) {
3802 case GTK_JUSTIFY_RIGHT:
3803 hildon_picker_button_set_active (HILDON_PICKER_BUTTON (helper.align_picker), 2);
3805 case GTK_JUSTIFY_CENTER:
3806 hildon_picker_button_set_active (HILDON_PICKER_BUTTON (helper.align_picker), 1);
3809 hildon_picker_button_set_active (HILDON_PICKER_BUTTON (helper.align_picker), 0);
3813 g_free (format_state);
3815 /* Signal connects */
3816 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3817 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3818 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3819 g_signal_connect (G_OBJECT (format_picker), "value-changed", G_CALLBACK (on_format_picker_value_changed), &helper);
3820 g_signal_connect (G_OBJECT (helper.align_picker), "value-changed",
3821 G_CALLBACK (on_align_picker_value_changed), &helper);
3823 gtk_dialog_run (GTK_DIALOG (dialog));
3825 /* Read new values */
3827 gtk_widget_destroy (dialog);
3828 g_slist_free (helper.priority_group);
3832 static void on_message_settings (GtkAction *action,
3833 ModestMsgEditWindow *window)
3835 modest_msg_edit_window_show_msg_settings_dialog (window);
3839 on_cc_button_toggled (HildonCheckButton *button,
3840 ModestMsgEditWindow *window)
3842 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
3844 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
3845 hildon_check_button_get_active (button));
3849 on_bcc_button_toggled (HildonCheckButton *button,
3850 ModestMsgEditWindow *window)
3852 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
3854 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
3855 hildon_check_button_get_active (button));
3859 setup_menu (ModestMsgEditWindow *self)
3861 ModestMsgEditWindowPrivate *priv = NULL;
3863 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
3865 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3867 /* Settings menu buttons */
3868 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_checknames"), NULL,
3869 APP_MENU_CALLBACK (modest_ui_actions_on_check_names),
3871 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_undo"), "<Ctrl>z",
3872 APP_MENU_CALLBACK (modest_ui_actions_on_undo),
3873 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_undo));
3875 priv->cc_button = hildon_check_button_new (0);
3876 gtk_button_set_label (GTK_BUTTON (priv->cc_button), _("mcen_me_editor_showcc"));
3877 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button),
3879 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->cc_button),
3881 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
3882 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
3883 priv->bcc_button = hildon_check_button_new (0);
3884 gtk_button_set_label (GTK_BUTTON (priv->bcc_button), _("mcen_me_editor_showbcc"));
3885 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button),
3887 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->bcc_button),
3889 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
3890 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
3892 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_attach_inlineimage"), NULL,
3893 APP_MENU_CALLBACK (modest_ui_actions_on_insert_image),
3894 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_set_style));
3895 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_remove_attachments"), NULL,
3896 APP_MENU_CALLBACK (modest_ui_actions_on_remove_attachments),
3897 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
3898 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_message_settings"), NULL,
3899 APP_MENU_CALLBACK (on_message_settings),
3901 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_viewer_find"), "<Ctrl>f",
3902 APP_MENU_CALLBACK (modest_ui_actions_on_toggle_find_in_page),