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 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2225 GtkWidget *dialog = NULL;
2227 GSList *uris = NULL;
2229 GnomeVFSFileSize total_size, allowed_size;
2230 ModestMsgEditWindowPrivate *priv;
2234 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2236 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2238 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2241 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2242 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2243 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2244 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), GTK_WINDOW (dialog), GTK_WINDOW (window));
2246 response = gtk_dialog_run (GTK_DIALOG (dialog));
2248 case GTK_RESPONSE_OK:
2249 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2254 gtk_widget_destroy (dialog);
2256 /* allowed size is the maximum size - what's already there */
2257 modest_attachments_view_get_sizes (
2258 MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2259 &att_num, &att_size);
2260 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2263 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2265 const gchar *uri = (const gchar *) uri_node->data;
2267 total_size += modest_msg_edit_window_attach_file_one
2268 (window, uri, allowed_size);
2270 if (total_size > allowed_size) {
2271 g_warning ("%s: total size: %u",
2272 __FUNCTION__, (unsigned int)total_size);
2276 allowed_size -= total_size;
2280 g_slist_foreach (uris, (GFunc) g_free, NULL);
2281 g_slist_free (uris);
2286 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2288 GnomeVFSFileSize allowed_size)
2291 GnomeVFSHandle *handle = NULL;
2292 ModestMsgEditWindowPrivate *priv;
2293 GnomeVFSResult result;
2294 GnomeVFSFileSize size = 0;
2295 g_return_val_if_fail (window, 0);
2296 g_return_val_if_fail (uri, 0);
2298 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2300 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2301 if (result == GNOME_VFS_OK) {
2302 TnyMimePart *mime_part;
2304 const gchar *mime_type = NULL;
2306 gchar *escaped_filename;
2309 GnomeVFSFileInfo *info;
2310 GnomeVFSURI *vfs_uri;
2312 gnome_vfs_close (handle);
2313 vfs_uri = gnome_vfs_uri_new (uri);
2316 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2317 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2318 g_free (escaped_filename);
2319 gnome_vfs_uri_unref (vfs_uri);
2321 info = gnome_vfs_file_info_new ();
2323 if (gnome_vfs_get_file_info (uri,
2325 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2327 mime_type = gnome_vfs_file_info_get_mime_type (info);
2328 mime_part = tny_platform_factory_new_mime_part
2329 (modest_runtime_get_platform_factory ());
2331 /* try to get the attachment's size; this may fail for weird
2332 * file systems, like obex, upnp... */
2333 if (allowed_size != 0 &&
2334 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2336 if (size > allowed_size) {
2337 modest_platform_information_banner (NULL, NULL,
2338 dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2342 g_warning ("%s: could not get attachment size", __FUNCTION__);
2344 stream = create_stream_for_uri (uri);
2346 if (stream == NULL) {
2348 modest_platform_information_banner (NULL, NULL, dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2350 g_object_unref (mime_part);
2351 gnome_vfs_file_info_unref (info);
2355 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2356 g_object_unref (stream);
2358 content_id = g_strdup_printf ("%d", priv->next_cid);
2359 tny_mime_part_set_content_id (mime_part, content_id);
2360 g_free (content_id);
2363 basename = g_path_get_basename (filename);
2364 tny_mime_part_set_filename (mime_part, basename);
2367 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2368 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2370 info->size == 0, info->size);
2371 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2372 gtk_widget_show_all (priv->attachments_caption);
2373 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2375 g_object_unref (mime_part);
2376 gnome_vfs_file_info_unref (info);
2383 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2386 ModestMsgEditWindowPrivate *priv;
2389 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2390 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2392 if (att_list == NULL) {
2393 att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2395 g_object_ref (att_list);
2398 if (tny_list_get_length (att_list) == 0) {
2399 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2401 gboolean dialog_response;
2402 gchar *message = NULL;
2403 gchar *filename = NULL;
2405 if (tny_list_get_length (att_list) == 1) {
2407 iter = tny_list_create_iterator (att_list);
2408 part = (TnyMimePart *) tny_iterator_get_current (iter);
2409 g_object_unref (iter);
2410 if (TNY_IS_MSG (part)) {
2411 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2413 filename = tny_header_dup_subject (header);
2414 g_object_unref (header);
2416 if (filename == NULL) {
2417 filename = g_strdup (_("mail_va_no_subject"));
2420 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2422 g_object_unref (part);
2424 filename = g_strdup ("");
2426 message = g_strdup_printf (ngettext("emev_nc_delete_attachment", "emev_nc_delete_attachments",
2427 tny_list_get_length (att_list)), filename);
2430 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window), message);
2433 if (dialog_response != GTK_RESPONSE_OK) {
2434 g_object_unref (att_list);
2437 hildon_banner_show_information (NULL, NULL, _("mcen_me_inbox_remove_attachments"));
2439 for (iter = tny_list_create_iterator (att_list);
2440 !tny_iterator_is_done (iter);
2441 tny_iterator_next (iter)) {
2442 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2443 const gchar *att_id;
2444 tny_list_remove (priv->attachments, (GObject *) mime_part);
2446 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2448 if (tny_list_get_length (priv->attachments) == 0)
2449 gtk_widget_hide (priv->attachments_caption);
2450 att_id = tny_mime_part_get_content_id (mime_part);
2452 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2454 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2455 g_object_unref (mime_part);
2457 g_object_unref (iter);
2460 g_object_unref (att_list);
2462 /* if the last attachment has been removed, focus the Subject: field */
2463 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2464 gtk_widget_grab_focus (priv->subject_field);
2468 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2471 ModestMsgEditWindowPrivate *priv;
2472 GdkColor *new_color;
2473 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2475 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2476 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2479 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2481 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2483 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2485 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2490 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
2493 ModestMsgEditWindowPrivate *priv;
2494 gint new_size_index;
2495 ModestMsgEditWindow *window;
2498 window = MODEST_MSG_EDIT_WINDOW (userdata);
2499 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2500 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2502 if (gtk_check_menu_item_get_active (menu_item)) {
2504 WPTextBufferFormat format;
2506 memset (&format, 0, sizeof (format));
2507 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2509 label = gtk_bin_get_child (GTK_BIN (menu_item));
2511 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
2512 format.cs.font_size = TRUE;
2513 format.cs.text_position = TRUE;
2514 format.cs.font = TRUE;
2515 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
2516 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2518 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2519 GINT_TO_POINTER (wp_get_font_size_index (new_size_index, 12))))
2520 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2522 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2523 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
2524 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2530 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
2533 ModestMsgEditWindowPrivate *priv;
2534 gint new_font_index;
2535 ModestMsgEditWindow *window;
2538 window = MODEST_MSG_EDIT_WINDOW (userdata);
2539 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2540 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2542 if (gtk_check_menu_item_get_active (menu_item)) {
2545 label = gtk_bin_get_child (GTK_BIN (menu_item));
2547 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
2549 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2550 GINT_TO_POINTER(new_font_index)))
2551 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2553 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2554 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2555 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2561 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2564 ModestMsgEditWindowPrivate *priv = NULL;
2565 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2567 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2568 if (!priv->update_caption_visibility)
2571 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2573 gtk_widget_show (priv->cc_caption);
2575 gtk_widget_hide (priv->cc_caption);
2577 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2581 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2584 ModestMsgEditWindowPrivate *priv = NULL;
2585 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2587 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2588 if (!priv->update_caption_visibility)
2591 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2593 gtk_widget_show (priv->bcc_caption);
2595 gtk_widget_hide (priv->bcc_caption);
2597 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2601 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2602 ModestRecptEditor *editor)
2604 ModestMsgEditWindowPrivate *priv;
2606 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2607 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2609 /* we check for low-mem; in that case, show a warning, and don't allow
2610 * for the addressbook
2612 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2615 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2617 if (editor == NULL) {
2618 GtkWidget *view_focus;
2619 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2621 /* This code should be kept in sync with ModestRecptEditor. The
2622 textview inside the recpt editor is the one that really gets the
2623 focus. As it's inside a scrolled window, and this one inside the
2624 hbox recpt editor inherits from, we'll need to go up in the
2625 hierarchy to know if the text view is part of the recpt editor
2626 or if it's a different text entry */
2628 if (gtk_widget_get_parent (view_focus)) {
2629 GtkWidget *first_parent;
2631 first_parent = gtk_widget_get_parent (view_focus);
2632 if (gtk_widget_get_parent (first_parent) &&
2633 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2634 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2639 editor = MODEST_RECPT_EDITOR (priv->to_field);
2643 modest_address_book_select_addresses (editor);
2648 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2650 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2652 modest_msg_edit_window_open_addressbook (window, NULL);
2656 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2657 gboolean show_toolbar)
2659 ModestWindowPrivate *parent_priv;
2661 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2662 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2664 /* We can not just use the code of
2665 modest_msg_edit_window_setup_toolbar because it has a
2666 mixture of both initialization and creation code. */
2668 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2670 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2674 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2675 TnyHeaderFlags priority_flags)
2677 ModestMsgEditWindowPrivate *priv;
2678 ModestWindowPrivate *parent_priv;
2680 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2682 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2683 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2685 if (priv->priority_flags != priority_flags) {
2686 GtkAction *priority_action = NULL;
2688 priv->priority_flags = priority_flags;
2690 switch (priority_flags) {
2691 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2692 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2693 MODEST_HEADER_ICON_HIGH,
2694 HILDON_ICON_SIZE_XSMALL);
2695 gtk_widget_show (priv->priority_icon);
2696 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2697 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2699 case TNY_HEADER_FLAG_LOW_PRIORITY:
2700 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2701 MODEST_HEADER_ICON_LOW,
2702 HILDON_ICON_SIZE_XSMALL);
2703 gtk_widget_show (priv->priority_icon);
2704 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2705 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2708 gtk_widget_hide (priv->priority_icon);
2709 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2710 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2713 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2714 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2719 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2722 ModestMsgEditWindowPrivate *priv;
2723 ModestWindowPrivate *parent_priv;
2724 gint current_format;
2726 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2728 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2729 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2731 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2732 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2734 if (current_format != file_format) {
2735 switch (file_format) {
2736 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2737 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2738 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
2740 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2744 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2745 response = gtk_dialog_run (GTK_DIALOG (dialog));
2746 gtk_widget_destroy (dialog);
2747 if (response == GTK_RESPONSE_OK) {
2748 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2750 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
2751 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
2756 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2757 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2758 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2763 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2766 ModestMsgEditWindowPrivate *priv;
2767 WPTextBufferFormat oldfmt, fmt;
2768 gint old_position = 0;
2772 GdkColor *color = NULL;
2773 gboolean bold, bold_set, italic, italic_set;
2774 gboolean underline, underline_set;
2775 gboolean strikethrough, strikethrough_set;
2776 gboolean position_set;
2777 gboolean font_size_set, font_set, color_set;
2780 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2781 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2783 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2784 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
2785 GTK_WINDOW(dialog), GTK_WINDOW (window));
2787 /* First we get the currently selected font information */
2788 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2790 switch (oldfmt.text_position) {
2791 case TEXT_POSITION_NORMAL:
2794 case TEXT_POSITION_SUPERSCRIPT:
2802 g_object_set (G_OBJECT (dialog),
2803 "bold", oldfmt.bold != FALSE,
2804 "bold-set", !oldfmt.cs.bold,
2805 "underline", oldfmt.underline != FALSE,
2806 "underline-set", !oldfmt.cs.underline,
2807 "italic", oldfmt.italic != FALSE,
2808 "italic-set", !oldfmt.cs.italic,
2809 "strikethrough", oldfmt.strikethrough != FALSE,
2810 "strikethrough-set", !oldfmt.cs.strikethrough,
2811 "color", &oldfmt.color,
2812 "color-set", !oldfmt.cs.color,
2813 "size", wp_font_size[oldfmt.font_size],
2814 "size-set", !oldfmt.cs.font_size,
2815 "position", old_position,
2816 "position-set", !oldfmt.cs.text_position,
2817 "family", wp_get_font_name (oldfmt.font),
2818 "family-set", !oldfmt.cs.font,
2821 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2822 GTK_WINDOW (dialog), GTK_WINDOW (window));
2823 gtk_widget_show_all (dialog);
2824 priv->font_dialog = dialog;
2825 response = gtk_dialog_run (GTK_DIALOG (dialog));
2826 priv->font_dialog = NULL;
2827 if (response == GTK_RESPONSE_OK) {
2829 g_object_get( dialog,
2831 "bold-set", &bold_set,
2832 "underline", &underline,
2833 "underline-set", &underline_set,
2835 "italic-set", &italic_set,
2836 "strikethrough", &strikethrough,
2837 "strikethrough-set", &strikethrough_set,
2839 "color-set", &color_set,
2841 "size-set", &font_size_set,
2842 "family", &font_name,
2843 "family-set", &font_set,
2844 "position", &position,
2845 "position-set", &position_set,
2850 if (response == GTK_RESPONSE_OK) {
2851 memset(&fmt, 0, sizeof(fmt));
2857 fmt.italic = italic;
2858 fmt.cs.italic = TRUE;
2860 if (underline_set) {
2861 fmt.underline = underline;
2862 fmt.cs.underline = TRUE;
2864 if (strikethrough_set) {
2865 fmt.strikethrough = strikethrough;
2866 fmt.cs.strikethrough = TRUE;
2871 ? TEXT_POSITION_NORMAL
2872 : ( ( position == 1 )
2873 ? TEXT_POSITION_SUPERSCRIPT
2874 : TEXT_POSITION_SUBSCRIPT );
2875 fmt.cs.text_position = TRUE;
2876 fmt.font_size = oldfmt.font_size;
2880 fmt.cs.color = TRUE;
2883 fmt.font = wp_get_font_index(font_name,
2888 if (font_size_set) {
2889 fmt.cs.font_size = TRUE;
2890 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
2892 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2893 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2895 gtk_widget_destroy (dialog);
2897 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2901 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2903 ModestMsgEditWindowPrivate *priv;
2905 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2906 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2908 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2910 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2911 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2915 modest_msg_edit_window_redo (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_redo (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));
2930 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
2932 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2934 priv->can_undo = can_undo;
2938 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
2940 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2942 priv->can_redo = can_redo;
2946 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
2948 ModestMsgEditWindowPrivate *priv;
2949 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2950 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2952 return priv->can_undo;
2956 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
2958 ModestMsgEditWindowPrivate *priv;
2959 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2960 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2962 return priv->can_redo;
2967 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
2970 GtkTextIter match_start, match_end;
2972 if (image_id == NULL)
2975 gtk_text_buffer_get_start_iter (buffer, &iter);
2977 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
2978 GSList *tags = gtk_text_iter_get_tags (&match_start);
2980 for (node = tags; node != NULL; node = g_slist_next (node)) {
2981 GtkTextTag *tag = (GtkTextTag *) node->data;
2982 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
2983 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
2984 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
2986 offset = gtk_text_iter_get_offset (&match_start);
2987 gtk_text_buffer_delete (buffer, &match_start, &match_end);
2988 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
2992 gtk_text_iter_forward_char (&iter);
2997 message_is_empty (ModestMsgEditWindow *window)
2999 ModestMsgEditWindowPrivate *priv = NULL;
3001 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3002 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3004 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3005 * so we can ignore markup.
3007 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3010 count = gtk_text_buffer_get_char_count (buf);
3016 msg_body_focus (GtkWidget *focus,
3017 GdkEventFocus *event,
3021 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3022 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3023 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3028 recpt_field_changed (GtkTextBuffer *buffer,
3029 ModestMsgEditWindow *editor)
3031 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3032 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3036 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3038 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3039 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3043 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3046 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3047 GtkTextBuffer *buffer;
3049 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3050 gtk_text_buffer_set_modified (buffer, modified);
3051 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3052 gtk_text_buffer_set_modified (buffer, modified);
3053 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3054 gtk_text_buffer_set_modified (buffer, modified);
3055 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3059 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3061 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3062 const char *account_name;
3063 GtkTextBuffer *buffer;
3065 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3066 if (gtk_text_buffer_get_modified (buffer))
3068 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3069 if (gtk_text_buffer_get_modified (buffer))
3071 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3072 if (gtk_text_buffer_get_modified (buffer))
3074 if (gtk_text_buffer_get_modified (priv->text_buffer))
3076 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3077 if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3088 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3090 ModestMsgEditWindowPrivate *priv = NULL;
3092 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3093 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3095 /* check if there's no recipient added */
3096 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3097 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3098 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3099 /* no recipient contents, then select contacts */
3100 modest_msg_edit_window_open_addressbook (window, NULL);
3104 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3105 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3108 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3109 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3112 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3113 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3117 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3118 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3119 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3126 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3127 ModestMsgEditWindow *window)
3129 modest_msg_edit_window_offer_attach_file (window);
3133 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3135 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3137 return priv->clipboard_text;
3141 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3143 ModestMsgEditWindow *window)
3145 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3146 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3148 if (!GTK_WIDGET_VISIBLE (window))
3151 g_object_ref (window);
3152 text = gtk_clipboard_wait_for_text (selection_clipboard);
3154 if (priv->clipboard_text != NULL) {
3155 g_free (priv->clipboard_text);
3157 priv->clipboard_text = text;
3159 if (GTK_WIDGET_VISIBLE (window)) {
3160 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3162 g_object_unref (window);
3165 static gboolean clipboard_owner_change_idle (gpointer userdata)
3167 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3168 ModestMsgEditWindowPrivate *priv;
3170 gdk_threads_enter ();
3171 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3172 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3174 priv->clipboard_owner_idle = 0;
3175 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3176 gdk_threads_leave ();
3182 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3184 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3185 if (priv->clipboard_owner_idle == 0) {
3186 priv->clipboard_owner_idle = g_idle_add (clipboard_owner_change_idle, window);
3191 subject_field_move_cursor (GtkEntry *entry,
3192 GtkMovementStep step,
3197 if (!GTK_WIDGET_VISIBLE (window))
3200 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3204 update_window_title (ModestMsgEditWindow *window)
3206 ModestMsgEditWindowPrivate *priv = NULL;
3207 const gchar *subject;
3209 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3210 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3211 if (subject == NULL || subject[0] == '\0')
3212 subject = _("mail_va_new_email");
3214 gtk_window_set_title (GTK_WINDOW (window), subject);
3219 subject_field_changed (GtkEditable *editable,
3220 ModestMsgEditWindow *window)
3222 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3223 update_window_title (window);
3224 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3225 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3226 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3230 subject_field_insert_text (GtkEditable *editable,
3232 gint new_text_length,
3234 ModestMsgEditWindow *window)
3236 GString *result = g_string_new ("");
3238 gint result_len = 0;
3239 const gchar *entry_text = NULL;
3242 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3243 old_length = g_utf8_strlen (entry_text, -1);
3245 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3246 gunichar c = g_utf8_get_char_validated (current, 8);
3247 /* Invalid unichar, stop */
3253 result = g_string_append_unichar (result, c);
3257 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3258 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3261 /* Prevent endless recursion */
3262 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3263 g_signal_emit_by_name (editable, "insert-text",
3264 (gpointer) result->str, (gpointer) result->len,
3265 (gpointer) position, (gpointer) window);
3266 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3270 if (result_len + old_length > 1000) {
3271 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3272 dgettext("hildon-common-strings",
3273 "ckdg_ib_maximum_characters_reached"));
3275 g_string_free (result, TRUE);
3279 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3282 ModestMsgEditWindowPrivate *priv = NULL;
3284 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3285 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3287 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3290 gtk_widget_show_all (priv->find_toolbar);
3291 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3293 gtk_widget_hide_all (priv->find_toolbar);
3294 gtk_widget_grab_focus (priv->msg_body);
3299 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3301 GtkTextIter *match_start,
3302 GtkTextIter *match_end)
3304 GtkTextIter end_iter;
3305 gchar *str_casefold;
3308 gchar *range_casefold;
3311 gboolean result = FALSE;
3318 gtk_text_iter_forward_to_end (&end_iter);
3320 str_casefold = g_utf8_casefold (str, -1);
3321 str_chars_n = strlen (str);
3323 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3324 range_casefold = g_utf8_casefold (range_text, -1);
3325 range_chars_n = strlen (range_casefold);
3327 if (range_chars_n < str_chars_n) {
3328 g_free (str_casefold);
3329 g_free (range_text);
3330 g_free (range_casefold);
3334 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3335 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3336 if (!g_utf8_collate (range_subtext, str_casefold)) {
3337 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3339 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3340 match_start, match_end, NULL);
3341 g_free (found_text);
3343 g_free (range_subtext);
3347 g_free (str_casefold);
3348 g_free (range_text);
3349 g_free (range_casefold);
3356 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3357 ModestMsgEditWindow *window)
3359 gchar *current_search = NULL;
3360 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3362 GtkTextIter selection_start, selection_end;
3363 GtkTextIter match_start, match_end;
3364 gboolean continue_search = FALSE;
3366 if (message_is_empty (window)) {
3367 g_free (priv->last_search);
3368 priv->last_search = NULL;
3369 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3373 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3374 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3375 g_free (current_search);
3376 g_free (priv->last_search);
3377 priv->last_search = NULL;
3378 /* Information banner about empty search */
3379 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-common-strings", "ecdg_ib_find_rep_enter_text"));
3383 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3384 continue_search = TRUE;
3386 g_free (priv->last_search);
3387 priv->last_search = g_strdup (current_search);
3390 if (continue_search) {
3391 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3392 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3393 &match_start, &match_end);
3395 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_search_complete"));
3397 GtkTextIter buffer_start;
3398 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3399 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3400 &match_start, &match_end);
3402 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_no_matches"));
3405 /* Mark as selected the string found in search */
3407 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3408 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3409 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3411 g_free (priv->last_search);
3412 priv->last_search = NULL;
3414 g_free (current_search);
3418 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3420 ModestMsgEditWindowPrivate *priv;
3422 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3427 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3430 ModestMsgEditWindowPrivate *priv;
3432 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3437 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3438 ModestMsgEditWindow *window)
3440 modest_msg_edit_window_toggle_find_toolbar (window, FALSE);
3444 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3447 ModestMsgEditWindowPrivate *priv;
3448 TnyHeader *header = NULL;
3450 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3451 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3453 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3454 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3456 if (priv->draft_msg != NULL) {
3457 g_object_unref (priv->draft_msg);
3460 if (draft != NULL) {
3461 g_object_ref (draft);
3462 header = tny_msg_get_header (draft);
3463 if (priv->msg_uid) {
3464 g_free (priv->msg_uid);
3465 priv->msg_uid = NULL;
3467 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3468 if (GTK_WIDGET_REALIZED (window)) {
3469 if (!modest_window_mgr_register_window (mgr, MODEST_WINDOW (window), NULL)) {
3470 gtk_widget_destroy (GTK_WIDGET (window));
3476 priv->draft_msg = draft;
3480 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3481 GtkTextIter *start, GtkTextIter *end,
3484 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3485 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3488 if (tag == NULL) return;
3489 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3490 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3491 replace_with_images (window, priv->images);
3496 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3499 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3501 g_return_if_fail (TNY_IS_MIME_PART (part));
3502 tny_list_prepend (priv->attachments, (GObject *) part);
3503 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3504 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3505 gtk_widget_show_all (priv->attachments_caption);
3506 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3510 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3512 ModestMsgEditWindowPrivate *priv;
3514 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3515 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3517 return priv->msg_uid;
3521 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3522 ModestMsgEditWindowWidgetType widget_type)
3524 ModestMsgEditWindowPrivate *priv;
3526 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3527 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3529 switch (widget_type) {
3530 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3531 return priv->msg_body;
3533 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3534 return priv->to_field;
3536 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3537 return priv->cc_field;
3539 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3540 return priv->bcc_field;
3542 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3543 return priv->subject_field;
3545 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3546 return priv->attachments_view;
3554 remove_tags (WPTextBuffer *buffer)
3556 GtkTextIter start, end;
3558 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3559 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3561 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3565 on_account_removed (TnyAccountStore *account_store,
3566 TnyAccount *account,
3569 /* Do nothing if it's a store account, because we use the
3570 transport to send the messages */
3571 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3572 const gchar *parent_acc = NULL;
3573 const gchar *our_acc = NULL;
3575 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3576 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3577 /* Close this window if I'm showing a message of the removed account */
3578 if (strcmp (parent_acc, our_acc) == 0)
3579 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3583 typedef struct _MessageSettingsHelper {
3584 ModestMsgEditWindow *window;
3585 GSList *priority_group;
3586 GtkWidget *align_picker;
3587 } MessageSettingsHelper;
3590 on_priority_toggle (GtkToggleButton *button,
3591 MessageSettingsHelper *helper)
3594 ModestMsgEditWindowPrivate *priv;
3596 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3597 if (gtk_toggle_button_get_active (button)) {
3599 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3600 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3601 if ((node_button != button) &&
3602 gtk_toggle_button_get_active (node_button)) {
3603 gtk_toggle_button_set_active (node_button, FALSE);
3605 if (priv->priority_flags != (TnyHeaderFlags) g_object_get_data (G_OBJECT (button), "priority"))
3606 modest_msg_edit_window_set_priority_flags (helper->window,
3608 g_object_get_data (G_OBJECT (button),
3614 gboolean found = FALSE;
3615 /* If no one is active, activate it again */
3616 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3617 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3618 if (gtk_toggle_button_get_active (node_button)) {
3624 gtk_toggle_button_set_active (button, TRUE);
3630 on_format_picker_value_changed (HildonPickerButton *button,
3631 MessageSettingsHelper *helper)
3633 ModestMsgEditFormat new_format, old_format;
3636 switch (hildon_picker_button_get_active (button)) {
3638 new_format = MODEST_MSG_EDIT_FORMAT_HTML;
3639 file_format = MODEST_FILE_FORMAT_FORMATTED_TEXT;
3643 new_format = MODEST_MSG_EDIT_FORMAT_TEXT;
3644 file_format = MODEST_FILE_FORMAT_PLAIN_TEXT;
3648 old_format = modest_msg_edit_window_get_format (helper->window);
3649 if (new_format != old_format) {
3650 modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (helper->window), file_format);
3652 switch (modest_msg_edit_window_get_format (helper->window)) {
3653 case MODEST_MSG_EDIT_FORMAT_TEXT:
3654 hildon_picker_button_set_active (button, 0);
3655 gtk_widget_set_sensitive (helper->align_picker, FALSE);
3657 case MODEST_MSG_EDIT_FORMAT_HTML:
3659 hildon_picker_button_set_active (button, 1);
3660 gtk_widget_set_sensitive (helper->align_picker, TRUE);
3667 on_align_picker_value_changed (HildonPickerButton *button,
3668 MessageSettingsHelper *helper)
3670 GtkJustification new_justify;
3671 ModestMsgEditFormatState *format_state = NULL;
3673 switch (hildon_picker_button_get_active (button)) {
3675 new_justify = GTK_JUSTIFY_CENTER;
3678 new_justify = GTK_JUSTIFY_RIGHT;
3682 new_justify = GTK_JUSTIFY_LEFT;
3686 format_state = modest_msg_edit_window_get_format_state (helper->window);
3687 if (format_state->justification != new_justify)
3688 format_state->justification = new_justify;
3689 modest_msg_edit_window_set_format_state (helper->window, format_state);
3690 g_free (format_state);
3694 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
3698 GtkWidget *priority_hbox;
3699 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
3700 GtkWidget *captioned;
3701 GtkSizeGroup *title_sizegroup, *value_sizegroup;
3702 GtkWidget *format_picker;
3703 GtkWidget *format_selector;
3704 ModestMsgEditWindowPrivate *priv;
3705 MessageSettingsHelper helper = {0,};
3706 ModestMsgEditFormatState *format_state = NULL;
3708 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3709 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3710 helper.window = window;
3711 helper.priority_group = NULL;
3713 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3714 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3716 dialog = gtk_dialog_new ();
3717 vbox = gtk_vbox_new (FALSE, 0);
3718 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), vbox);
3719 gtk_widget_show (vbox);
3721 /* Priority toggles */
3722 priority_hbox = gtk_hbox_new (TRUE, 0);
3723 high_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3724 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
3725 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
3726 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
3727 medium_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3728 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
3729 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
3730 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
3731 low_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3732 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
3733 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
3734 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
3735 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, TRUE, TRUE, 0);
3736 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, TRUE, TRUE, 0);
3737 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, TRUE, TRUE, 0);
3738 gtk_widget_show_all (priority_hbox);
3739 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
3740 _("mcen_me_editor_message_priority"), priority_hbox);
3741 gtk_widget_show (captioned);
3742 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
3744 /* format selector */
3745 format_selector = hildon_touch_selector_new_text ();
3746 hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (format_selector), _("mcen_me_editor_plain_text"));
3747 hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (format_selector), _("mcen_me_editor_formatted_text"));
3748 format_picker = hildon_picker_button_new (MODEST_EDITABLE_SIZE,
3749 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL);
3750 hildon_picker_button_set_selector (HILDON_PICKER_BUTTON (format_picker), HILDON_TOUCH_SELECTOR (format_selector));
3751 modest_maemo_utils_set_hbutton_layout (title_sizegroup, value_sizegroup,
3752 _("mcen_me_editor_format"), format_picker);
3753 gtk_widget_show_all (format_picker);
3754 gtk_box_pack_start (GTK_BOX (vbox), format_picker, FALSE, FALSE, 0);
3757 g_object_unref (title_sizegroup);
3758 g_object_unref (value_sizegroup);
3759 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_me_message_settings"));
3761 /* Set current values */
3762 switch (priv->priority_flags) {
3763 case TNY_HEADER_FLAG_HIGH_PRIORITY:
3764 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (high_toggle), TRUE);
3766 case TNY_HEADER_FLAG_LOW_PRIORITY:
3767 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (low_toggle), TRUE);
3770 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (medium_toggle), TRUE);
3774 switch (modest_msg_edit_window_get_format (window)) {
3775 case MODEST_MSG_EDIT_FORMAT_TEXT:
3776 hildon_picker_button_set_active (HILDON_PICKER_BUTTON (format_picker), 0);
3777 gtk_widget_set_sensitive (helper.align_picker, FALSE);
3779 case MODEST_MSG_EDIT_FORMAT_HTML:
3781 hildon_picker_button_set_active (HILDON_PICKER_BUTTON (format_picker), 1);
3782 gtk_widget_set_sensitive (helper.align_picker, TRUE);
3786 format_state = modest_msg_edit_window_get_format_state (window);
3787 switch (format_state->justification) {
3788 case GTK_JUSTIFY_RIGHT:
3789 hildon_picker_button_set_active (HILDON_PICKER_BUTTON (helper.align_picker), 2);
3791 case GTK_JUSTIFY_CENTER:
3792 hildon_picker_button_set_active (HILDON_PICKER_BUTTON (helper.align_picker), 1);
3795 hildon_picker_button_set_active (HILDON_PICKER_BUTTON (helper.align_picker), 0);
3799 g_free (format_state);
3801 /* Signal connects */
3802 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3803 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3804 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3805 g_signal_connect (G_OBJECT (format_picker), "value-changed", G_CALLBACK (on_format_picker_value_changed), &helper);
3806 g_signal_connect (G_OBJECT (helper.align_picker), "value-changed",
3807 G_CALLBACK (on_align_picker_value_changed), &helper);
3809 gtk_dialog_run (GTK_DIALOG (dialog));
3811 /* Read new values */
3813 gtk_widget_destroy (dialog);
3814 g_slist_free (helper.priority_group);
3818 static void on_message_settings (GtkAction *action,
3819 ModestMsgEditWindow *window)
3821 modest_msg_edit_window_show_msg_settings_dialog (window);
3825 on_cc_button_toggled (HildonCheckButton *button,
3826 ModestMsgEditWindow *window)
3828 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
3830 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
3831 hildon_check_button_get_active (button));
3835 on_bcc_button_toggled (HildonCheckButton *button,
3836 ModestMsgEditWindow *window)
3838 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
3840 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
3841 hildon_check_button_get_active (button));
3845 setup_menu (ModestMsgEditWindow *self)
3847 ModestMsgEditWindowPrivate *priv = NULL;
3849 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
3851 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3853 /* Settings menu buttons */
3854 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_checknames"), NULL,
3855 APP_MENU_CALLBACK (modest_ui_actions_on_check_names),
3857 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_undo"), "<Ctrl>z",
3858 APP_MENU_CALLBACK (modest_ui_actions_on_undo),
3859 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_undo));
3861 priv->cc_button = hildon_check_button_new (0);
3862 gtk_button_set_label (GTK_BUTTON (priv->cc_button), _("mcen_me_editor_showcc"));
3863 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button),
3865 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->cc_button),
3867 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
3868 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
3869 priv->bcc_button = hildon_check_button_new (0);
3870 gtk_button_set_label (GTK_BUTTON (priv->bcc_button), _("mcen_me_editor_showbcc"));
3871 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button),
3873 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->bcc_button),
3875 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
3876 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
3878 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_attach_inlineimage"), NULL,
3879 APP_MENU_CALLBACK (modest_ui_actions_on_insert_image),
3880 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_set_style));
3881 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_remove_attachments"), NULL,
3882 APP_MENU_CALLBACK (modest_ui_actions_on_remove_attachments),
3883 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
3884 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_message_settings"), NULL,
3885 APP_MENU_CALLBACK (on_message_settings),
3887 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_viewer_find"), "<Ctrl>f",
3888 APP_MENU_CALLBACK (modest_ui_actions_on_toggle_find_in_page),