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 correct_scroll_idle;
271 guint scroll_drag_timeout_id;
275 TnyList *attachments;
280 TnyHeaderFlags priority_flags;
282 gboolean can_undo, can_redo;
283 gulong clipboard_change_handler_id;
284 gulong default_clipboard_change_handler_id;
285 gulong account_removed_handler_id;
286 guint clipboard_owner_idle;
287 gchar *clipboard_text;
296 GtkWidget *cc_button;
297 GtkWidget *bcc_button;
300 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
301 MODEST_TYPE_MSG_EDIT_WINDOW, \
302 ModestMsgEditWindowPrivate))
304 static GtkWindowClass *parent_class = NULL;
306 /* uncomment the following if you have defined any signals */
307 /* static guint signals[LAST_SIGNAL] = {0}; */
310 modest_msg_edit_window_get_type (void)
312 static GType my_type = 0;
314 static const GTypeInfo my_info = {
315 sizeof(ModestMsgEditWindowClass),
316 NULL, /* base init */
317 NULL, /* base finalize */
318 (GClassInitFunc) modest_msg_edit_window_class_init,
319 NULL, /* class finalize */
320 NULL, /* class data */
321 sizeof(ModestMsgEditWindow),
323 (GInstanceInitFunc) modest_msg_edit_window_init,
326 my_type = g_type_register_static (MODEST_TYPE_HILDON2_WINDOW,
327 "ModestMsgEditWindow",
335 save_state (ModestWindow *self)
337 modest_widget_memory_save (modest_runtime_get_conf(),
338 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
343 restore_settings (ModestMsgEditWindow *self)
345 ModestConf *conf = NULL;
347 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
349 conf = modest_runtime_get_conf ();
351 /* Dim at start clipboard actions */
352 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
353 gtk_action_set_sensitive (action, FALSE);
354 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
355 gtk_action_set_sensitive (action, FALSE);
356 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
357 gtk_action_set_sensitive (action, FALSE);
359 modest_widget_memory_restore (conf, G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
364 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
366 GObjectClass *gobject_class;
367 ModestWindowClass *modest_window_class;
368 gobject_class = (GObjectClass*) klass;
369 modest_window_class = (ModestWindowClass*) klass;
371 parent_class = g_type_class_peek_parent (klass);
372 gobject_class->finalize = modest_msg_edit_window_finalize;
374 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
375 modest_window_class->save_state_func = save_state;
376 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
378 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
382 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
384 ModestMsgEditWindowPrivate *priv;
385 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
387 priv->msg_body = NULL;
389 priv->from_field = NULL;
390 priv->to_field = NULL;
391 priv->cc_field = NULL;
392 priv->bcc_field = NULL;
393 priv->subject_field = NULL;
394 priv->attachments = TNY_LIST (tny_simple_list_new ());
395 priv->images = TNY_LIST (tny_simple_list_new ());
396 priv->images_size = 0;
397 priv->images_count = 0;
400 priv->cc_caption = NULL;
401 priv->bcc_caption = NULL;
402 priv->update_caption_visibility = FALSE;
404 priv->priority_flags = 0;
406 priv->find_toolbar = NULL;
407 priv->last_search = NULL;
409 priv->draft_msg = NULL;
410 priv->outbox_msg = NULL;
411 priv->msg_uid = NULL;
413 priv->can_undo = FALSE;
414 priv->can_redo = FALSE;
415 priv->clipboard_change_handler_id = 0;
416 priv->default_clipboard_change_handler_id = 0;
417 priv->account_removed_handler_id = 0;
418 priv->clipboard_owner_idle = 0;
419 priv->clipboard_text = NULL;
422 priv->scroll_drag_timeout_id = 0;
423 priv->correct_scroll_idle = 0;
424 priv->last_upper = 0.0;
426 priv->font_dialog = NULL;
427 priv->app_menu = NULL;
429 if (!is_wp_text_buffer_started) {
430 is_wp_text_buffer_started = TRUE;
431 wp_text_buffer_library_init ();
436 hildon_program_add_window (hildon_program_get_instance(),
442 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
444 static ModestPairList*
445 get_transports (void)
447 GSList *transports = NULL;
449 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
450 GSList *accounts = modest_account_mgr_account_names (account_mgr,
451 TRUE /* only enabled accounts. */);
453 GSList *cursor = accounts;
455 gchar *account_name = cursor->data;
456 gchar *from_string = NULL;
458 from_string = modest_account_mgr_get_from_string (account_mgr,
462 if (from_string && account_name) {
463 gchar *name = account_name;
464 ModestPair *pair = modest_pair_new ((gpointer) name,
465 (gpointer) from_string , TRUE);
466 transports = g_slist_prepend (transports, pair);
469 cursor = cursor->next;
471 g_slist_free (accounts); /* only free the accounts, not the elements,
472 * because they are used in the pairlist */
476 static void window_focus (GtkWindow *window,
480 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
484 scroll_drag_timeout (gpointer userdata)
486 ModestMsgEditWindow *win = (ModestMsgEditWindow *) userdata;
487 ModestMsgEditWindowPrivate *priv;
489 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(win);
491 correct_scroll_without_drag_check (win, TRUE);
493 priv->scroll_drag_timeout_id = 0;
499 correct_scroll_without_drag_check_idle (gpointer userdata)
501 ModestMsgEditWindow *w = (ModestMsgEditWindow *) userdata;
502 ModestMsgEditWindowPrivate *priv;
504 GdkRectangle rectangle;
509 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
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);
521 priv->correct_scroll_idle = 0;
526 correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused)
528 ModestMsgEditWindowPrivate *priv;
530 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
532 if (only_if_focused && !gtk_widget_is_focus (priv->msg_body))
535 if (priv->correct_scroll_idle > 0) {
539 priv->correct_scroll_idle = g_idle_add ((GSourceFunc) correct_scroll_without_drag_check_idle,
544 correct_scroll (ModestMsgEditWindow *w)
546 ModestMsgEditWindowPrivate *priv;
548 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
549 if (gtk_grab_get_current () == priv->msg_body) {
550 if (priv->scroll_drag_timeout_id == 0) {
551 priv->scroll_drag_timeout_id = g_timeout_add (500, (GSourceFunc) scroll_drag_timeout,
557 correct_scroll_without_drag_check (w, TRUE);
561 text_buffer_end_user_action (GtkTextBuffer *buffer,
562 ModestMsgEditWindow *userdata)
565 correct_scroll (userdata);
569 text_buffer_mark_set (GtkTextBuffer *buffer,
572 ModestMsgEditWindow *userdata)
574 gtk_text_buffer_begin_user_action (buffer);
575 gtk_text_buffer_end_user_action (buffer);
579 cut_clipboard_check (GtkTextView *text_view,
582 GtkTextBuffer *buffer;
584 buffer = gtk_text_view_get_buffer (text_view);
585 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
586 g_signal_stop_emission_by_name ((gpointer )text_view, "cut-clipboard");
591 copy_clipboard_check (GtkTextView *text_view,
594 GtkTextBuffer *buffer;
596 buffer = gtk_text_view_get_buffer (text_view);
597 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
598 g_signal_stop_emission_by_name ((gpointer )text_view, "copy-clipboard");
603 attachment_deleted (ModestAttachmentsView *attachments_view,
606 modest_msg_edit_window_remove_attachments (MODEST_MSG_EDIT_WINDOW (user_data),
611 connect_signals (ModestMsgEditWindow *obj)
613 ModestMsgEditWindowPrivate *priv;
615 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
617 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
618 G_CALLBACK (text_buffer_refresh_attributes), obj);
619 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
620 G_CALLBACK (text_buffer_can_undo), obj);
621 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
622 G_CALLBACK (text_buffer_can_redo), obj);
623 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
624 G_CALLBACK (body_changed), obj);
625 g_signal_connect (G_OBJECT (priv->text_buffer), "modified-changed",
626 G_CALLBACK (body_changed), obj);
627 g_signal_connect (G_OBJECT (priv->text_buffer), "end-user-action",
628 G_CALLBACK (text_buffer_end_user_action), obj);
629 g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
630 G_CALLBACK (text_buffer_mark_set), obj);
631 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
632 G_CALLBACK (text_buffer_apply_tag), obj);
633 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
634 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
635 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
636 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
637 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
638 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
640 g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
641 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
643 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
644 G_CALLBACK (msg_body_focus), obj);
645 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
646 G_CALLBACK (msg_body_focus), obj);
647 g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
648 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
649 "changed", G_CALLBACK (recpt_field_changed), obj);
650 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
651 "changed", G_CALLBACK (recpt_field_changed), obj);
652 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
653 "changed", G_CALLBACK (recpt_field_changed), obj);
654 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
655 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
656 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
658 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
659 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
661 priv->clipboard_change_handler_id =
662 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
663 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
664 priv->default_clipboard_change_handler_id =
665 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
666 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
668 g_signal_connect (G_OBJECT (priv->msg_body), "cut-clipboard", G_CALLBACK (cut_clipboard_check), NULL);
669 g_signal_connect (G_OBJECT (priv->msg_body), "copy-clipboard", G_CALLBACK (copy_clipboard_check), NULL);
670 g_signal_connect (G_OBJECT (priv->attachments_view), "delete", G_CALLBACK (attachment_deleted), obj);
674 init_wp_text_view_style ()
676 static gboolean initialized = FALSE;
679 gtk_rc_parse_string ("class \"WPTextView\" style \"fremantle-textview\"");
685 init_window (ModestMsgEditWindow *obj)
687 GtkWidget *to_caption, *subject_caption;
688 GtkWidget *main_vbox;
689 ModestMsgEditWindowPrivate *priv;
690 GtkActionGroup *action_group;
691 ModestWindowPrivate *parent_priv;
692 GdkPixbuf *window_icon = NULL;
693 GError *error = NULL;
695 GtkSizeGroup *title_size_group;
696 GtkSizeGroup *value_size_group;
697 GtkWidget *subject_box;
698 GtkWidget *attachment_icon;
699 GtkWidget *window_box;
700 #if (GTK_MINOR_VERSION >= 10)
701 GdkAtom deserialize_type;
704 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
705 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
707 parent_priv->ui_manager = gtk_ui_manager_new();
708 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
709 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
711 /* Add common actions */
712 gtk_action_group_add_actions (action_group,
713 modest_msg_edit_action_entries,
714 G_N_ELEMENTS (modest_msg_edit_action_entries),
716 gtk_action_group_add_actions (action_group,
717 hildon2_msg_edit_action_entries,
718 G_N_ELEMENTS (hildon2_msg_edit_action_entries),
720 gtk_action_group_add_toggle_actions (action_group,
721 modest_msg_edit_toggle_action_entries,
722 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
724 gtk_action_group_add_radio_actions (action_group,
725 modest_msg_edit_alignment_radio_action_entries,
726 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
728 G_CALLBACK (modest_ui_actions_on_change_justify),
730 gtk_action_group_add_radio_actions (action_group,
731 modest_msg_edit_priority_action_entries,
732 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
734 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
736 gtk_action_group_add_radio_actions (action_group,
737 modest_msg_edit_file_format_action_entries,
738 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
739 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
740 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
742 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
743 g_object_unref (action_group);
745 /* Load the UI definition */
746 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
749 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
750 g_clear_error (&error);
753 /* Add accelerators */
754 gtk_window_add_accel_group (GTK_WINDOW (obj),
755 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
757 parent_priv->menubar = NULL;
759 title_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
760 value_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
762 /* Note: This ModestPairList* must exist for as long as the picker
763 * that uses it, because the ModestSelectorPicker uses the ID opaquely,
764 * so it can't know how to manage its memory. */
765 priv->from_field = modest_selector_picker_new (MODEST_EDITABLE_SIZE,
766 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL,
768 modest_maemo_utils_set_hbutton_layout (title_size_group, value_size_group,
769 _("mail_va_from"), priv->from_field);
771 priv->to_field = modest_recpt_editor_new ();
772 priv->cc_field = modest_recpt_editor_new ();
773 priv->bcc_field = modest_recpt_editor_new ();
774 subject_box = gtk_hbox_new (FALSE, 0);
775 priv->priority_icon = gtk_image_new ();
776 gtk_box_pack_start (GTK_BOX (subject_box), priv->priority_icon, FALSE, FALSE, 0);
777 priv->subject_field = hildon_entry_new (MODEST_EDITABLE_SIZE);
778 gtk_entry_set_max_length (GTK_ENTRY (priv->subject_field) ,SUBJECT_MAX_LENGTH);
779 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
780 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
781 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
782 gtk_box_pack_start (GTK_BOX (subject_box), priv->subject_field, TRUE, TRUE, 0);
783 priv->add_attachment_button = gtk_button_new ();
784 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
785 gtk_button_set_relief (GTK_BUTTON (priv->add_attachment_button), GTK_RELIEF_NONE);
786 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
787 gtk_button_set_alignment (GTK_BUTTON (priv->add_attachment_button), 1.0, 0.5);
788 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, HILDON_ICON_SIZE_FINGER);
789 gtk_container_add (GTK_CONTAINER (priv->add_attachment_button), attachment_icon);
790 gtk_box_pack_start (GTK_BOX (subject_box), priv->add_attachment_button, FALSE, FALSE, 0);
791 priv->attachments_view = modest_attachments_view_new (NULL);
793 priv->header_box = gtk_vbox_new (FALSE, 0);
795 to_caption = modest_maemo_utils_create_captioned_with_size_type
796 (title_size_group, value_size_group,
797 _("mail_va_to"), FALSE, priv->to_field,
798 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
799 priv->cc_caption = modest_maemo_utils_create_captioned_with_size_type
800 (title_size_group, value_size_group,
801 _("mail_va_cc"), FALSE, priv->cc_field,
802 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
803 priv->bcc_caption = modest_maemo_utils_create_captioned_with_size_type
804 (title_size_group, value_size_group,
805 _("mail_va_hotfix1"), FALSE, priv->bcc_field,
806 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
807 subject_caption = modest_maemo_utils_create_captioned (title_size_group, value_size_group,
808 _("mail_va_subject"), FALSE, subject_box);
809 priv->attachments_caption = modest_maemo_utils_create_captioned_with_size_type (title_size_group, value_size_group,
810 _("mail_va_attachment"),
812 priv->attachments_view,
813 HILDON_SIZE_AUTO_WIDTH |
814 HILDON_SIZE_AUTO_HEIGHT);
815 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), value_size_group); */
816 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), value_size_group); */
817 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), value_size_group); */
818 g_object_unref (title_size_group);
819 g_object_unref (value_size_group);
821 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->from_field, FALSE, FALSE, 0);
822 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
823 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
824 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
825 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
826 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
827 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
829 init_wp_text_view_style ();
831 priv->msg_body = wp_text_view_new ();
834 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
835 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
836 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
837 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
838 #if (GTK_MINOR_VERSION >= 10)
839 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
840 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
842 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
843 deserialize_type, TRUE);
845 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
847 priv->find_toolbar = hildon_find_toolbar_new (NULL);
848 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
850 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
852 priv->pannable = hildon_pannable_area_new ();
854 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
856 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
857 priv->frame = gtk_frame_new (NULL);
858 gtk_box_pack_start (GTK_BOX(main_vbox), priv->frame, TRUE, TRUE, 0);
860 hildon_pannable_area_add_with_viewport (HILDON_PANNABLE_AREA (priv->pannable), main_vbox);
861 gtk_widget_show_all (GTK_WIDGET(priv->pannable));
863 window_box = gtk_vbox_new (FALSE, 0);
864 gtk_container_add (GTK_CONTAINER(obj), window_box);
866 gtk_box_pack_start (GTK_BOX (window_box), priv->pannable, TRUE, TRUE, 0);
868 gtk_container_add (GTK_CONTAINER (priv->frame), priv->msg_body);
870 /* Set window icon */
871 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
873 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
874 g_object_unref (window_icon);
879 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
881 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
883 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
884 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
885 priv->clipboard_change_handler_id))
886 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
887 priv->clipboard_change_handler_id);
888 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
889 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
890 priv->default_clipboard_change_handler_id))
891 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
892 priv->default_clipboard_change_handler_id);
894 if (priv->account_removed_handler_id &&
895 g_signal_handler_is_connected (modest_runtime_get_account_store (),
896 priv->account_removed_handler_id))
897 g_signal_handler_disconnect(modest_runtime_get_account_store (),
898 priv->account_removed_handler_id);
902 modest_msg_edit_window_finalize (GObject *obj)
904 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
906 /* Sanity check: shouldn't be needed, the window mgr should
907 call this function before */
908 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
910 if (priv->font_dialog != NULL) {
911 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
914 if (priv->clipboard_text != NULL) {
915 g_free (priv->clipboard_text);
916 priv->clipboard_text = NULL;
919 if (priv->draft_msg != NULL) {
920 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
921 if (TNY_IS_HEADER (header)) {
922 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
923 modest_window_mgr_unregister_header (mgr, header);
925 g_object_unref (priv->draft_msg);
926 priv->draft_msg = NULL;
928 if (priv->outbox_msg != NULL) {
929 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
930 if (TNY_IS_HEADER (header)) {
931 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
932 modest_window_mgr_unregister_header (mgr, header);
934 g_object_unref (priv->outbox_msg);
935 priv->outbox_msg = NULL;
937 if (priv->correct_scroll_idle > 0) {
938 g_source_remove (priv->correct_scroll_idle);
939 priv->correct_scroll_idle = 0;
941 if (priv->scroll_drag_timeout_id > 0) {
942 g_source_remove (priv->scroll_drag_timeout_id);
943 priv->scroll_drag_timeout_id = 0;
945 if (priv->clipboard_owner_idle > 0) {
946 g_source_remove (priv->clipboard_owner_idle);
947 priv->clipboard_owner_idle = 0;
949 if (priv->original_account_name)
950 g_free (priv->original_account_name);
951 g_free (priv->msg_uid);
952 g_free (priv->last_search);
953 g_slist_free (priv->font_items_group);
954 g_slist_free (priv->size_items_group);
955 g_object_unref (priv->attachments);
956 g_object_unref (priv->images);
958 /* This had to stay alive for as long as the picker that used it: */
959 modest_pair_list_free (priv->from_field_protos);
961 G_OBJECT_CLASS(parent_class)->finalize (obj);
965 pixbuf_from_stream (TnyStream *stream, const gchar *mime_type, guint64 *stream_size)
967 GdkPixbufLoader *loader;
973 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
975 if (loader == NULL) {
981 tny_stream_reset (TNY_STREAM (stream));
982 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
983 GError *error = NULL;
984 unsigned char read_buffer[128];
986 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
988 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
990 g_error_free (error);
995 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
997 g_object_ref (pixbuf);
998 gdk_pixbuf_loader_close (loader, NULL);
999 g_object_unref (loader);
1004 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1005 GdkPixbuf *new_pixbuf;
1007 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1008 gdk_pixbuf_get_width (pixbuf);
1009 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1010 g_object_unref (pixbuf);
1011 pixbuf = new_pixbuf;
1015 *stream_size = size;
1021 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1023 ModestMsgEditWindowPrivate *priv;
1026 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1028 for (iter = tny_list_create_iterator (attachments);
1029 !tny_iterator_is_done (iter);
1030 tny_iterator_next (iter)) {
1031 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1032 const gchar *cid = tny_mime_part_get_content_id (part);
1033 const gchar *mime_type = tny_mime_part_get_content_type (part);
1034 if ((cid != NULL)&&(mime_type != NULL)) {
1035 guint64 stream_size;
1036 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1037 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
1040 g_object_unref (stream);
1042 if (pixbuf != NULL) {
1043 priv->images_count ++;
1044 priv->images_size += stream_size;
1045 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1046 g_object_unref (pixbuf);
1049 g_object_unref (part);
1051 g_object_unref (iter);
1055 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1057 TnyMimePart *parent = NULL;
1058 const gchar *content_type = NULL;
1059 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1061 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1063 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1064 parent = g_object_ref (msg);
1065 } else if (content_type && !g_strcasecmp (content_type, "multipart/mixed")) {
1066 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1069 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1070 iter = tny_list_create_iterator (parts);
1071 while (!tny_iterator_is_done (iter)) {
1073 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1074 content_type = tny_mime_part_get_content_type (part);
1075 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1079 g_object_unref (part);
1081 tny_iterator_next (iter);
1083 g_object_unref (iter);
1084 g_object_unref (parts);
1087 if (parent != NULL) {
1088 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1091 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1092 iter = tny_list_create_iterator (parts);
1093 while (!tny_iterator_is_done (iter)) {
1095 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1096 content_type = tny_mime_part_get_content_type (part);
1097 if (content_type && g_str_has_prefix (content_type, "image/")) {
1098 tny_list_prepend (priv->images, (GObject *) part);
1100 g_object_unref (part);
1101 tny_iterator_next (iter);
1103 g_object_unref (iter);
1104 g_object_unref (parts);
1105 g_object_unref (parent);
1110 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1113 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1115 for (iter = tny_list_create_iterator (attachments) ;
1116 !tny_iterator_is_done (iter);
1117 tny_iterator_next (iter)) {
1118 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1119 const gchar *cid = tny_mime_part_get_content_id (part);
1121 char *invalid = NULL;
1122 gint int_cid = strtol (cid, &invalid, 10);
1123 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1124 priv->next_cid = int_cid + 1;
1127 g_object_unref (part);
1129 g_object_unref (iter);
1133 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1136 gchar *to, *cc, *bcc, *subject;
1138 ModestMsgEditWindowPrivate *priv;
1139 ModestWindowPrivate *parent_priv;
1141 TnyHeaderFlags priority_flags;
1142 TnyFolder *msg_folder;
1143 gboolean is_html = FALSE;
1144 gboolean field_view_set;
1146 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1147 g_return_if_fail (TNY_IS_MSG (msg));
1149 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1150 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1152 header = tny_msg_get_header (msg);
1153 to = tny_header_dup_to (header);
1154 cc = tny_header_dup_cc (header);
1155 bcc = tny_header_dup_bcc (header);
1156 subject = tny_header_dup_subject (header);
1157 priority_flags = tny_header_get_priority (header);
1160 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
1162 field_view_set = TRUE;
1164 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
1165 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1166 gtk_widget_show (priv->cc_caption);
1167 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1168 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1169 gtk_widget_hide (priv->cc_caption);
1170 field_view_set = FALSE;
1172 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button), field_view_set);
1174 field_view_set = TRUE;
1176 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
1177 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1178 gtk_widget_show (priv->bcc_caption);
1179 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1180 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1181 gtk_widget_hide (priv->bcc_caption);
1182 field_view_set = FALSE;
1184 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button), field_view_set);
1188 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1189 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1192 update_window_title (self);
1194 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1195 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1197 if ((body == NULL)||(body[0] == '\0')) {
1199 body = modest_text_utils_convert_to_html ("");
1202 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1203 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1206 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1209 /* Add attachments to the view */
1210 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1211 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1212 if (tny_list_get_length (priv->attachments) == 0) {
1213 gtk_widget_hide (priv->attachments_caption);
1215 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1216 gtk_widget_show_all (priv->attachments_caption);
1218 get_related_images (self, msg);
1219 update_next_cid (self, priv->attachments);
1220 update_next_cid (self, priv->images);
1221 replace_with_images (self, priv->images);
1223 if (preserve_is_rich && !is_html) {
1224 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1225 /* Get the default format required from configuration */
1226 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1227 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1230 /* Set the default focus depending on having already a To: field or not */
1231 if ((!to)||(*to == '\0')) {
1232 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1234 gtk_widget_grab_focus (priv->msg_body);
1237 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1239 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1240 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1242 modest_msg_edit_window_set_modified (self, FALSE);
1244 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1245 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1246 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1247 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1249 if (priv->msg_uid) {
1250 g_free (priv->msg_uid);
1251 priv->msg_uid = NULL;
1254 /* we should set a reference to the incoming message if it is a draft */
1255 msg_folder = tny_msg_get_folder (msg);
1257 if (modest_tny_folder_is_local_folder (msg_folder)) {
1258 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1259 if (type == TNY_FOLDER_TYPE_INVALID)
1260 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1262 if (type == TNY_FOLDER_TYPE_DRAFTS)
1263 priv->draft_msg = g_object_ref(msg);
1264 if (type == TNY_FOLDER_TYPE_OUTBOX)
1265 priv->outbox_msg = g_object_ref(msg);
1266 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1268 g_object_unref (msg_folder);
1278 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
1281 GList *item_children, *node;
1282 GtkWidget *bin_child;
1284 bin_child = gtk_bin_get_child (GTK_BIN(item));
1286 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
1288 for (node = item_children; node != NULL; node = g_list_next (node)) {
1289 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
1290 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
1293 g_list_free (item_children);
1297 menu_tool_button_dont_expand (GtkMenuToolButton *item)
1300 GList *item_children, *node;
1302 box = gtk_bin_get_child (GTK_BIN (item));
1303 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
1304 item_children = gtk_container_get_children (GTK_CONTAINER (box));
1306 for (node = item_children; node != NULL; node = g_list_next (node)) {
1307 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
1308 if (GTK_IS_TOGGLE_BUTTON (node->data))
1309 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
1310 else if (GTK_IS_BUTTON (node->data))
1311 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
1313 g_list_free (item_children);
1318 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1320 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1321 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1322 GtkWidget *placeholder;
1323 GtkWidget *tool_item;
1328 GtkWidget *sizes_menu;
1329 GtkWidget *fonts_menu;
1330 GSList *radio_group = NULL;
1331 GSList *node = NULL;
1335 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1336 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1338 /* Font color placeholder */
1339 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1340 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1343 priv->font_color_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1344 priv->font_color_button = hildon_color_button_new ();
1345 GTK_WIDGET_UNSET_FLAGS (priv->font_color_toolitem, GTK_CAN_FOCUS);
1346 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1347 gtk_container_add (GTK_CONTAINER (priv->font_color_toolitem), priv->font_color_button);
1348 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1349 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1350 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->font_color_toolitem), insert_index);
1351 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1353 G_CALLBACK (modest_msg_edit_window_color_button_change),
1356 /* Font size and face placeholder */
1357 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1358 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1360 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1361 priv->size_tool_button_label = gtk_label_new (NULL);
1362 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1363 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1364 size_text,"</span>", NULL);
1365 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1367 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
1368 sizes_menu = gtk_menu_new ();
1369 priv->size_items_group = NULL;
1371 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1372 GtkWidget *size_menu_item;
1374 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1375 size_menu_item = gtk_radio_menu_item_new_with_label (radio_group, size_text);
1376 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (size_menu_item));
1377 gtk_menu_shell_append (GTK_MENU_SHELL (sizes_menu), size_menu_item);
1378 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (size_menu_item), (wp_font_size[size_index] == 12));
1379 gtk_widget_show (size_menu_item);
1381 priv->size_items_group = g_slist_prepend (priv->size_items_group, size_menu_item);
1385 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1386 GtkWidget *item = (GtkWidget *) node->data;
1387 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_size_change),
1391 priv->size_items_group = g_slist_reverse (priv->size_items_group);
1392 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), sizes_menu);
1393 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1394 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1395 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1396 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1397 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1398 priv->font_size_toolitem = tool_item;
1401 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1402 priv->font_tool_button_label = gtk_label_new (NULL);
1403 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1404 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1406 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
1407 fonts_menu = gtk_menu_new ();
1408 priv->font_items_group = NULL;
1410 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1411 GtkWidget *font_menu_item;
1412 GtkWidget *child_label;
1414 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
1415 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
1416 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
1417 wp_get_font_name (font_index), "</span>", NULL);
1418 gtk_label_set_markup (GTK_LABEL (child_label), markup);
1421 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
1422 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
1423 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
1424 gtk_widget_show (font_menu_item);
1426 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
1429 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1430 GtkWidget *item = (GtkWidget *) node->data;
1431 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
1434 priv->font_items_group = g_slist_reverse (priv->font_items_group);
1435 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
1436 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1437 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1438 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1439 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1440 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1441 priv->font_face_toolitem = tool_item;
1443 /* Set expand and homogeneous for remaining items */
1444 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
1445 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1446 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1447 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1448 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1449 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1450 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1451 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1452 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1454 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1455 will not show the tool items added to the placeholders) */
1456 gtk_widget_show_all (parent_priv->toolbar);
1458 /* Set the no show all *after* showing all items. We do not
1459 want the toolbar to be shown with a show all because it
1460 could go agains the gconf setting regarding showing or not
1461 the toolbar of the editor window */
1462 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1468 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, gboolean preserve_is_rich)
1471 ModestWindowPrivate *parent_priv;
1472 ModestMsgEditWindowPrivate *priv;
1473 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1474 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1475 ModestWindowMgr *mgr = NULL;
1477 g_return_val_if_fail (msg, NULL);
1478 g_return_val_if_fail (account_name, NULL);
1480 mgr = modest_runtime_get_window_mgr ();
1482 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1484 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1485 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1487 /* Menubar. Update the state of some toggles */
1488 priv->from_field_protos = get_transports ();
1489 modest_selector_picker_set_pair_list (MODEST_SELECTOR_PICKER (priv->from_field), priv->from_field_protos);
1490 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1491 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1493 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1494 hildon_touch_selector_get_current_text
1495 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1496 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1497 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1500 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1502 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1504 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1506 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1508 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1509 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1510 /* Add common dimming rules */
1511 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1512 modest_msg_edit_window_toolbar_dimming_entries,
1513 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1514 MODEST_WINDOW (obj));
1515 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_toolitem,
1516 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1517 MODEST_WINDOW (obj));
1518 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1519 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1520 MODEST_WINDOW (obj));
1521 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1522 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1523 MODEST_WINDOW (obj));
1524 /* Insert dimming rules group for this window */
1525 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1526 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1528 /* Setup app menu */
1529 setup_menu (MODEST_MSG_EDIT_WINDOW (obj));
1531 /* Checks the dimming rules */
1532 g_object_unref (toolbar_rules_group);
1533 g_object_unref (clipboard_rules_group);
1534 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1536 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1538 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1539 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1540 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1541 priv->update_caption_visibility = TRUE;
1543 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1545 /* Track account-removed signal, this window should be closed
1546 in the case we're creating a mail associated to the account
1548 priv->account_removed_handler_id =
1549 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1551 G_CALLBACK(on_account_removed),
1554 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1556 return (ModestWindow*) obj;
1560 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1562 GString **string_buffer = (GString **) user_data;
1564 *string_buffer = g_string_append (*string_buffer, buffer);
1570 * @result: A new string which should be freed with g_free().
1573 get_formatted_data (ModestMsgEditWindow *edit_window)
1575 ModestMsgEditWindowPrivate *priv;
1576 GString *string_buffer = g_string_new ("");
1578 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1580 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1582 modest_text_utils_hyperlinkify (string_buffer);
1584 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1586 return g_string_free (string_buffer, FALSE);
1591 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1594 const gchar *account_name;
1595 ModestMsgEditWindowPrivate *priv;
1596 TnyIterator *att_iter;
1598 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1600 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1602 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1603 g_return_val_if_fail (account_name, NULL);
1606 /* don't free these (except from) */
1607 data = g_slice_new0 (MsgData);
1608 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1610 data->account_name = g_strdup (account_name);
1611 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1612 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1613 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1614 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1615 if (priv->draft_msg) {
1616 data->draft_msg = g_object_ref (priv->draft_msg);
1617 } else if (priv->outbox_msg) {
1618 data->draft_msg = g_object_ref (priv->outbox_msg);
1620 data->draft_msg = NULL;
1623 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1625 gtk_text_buffer_get_bounds (buf, &b, &e);
1626 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1628 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1629 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1631 data->html_body = NULL;
1633 /* deep-copy the data */
1634 att_iter = tny_list_create_iterator (priv->attachments);
1635 data->attachments = NULL;
1636 while (!tny_iterator_is_done (att_iter)) {
1637 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1638 if (!(TNY_IS_MIME_PART(part))) {
1639 g_warning ("strange data in attachment list");
1640 g_object_unref (part);
1641 tny_iterator_next (att_iter);
1644 data->attachments = g_list_append (data->attachments,
1646 tny_iterator_next (att_iter);
1648 g_object_unref (att_iter);
1650 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1651 att_iter = tny_list_create_iterator (priv->images);
1652 data->images = NULL;
1653 while (!tny_iterator_is_done (att_iter)) {
1654 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1656 if (!(TNY_IS_MIME_PART(part))) {
1657 g_warning ("strange data in attachment list");
1658 g_object_unref (part);
1659 tny_iterator_next (att_iter);
1662 cid = tny_mime_part_get_content_id (part);
1664 gchar *image_tag_id;
1665 GtkTextTag *image_tag;
1667 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1668 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1669 g_free (image_tag_id);
1671 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1673 ((gtk_text_iter_has_tag (&iter, image_tag))||
1674 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1675 data->images = g_list_append (data->images,
1676 g_object_ref (part));
1678 g_object_unref (part);
1679 tny_iterator_next (att_iter);
1681 g_object_unref (att_iter);
1683 data->priority_flags = priv->priority_flags;
1690 unref_gobject (GObject *obj, gpointer data)
1692 if (!G_IS_OBJECT(obj))
1694 g_object_unref (obj);
1698 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1701 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1709 g_free (data->from);
1710 g_free (data->subject);
1711 g_free (data->plain_body);
1712 g_free (data->html_body);
1713 g_free (data->account_name);
1715 if (data->draft_msg != NULL) {
1716 g_object_unref (data->draft_msg);
1717 data->draft_msg = NULL;
1720 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1721 g_list_free (data->attachments);
1722 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1723 g_list_free (data->images);
1725 g_slice_free (MsgData, data);
1729 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1731 guint64 *parts_size)
1733 ModestMsgEditWindowPrivate *priv;
1735 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1737 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1739 /* TODO: add images */
1740 *parts_size += priv->images_size;
1741 *parts_count += priv->images_count;
1746 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1749 ModestMsgEditWindowPrivate *priv = NULL;
1750 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1752 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1754 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1756 return MODEST_MSG_EDIT_FORMAT_HTML;
1758 return MODEST_MSG_EDIT_FORMAT_TEXT;
1762 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1763 ModestMsgEditFormat format)
1765 ModestMsgEditWindowPrivate *priv;
1767 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1768 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1771 case MODEST_MSG_EDIT_FORMAT_HTML:
1772 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1774 case MODEST_MSG_EDIT_FORMAT_TEXT:
1775 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1778 g_return_if_reached ();
1782 ModestMsgEditFormatState *
1783 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1785 ModestMsgEditFormatState *format_state = NULL;
1786 ModestMsgEditWindowPrivate *priv;
1787 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1789 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1790 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1792 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1794 format_state = g_new0 (ModestMsgEditFormatState, 1);
1795 format_state->bold = buffer_format->bold&0x1;
1796 format_state->italics = buffer_format->italic&0x1;
1797 format_state->bullet = buffer_format->bullet&0x1;
1798 format_state->color = buffer_format->color;
1799 format_state->font_size = buffer_format->font_size;
1800 format_state->font_family = wp_get_font_name (buffer_format->font);
1801 format_state->justification = buffer_format->justification;
1802 g_free (buffer_format);
1804 return format_state;
1809 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1810 const ModestMsgEditFormatState *format_state)
1812 ModestMsgEditWindowPrivate *priv;
1813 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1814 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1815 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1816 g_return_if_fail (format_state != NULL);
1818 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1819 gtk_widget_grab_focus (priv->msg_body);
1820 buffer_format->bold = (format_state->bold != FALSE);
1821 buffer_format->italic = (format_state->italics != FALSE);
1822 buffer_format->color = format_state->color;
1823 buffer_format->font_size = format_state->font_size;
1824 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1825 buffer_format->justification = format_state->justification;
1826 buffer_format->bullet = format_state->bullet;
1828 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1830 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1831 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1832 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1833 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1834 buffer_format->cs.font = (buffer_format->font != current_format->font);
1835 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1836 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1838 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1839 if (buffer_format->cs.bold) {
1840 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
1841 GINT_TO_POINTER (buffer_format->bold&0x1));
1843 if (buffer_format->cs.italic) {
1844 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
1845 GINT_TO_POINTER (buffer_format->italic&0x1));
1847 if (buffer_format->cs.color) {
1848 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1849 GINT_TO_POINTER (&(buffer_format->color)));
1851 if (buffer_format->cs.font_size) {
1852 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1853 GINT_TO_POINTER (buffer_format->font_size));
1855 if (buffer_format->cs.justification) {
1856 switch (buffer_format->justification) {
1857 case GTK_JUSTIFY_LEFT:
1858 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
1859 GINT_TO_POINTER(TRUE));
1861 case GTK_JUSTIFY_CENTER:
1862 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
1863 GINT_TO_POINTER(TRUE));
1865 case GTK_JUSTIFY_RIGHT:
1866 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
1867 GINT_TO_POINTER(TRUE));
1874 if (buffer_format->cs.font) {
1875 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1876 GINT_TO_POINTER (buffer_format->font));
1878 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1879 if (buffer_format->cs.bullet) {
1880 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
1881 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
1883 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1885 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
1887 g_free (buffer_format);
1888 g_free (current_format);
1890 /* Check dimming rules */
1891 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1892 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1896 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1898 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1900 ModestWindowPrivate *parent_priv;
1901 ModestMsgEditWindowPrivate *priv;
1902 GtkWidget *new_size_menuitem;
1903 GtkWidget *new_font_menuitem;
1905 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1906 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1908 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1909 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu");
1910 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1911 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1913 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatPlainTextMenu");
1914 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1915 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1918 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1920 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1921 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1923 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1924 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1926 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
1927 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
1930 switch (buffer_format->justification)
1932 case GTK_JUSTIFY_LEFT:
1933 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
1935 case GTK_JUSTIFY_CENTER:
1936 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
1938 case GTK_JUSTIFY_RIGHT:
1939 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
1946 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
1948 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1949 G_CALLBACK (modest_msg_edit_window_color_button_change),
1951 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1952 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1953 G_CALLBACK (modest_msg_edit_window_color_button_change),
1956 new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group,
1957 buffer_format->font_size))->data);
1958 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1962 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1963 markup = g_strconcat ("<span font_family='Sans'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1964 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1966 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1967 G_CALLBACK (modest_msg_edit_window_size_change),
1969 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
1970 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
1971 G_CALLBACK (modest_msg_edit_window_size_change),
1975 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
1976 buffer_format->font))->data);
1977 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
1981 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
1982 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1983 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1985 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
1986 G_CALLBACK (modest_msg_edit_window_font_change),
1988 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
1989 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
1990 G_CALLBACK (modest_msg_edit_window_font_change),
1994 g_free (buffer_format);
1998 #ifdef MODEST_HILDON_VERSION_0
2000 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2003 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2004 ModestMsgEditWindowPrivate *priv;
2005 GtkWidget *dialog = NULL;
2007 GdkColor *new_color = NULL;
2009 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2010 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2012 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2013 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
2014 g_free (buffer_format);
2016 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2017 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2018 if (new_color != NULL) {
2019 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2020 (gpointer) new_color);
2023 gtk_widget_destroy (dialog);
2028 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2031 ModestMsgEditWindowPrivate *priv;
2032 GtkWidget *dialog = NULL;
2034 GdkColor *old_color = NULL;
2035 const GdkColor *new_color = NULL;
2037 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2038 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2040 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2041 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2043 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2044 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2045 if (new_color != NULL)
2046 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2048 gtk_widget_destroy (dialog);
2054 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2057 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2058 ModestMsgEditWindowPrivate *priv;
2059 GtkWidget *dialog = NULL;
2061 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2062 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2064 dialog = hildon_color_chooser_new ();
2065 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2066 g_free (buffer_format);
2068 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2070 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2071 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2074 gtk_widget_destroy (dialog);
2079 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2082 ModestMsgEditWindowPrivate *priv;
2083 GtkWidget *dialog = NULL;
2084 GdkColor *old_color = NULL;
2086 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2087 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2089 dialog = hildon_color_chooser_new ();
2090 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2092 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2094 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2095 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2097 gtk_widget_destroy (dialog);
2100 #endif /*!MODEST_HILDON_VERSION_0*/
2105 create_stream_for_uri (const gchar* uri)
2110 TnyStream *result = NULL;
2112 GnomeVFSHandle *handle = NULL;
2113 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2114 if (test == GNOME_VFS_OK) {
2115 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2116 /* Streams over OBEX (Bluetooth) are not seekable but
2117 * we expect them to be (we might need to read them
2118 * several times). So if this is a Bluetooth URI just
2119 * read the whole file into memory (this is not a fast
2120 * protocol so we can assume that these files are not
2121 * going to be very big) */
2122 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2123 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2124 TnyStream *memstream = tny_camel_mem_stream_new ();
2125 tny_stream_write_to_stream (vfssstream, memstream);
2126 g_object_unref (vfssstream);
2129 result = vfssstream;
2137 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2140 ModestMsgEditWindowPrivate *priv;
2141 GtkWidget *dialog = NULL;
2143 GSList *uris = NULL;
2144 GSList *uri_node = NULL;
2146 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2148 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2149 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2150 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2152 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2154 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2155 GTK_WINDOW (dialog), GTK_WINDOW (window));
2157 response = gtk_dialog_run (GTK_DIALOG (dialog));
2159 case GTK_RESPONSE_OK:
2160 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2165 gtk_widget_destroy (dialog);
2167 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2169 GnomeVFSHandle *handle = NULL;
2170 GnomeVFSResult result;
2171 GtkTextIter position;
2172 GtkTextMark *insert_mark;
2174 uri = (const gchar *) uri_node->data;
2175 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2176 if (result == GNOME_VFS_OK) {
2178 GnomeVFSFileInfo *info;
2179 gchar *filename, *basename, *escaped_filename;
2180 TnyMimePart *mime_part;
2182 const gchar *mime_type = NULL;
2183 GnomeVFSURI *vfs_uri;
2184 guint64 stream_size;
2186 gnome_vfs_close (handle);
2187 vfs_uri = gnome_vfs_uri_new (uri);
2189 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2190 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2191 g_free (escaped_filename);
2192 gnome_vfs_uri_unref (vfs_uri);
2193 info = gnome_vfs_file_info_new ();
2195 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2196 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2198 mime_type = gnome_vfs_file_info_get_mime_type (info);
2200 mime_part = tny_platform_factory_new_mime_part
2201 (modest_runtime_get_platform_factory ());
2203 TnyStream *stream = create_stream_for_uri (uri);
2205 if (stream == NULL) {
2207 modest_platform_information_banner (NULL, NULL, dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2209 g_object_unref (mime_part);
2210 gnome_vfs_file_info_unref (info);
2214 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2216 content_id = g_strdup_printf ("%d", priv->next_cid);
2217 tny_mime_part_set_content_id (mime_part, content_id);
2218 g_free (content_id);
2221 basename = g_path_get_basename (filename);
2222 tny_mime_part_set_filename (mime_part, basename);
2225 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
2227 if (pixbuf != NULL) {
2228 priv->images_size += stream_size;
2229 priv->images_count ++;
2230 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2231 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2232 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
2233 g_object_unref (pixbuf);
2236 tny_list_prepend (priv->images, (GObject *) mime_part);
2237 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2239 g_object_unref (mime_part);
2240 gnome_vfs_file_info_unref (info);
2249 on_attach_file_response (GtkDialog *dialog,
2253 GSList *uris = NULL;
2255 GnomeVFSFileSize total_size, allowed_size;
2256 ModestMsgEditWindow *window;
2257 ModestMsgEditWindowPrivate *priv;
2262 case GTK_RESPONSE_OK:
2263 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2269 window = MODEST_MSG_EDIT_WINDOW (user_data);
2270 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2272 /* allowed size is the maximum size - what's already there */
2273 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2274 &att_num, &att_size);
2275 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2278 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2280 const gchar *uri = (const gchar *) uri_node->data;
2283 modest_msg_edit_window_attach_file_one (window, uri, allowed_size);
2285 if (total_size > allowed_size) {
2286 g_warning ("%s: total size: %u",
2287 __FUNCTION__, (unsigned int)total_size);
2290 allowed_size -= total_size;
2292 g_slist_foreach (uris, (GFunc) g_free, NULL);
2293 g_slist_free (uris);
2295 gtk_widget_destroy (GTK_WIDGET (dialog));
2299 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2301 GtkWidget *dialog = NULL;
2302 ModestMsgEditWindowPrivate *priv;
2304 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2306 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2308 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2311 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window),
2312 GTK_FILE_CHOOSER_ACTION_OPEN);
2313 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2314 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2315 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2316 GTK_WINDOW (dialog), GTK_WINDOW (window));
2318 /* Connect to response & show */
2319 g_signal_connect (dialog, "response",
2320 G_CALLBACK (on_attach_file_response), window);
2321 gtk_widget_show (dialog);
2326 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2328 GnomeVFSFileSize allowed_size)
2331 GnomeVFSHandle *handle = NULL;
2332 ModestMsgEditWindowPrivate *priv;
2333 GnomeVFSResult result;
2334 GnomeVFSFileSize size = 0;
2335 g_return_val_if_fail (window, 0);
2336 g_return_val_if_fail (uri, 0);
2338 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2340 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2341 if (result == GNOME_VFS_OK) {
2342 TnyMimePart *mime_part;
2344 const gchar *mime_type = NULL;
2346 gchar *escaped_filename;
2349 GnomeVFSFileInfo *info;
2350 GnomeVFSURI *vfs_uri;
2352 gnome_vfs_close (handle);
2353 vfs_uri = gnome_vfs_uri_new (uri);
2356 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2357 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2358 g_free (escaped_filename);
2359 gnome_vfs_uri_unref (vfs_uri);
2361 info = gnome_vfs_file_info_new ();
2363 if (gnome_vfs_get_file_info (uri,
2365 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2367 mime_type = gnome_vfs_file_info_get_mime_type (info);
2368 mime_part = tny_platform_factory_new_mime_part
2369 (modest_runtime_get_platform_factory ());
2371 /* try to get the attachment's size; this may fail for weird
2372 * file systems, like obex, upnp... */
2373 if (allowed_size != 0 &&
2374 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2376 if (size > allowed_size) {
2377 modest_platform_information_banner (NULL, NULL,
2378 dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2382 g_warning ("%s: could not get attachment size", __FUNCTION__);
2384 stream = create_stream_for_uri (uri);
2386 if (stream == NULL) {
2388 modest_platform_information_banner (NULL, NULL, dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2390 g_object_unref (mime_part);
2391 gnome_vfs_file_info_unref (info);
2395 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2396 g_object_unref (stream);
2398 content_id = g_strdup_printf ("%d", priv->next_cid);
2399 tny_mime_part_set_content_id (mime_part, content_id);
2400 g_free (content_id);
2403 basename = g_path_get_basename (filename);
2404 tny_mime_part_set_filename (mime_part, basename);
2407 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2408 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2410 info->size == 0, info->size);
2411 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2412 gtk_widget_show_all (priv->attachments_caption);
2413 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2415 g_object_unref (mime_part);
2416 gnome_vfs_file_info_unref (info);
2423 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2426 ModestMsgEditWindowPrivate *priv;
2429 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2430 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2432 if (att_list == NULL) {
2433 att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2435 g_object_ref (att_list);
2438 if (tny_list_get_length (att_list) == 0) {
2439 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2441 gboolean dialog_response;
2442 gchar *message = NULL;
2443 gchar *filename = NULL;
2445 if (tny_list_get_length (att_list) == 1) {
2447 iter = tny_list_create_iterator (att_list);
2448 part = (TnyMimePart *) tny_iterator_get_current (iter);
2449 g_object_unref (iter);
2450 if (TNY_IS_MSG (part)) {
2451 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2453 filename = tny_header_dup_subject (header);
2454 g_object_unref (header);
2456 if (filename == NULL) {
2457 filename = g_strdup (_("mail_va_no_subject"));
2460 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2462 g_object_unref (part);
2464 filename = g_strdup ("");
2466 message = g_strdup_printf (ngettext("emev_nc_delete_attachment",
2467 "emev_nc_delete_attachments",
2468 tny_list_get_length (att_list)), filename);
2471 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
2475 if (dialog_response != GTK_RESPONSE_OK) {
2476 g_object_unref (att_list);
2480 for (iter = tny_list_create_iterator (att_list);
2481 !tny_iterator_is_done (iter);
2482 tny_iterator_next (iter)) {
2483 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2484 const gchar *att_id;
2485 tny_list_remove (priv->attachments, (GObject *) mime_part);
2487 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2489 if (tny_list_get_length (priv->attachments) == 0)
2490 gtk_widget_hide (priv->attachments_caption);
2491 att_id = tny_mime_part_get_content_id (mime_part);
2493 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2495 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2496 g_object_unref (mime_part);
2498 g_object_unref (iter);
2501 g_object_unref (att_list);
2503 /* if the last attachment has been removed, focus the Subject: field */
2504 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2505 gtk_widget_grab_focus (priv->subject_field);
2509 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2512 ModestMsgEditWindowPrivate *priv;
2513 GdkColor *new_color;
2514 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2516 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2517 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2520 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2522 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2524 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2526 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2531 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
2534 ModestMsgEditWindowPrivate *priv;
2535 gint new_size_index;
2536 ModestMsgEditWindow *window;
2539 window = MODEST_MSG_EDIT_WINDOW (userdata);
2540 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2541 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2543 if (gtk_check_menu_item_get_active (menu_item)) {
2545 WPTextBufferFormat format;
2547 memset (&format, 0, sizeof (format));
2548 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2550 label = gtk_bin_get_child (GTK_BIN (menu_item));
2552 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
2553 format.cs.font_size = TRUE;
2554 format.cs.text_position = TRUE;
2555 format.cs.font = TRUE;
2556 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
2557 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2559 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2560 GINT_TO_POINTER (wp_get_font_size_index (new_size_index, 12))))
2561 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2563 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2564 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
2565 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2571 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
2574 ModestMsgEditWindowPrivate *priv;
2575 gint new_font_index;
2576 ModestMsgEditWindow *window;
2579 window = MODEST_MSG_EDIT_WINDOW (userdata);
2580 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2581 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2583 if (gtk_check_menu_item_get_active (menu_item)) {
2586 label = gtk_bin_get_child (GTK_BIN (menu_item));
2588 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
2590 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2591 GINT_TO_POINTER(new_font_index)))
2592 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2594 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2595 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2596 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2602 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2605 ModestMsgEditWindowPrivate *priv = NULL;
2606 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2608 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2609 if (!priv->update_caption_visibility)
2612 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2614 gtk_widget_show (priv->cc_caption);
2616 gtk_widget_hide (priv->cc_caption);
2618 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2622 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2625 ModestMsgEditWindowPrivate *priv = NULL;
2626 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2628 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2629 if (!priv->update_caption_visibility)
2632 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2634 gtk_widget_show (priv->bcc_caption);
2636 gtk_widget_hide (priv->bcc_caption);
2638 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2642 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2643 ModestRecptEditor *editor)
2645 ModestMsgEditWindowPrivate *priv;
2647 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2648 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2650 /* we check for low-mem; in that case, show a warning, and don't allow
2651 * for the addressbook
2653 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2656 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2658 if (editor == NULL) {
2659 GtkWidget *view_focus;
2660 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2662 /* This code should be kept in sync with ModestRecptEditor. The
2663 textview inside the recpt editor is the one that really gets the
2664 focus. As it's inside a scrolled window, and this one inside the
2665 hbox recpt editor inherits from, we'll need to go up in the
2666 hierarchy to know if the text view is part of the recpt editor
2667 or if it's a different text entry */
2669 if (gtk_widget_get_parent (view_focus)) {
2670 GtkWidget *first_parent;
2672 first_parent = gtk_widget_get_parent (view_focus);
2673 if (gtk_widget_get_parent (first_parent) &&
2674 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2675 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2680 editor = MODEST_RECPT_EDITOR (priv->to_field);
2684 modest_address_book_select_addresses (editor);
2689 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2691 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2693 modest_msg_edit_window_open_addressbook (window, NULL);
2697 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2698 gboolean show_toolbar)
2700 ModestWindowPrivate *parent_priv;
2702 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2703 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2705 /* We can not just use the code of
2706 modest_msg_edit_window_setup_toolbar because it has a
2707 mixture of both initialization and creation code. */
2709 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2711 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2715 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2716 TnyHeaderFlags priority_flags)
2718 ModestMsgEditWindowPrivate *priv;
2719 ModestWindowPrivate *parent_priv;
2721 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2723 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2724 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2726 if (priv->priority_flags != priority_flags) {
2727 GtkAction *priority_action = NULL;
2729 priv->priority_flags = priority_flags;
2731 switch (priority_flags) {
2732 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2733 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2734 MODEST_HEADER_ICON_HIGH,
2735 HILDON_ICON_SIZE_XSMALL);
2736 gtk_widget_show (priv->priority_icon);
2737 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2738 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2740 case TNY_HEADER_FLAG_LOW_PRIORITY:
2741 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2742 MODEST_HEADER_ICON_LOW,
2743 HILDON_ICON_SIZE_XSMALL);
2744 gtk_widget_show (priv->priority_icon);
2745 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2746 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2749 gtk_widget_hide (priv->priority_icon);
2750 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2751 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2754 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2755 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2760 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2763 ModestMsgEditWindowPrivate *priv;
2764 ModestWindowPrivate *parent_priv;
2765 gint current_format;
2767 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2769 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2770 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2772 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2773 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2775 if (current_format != file_format) {
2776 switch (file_format) {
2777 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2778 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2779 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
2781 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2785 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2786 response = gtk_dialog_run (GTK_DIALOG (dialog));
2787 gtk_widget_destroy (dialog);
2788 if (response == GTK_RESPONSE_OK) {
2789 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2791 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
2792 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
2797 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2798 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2799 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2804 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2807 ModestMsgEditWindowPrivate *priv;
2808 WPTextBufferFormat oldfmt, fmt;
2809 gint old_position = 0;
2813 GdkColor *color = NULL;
2814 gboolean bold, bold_set, italic, italic_set;
2815 gboolean underline, underline_set;
2816 gboolean strikethrough, strikethrough_set;
2817 gboolean position_set;
2818 gboolean font_size_set, font_set, color_set;
2821 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2822 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2824 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2825 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
2826 GTK_WINDOW(dialog), GTK_WINDOW (window));
2828 /* First we get the currently selected font information */
2829 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2831 switch (oldfmt.text_position) {
2832 case TEXT_POSITION_NORMAL:
2835 case TEXT_POSITION_SUPERSCRIPT:
2843 g_object_set (G_OBJECT (dialog),
2844 "bold", oldfmt.bold != FALSE,
2845 "bold-set", !oldfmt.cs.bold,
2846 "underline", oldfmt.underline != FALSE,
2847 "underline-set", !oldfmt.cs.underline,
2848 "italic", oldfmt.italic != FALSE,
2849 "italic-set", !oldfmt.cs.italic,
2850 "strikethrough", oldfmt.strikethrough != FALSE,
2851 "strikethrough-set", !oldfmt.cs.strikethrough,
2852 "color", &oldfmt.color,
2853 "color-set", !oldfmt.cs.color,
2854 "size", wp_font_size[oldfmt.font_size],
2855 "size-set", !oldfmt.cs.font_size,
2856 "position", old_position,
2857 "position-set", !oldfmt.cs.text_position,
2858 "family", wp_get_font_name (oldfmt.font),
2859 "family-set", !oldfmt.cs.font,
2862 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2863 GTK_WINDOW (dialog), GTK_WINDOW (window));
2864 gtk_widget_show_all (dialog);
2865 priv->font_dialog = dialog;
2866 response = gtk_dialog_run (GTK_DIALOG (dialog));
2867 priv->font_dialog = NULL;
2868 if (response == GTK_RESPONSE_OK) {
2870 g_object_get( dialog,
2872 "bold-set", &bold_set,
2873 "underline", &underline,
2874 "underline-set", &underline_set,
2876 "italic-set", &italic_set,
2877 "strikethrough", &strikethrough,
2878 "strikethrough-set", &strikethrough_set,
2880 "color-set", &color_set,
2882 "size-set", &font_size_set,
2883 "family", &font_name,
2884 "family-set", &font_set,
2885 "position", &position,
2886 "position-set", &position_set,
2891 if (response == GTK_RESPONSE_OK) {
2892 memset(&fmt, 0, sizeof(fmt));
2898 fmt.italic = italic;
2899 fmt.cs.italic = TRUE;
2901 if (underline_set) {
2902 fmt.underline = underline;
2903 fmt.cs.underline = TRUE;
2905 if (strikethrough_set) {
2906 fmt.strikethrough = strikethrough;
2907 fmt.cs.strikethrough = TRUE;
2912 ? TEXT_POSITION_NORMAL
2913 : ( ( position == 1 )
2914 ? TEXT_POSITION_SUPERSCRIPT
2915 : TEXT_POSITION_SUBSCRIPT );
2916 fmt.cs.text_position = TRUE;
2917 fmt.font_size = oldfmt.font_size;
2921 fmt.cs.color = TRUE;
2924 fmt.font = wp_get_font_index(font_name,
2929 if (font_size_set) {
2930 fmt.cs.font_size = TRUE;
2931 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
2933 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2934 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2936 gtk_widget_destroy (dialog);
2938 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2942 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2944 ModestMsgEditWindowPrivate *priv;
2946 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2947 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2949 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2951 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2952 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2956 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
2958 ModestMsgEditWindowPrivate *priv;
2960 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2961 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2963 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
2965 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2966 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2971 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
2973 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2975 priv->can_undo = can_undo;
2979 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
2981 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2983 priv->can_redo = can_redo;
2987 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
2989 ModestMsgEditWindowPrivate *priv;
2990 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2991 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2993 return priv->can_undo;
2997 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
2999 ModestMsgEditWindowPrivate *priv;
3000 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3001 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3003 return priv->can_redo;
3008 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3011 GtkTextIter match_start, match_end;
3013 if (image_id == NULL)
3016 gtk_text_buffer_get_start_iter (buffer, &iter);
3018 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3019 GSList *tags = gtk_text_iter_get_tags (&match_start);
3021 for (node = tags; node != NULL; node = g_slist_next (node)) {
3022 GtkTextTag *tag = (GtkTextTag *) node->data;
3023 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3024 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3025 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3027 offset = gtk_text_iter_get_offset (&match_start);
3028 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3029 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3033 gtk_text_iter_forward_char (&iter);
3038 message_is_empty (ModestMsgEditWindow *window)
3040 ModestMsgEditWindowPrivate *priv = NULL;
3042 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3043 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3045 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3046 * so we can ignore markup.
3048 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3051 count = gtk_text_buffer_get_char_count (buf);
3057 msg_body_focus (GtkWidget *focus,
3058 GdkEventFocus *event,
3062 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3063 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3064 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3069 recpt_field_changed (GtkTextBuffer *buffer,
3070 ModestMsgEditWindow *editor)
3072 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3073 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3077 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3079 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3080 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3084 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3087 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3088 GtkTextBuffer *buffer;
3090 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3091 gtk_text_buffer_set_modified (buffer, modified);
3092 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3093 gtk_text_buffer_set_modified (buffer, modified);
3094 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3095 gtk_text_buffer_set_modified (buffer, modified);
3096 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3100 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3102 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3103 const char *account_name;
3104 GtkTextBuffer *buffer;
3106 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3107 if (gtk_text_buffer_get_modified (buffer))
3109 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3110 if (gtk_text_buffer_get_modified (buffer))
3112 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3113 if (gtk_text_buffer_get_modified (buffer))
3115 if (gtk_text_buffer_get_modified (priv->text_buffer))
3117 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3118 if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3129 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3131 ModestMsgEditWindowPrivate *priv = NULL;
3133 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3134 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3136 /* check if there's no recipient added */
3137 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3138 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3139 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3140 /* no recipient contents, then select contacts */
3141 modest_msg_edit_window_open_addressbook (window, NULL);
3145 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3146 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3149 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3150 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3153 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3154 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3158 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3159 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3160 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3167 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3168 ModestMsgEditWindow *window)
3170 modest_msg_edit_window_offer_attach_file (window);
3174 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3176 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3178 return priv->clipboard_text;
3182 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3184 ModestMsgEditWindow *window)
3186 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3187 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3189 if (!GTK_WIDGET_VISIBLE (window))
3192 g_object_ref (window);
3193 text = gtk_clipboard_wait_for_text (selection_clipboard);
3195 if (priv->clipboard_text != NULL) {
3196 g_free (priv->clipboard_text);
3198 priv->clipboard_text = text;
3200 if (GTK_WIDGET_VISIBLE (window)) {
3201 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3203 g_object_unref (window);
3206 static gboolean clipboard_owner_change_idle (gpointer userdata)
3208 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3209 ModestMsgEditWindowPrivate *priv;
3211 gdk_threads_enter ();
3212 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3213 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3215 priv->clipboard_owner_idle = 0;
3216 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3217 gdk_threads_leave ();
3223 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3225 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3226 if (priv->clipboard_owner_idle == 0) {
3227 priv->clipboard_owner_idle = g_idle_add (clipboard_owner_change_idle, window);
3232 subject_field_move_cursor (GtkEntry *entry,
3233 GtkMovementStep step,
3238 if (!GTK_WIDGET_VISIBLE (window))
3241 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3245 update_window_title (ModestMsgEditWindow *window)
3247 ModestMsgEditWindowPrivate *priv = NULL;
3248 const gchar *subject;
3250 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3251 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3252 if (subject == NULL || subject[0] == '\0')
3253 subject = _("mail_va_new_email");
3255 gtk_window_set_title (GTK_WINDOW (window), subject);
3260 subject_field_changed (GtkEditable *editable,
3261 ModestMsgEditWindow *window)
3263 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3264 update_window_title (window);
3265 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3266 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3267 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3271 subject_field_insert_text (GtkEditable *editable,
3273 gint new_text_length,
3275 ModestMsgEditWindow *window)
3277 GString *result = g_string_new ("");
3279 gint result_len = 0;
3280 const gchar *entry_text = NULL;
3283 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3284 old_length = g_utf8_strlen (entry_text, -1);
3286 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3287 gunichar c = g_utf8_get_char_validated (current, 8);
3288 /* Invalid unichar, stop */
3294 result = g_string_append_unichar (result, c);
3298 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3299 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3302 /* Prevent endless recursion */
3303 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3304 g_signal_emit_by_name (editable, "insert-text",
3305 (gpointer) result->str, (gpointer) result->len,
3306 (gpointer) position, (gpointer) window);
3307 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3311 if (result_len + old_length > 1000) {
3312 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3313 dgettext("hildon-common-strings",
3314 "ckdg_ib_maximum_characters_reached"));
3316 g_string_free (result, TRUE);
3320 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3323 ModestMsgEditWindowPrivate *priv = NULL;
3325 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3326 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3328 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3331 gtk_widget_show_all (priv->find_toolbar);
3332 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3334 gtk_widget_hide_all (priv->find_toolbar);
3335 gtk_widget_grab_focus (priv->msg_body);
3340 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3342 GtkTextIter *match_start,
3343 GtkTextIter *match_end)
3345 GtkTextIter end_iter;
3346 gchar *str_casefold;
3349 gchar *range_casefold;
3352 gboolean result = FALSE;
3359 gtk_text_iter_forward_to_end (&end_iter);
3361 str_casefold = g_utf8_casefold (str, -1);
3362 str_chars_n = strlen (str);
3364 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3365 range_casefold = g_utf8_casefold (range_text, -1);
3366 range_chars_n = strlen (range_casefold);
3368 if (range_chars_n < str_chars_n) {
3369 g_free (str_casefold);
3370 g_free (range_text);
3371 g_free (range_casefold);
3375 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3376 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3377 if (!g_utf8_collate (range_subtext, str_casefold)) {
3378 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3380 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3381 match_start, match_end, NULL);
3382 g_free (found_text);
3384 g_free (range_subtext);
3388 g_free (str_casefold);
3389 g_free (range_text);
3390 g_free (range_casefold);
3397 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3398 ModestMsgEditWindow *window)
3400 gchar *current_search = NULL;
3401 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3403 GtkTextIter selection_start, selection_end;
3404 GtkTextIter match_start, match_end;
3405 gboolean continue_search = FALSE;
3407 if (message_is_empty (window)) {
3408 g_free (priv->last_search);
3409 priv->last_search = NULL;
3410 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3414 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3415 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3416 g_free (current_search);
3417 g_free (priv->last_search);
3418 priv->last_search = NULL;
3419 /* Information banner about empty search */
3420 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-common-strings", "ecdg_ib_find_rep_enter_text"));
3424 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3425 continue_search = TRUE;
3427 g_free (priv->last_search);
3428 priv->last_search = g_strdup (current_search);
3431 if (continue_search) {
3432 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3433 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3434 &match_start, &match_end);
3436 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_search_complete"));
3438 GtkTextIter buffer_start;
3439 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3440 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3441 &match_start, &match_end);
3443 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_no_matches"));
3446 /* Mark as selected the string found in search */
3448 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3449 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3450 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3452 g_free (priv->last_search);
3453 priv->last_search = NULL;
3455 g_free (current_search);
3459 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3461 ModestMsgEditWindowPrivate *priv;
3463 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3468 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3471 ModestMsgEditWindowPrivate *priv;
3473 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3478 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3479 ModestMsgEditWindow *window)
3481 modest_msg_edit_window_toggle_find_toolbar (window, FALSE);
3485 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3488 ModestMsgEditWindowPrivate *priv;
3489 TnyHeader *header = NULL;
3491 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3492 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3494 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3495 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3497 if (priv->draft_msg != NULL) {
3498 g_object_unref (priv->draft_msg);
3501 if (draft != NULL) {
3502 g_object_ref (draft);
3503 header = tny_msg_get_header (draft);
3504 if (priv->msg_uid) {
3505 g_free (priv->msg_uid);
3506 priv->msg_uid = NULL;
3508 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3509 if (GTK_WIDGET_REALIZED (window)) {
3510 if (!modest_window_mgr_register_window (mgr, MODEST_WINDOW (window), NULL)) {
3511 gtk_widget_destroy (GTK_WIDGET (window));
3517 priv->draft_msg = draft;
3521 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3522 GtkTextIter *start, GtkTextIter *end,
3525 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3526 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3529 if (tag == NULL) return;
3530 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3531 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3532 replace_with_images (window, priv->images);
3537 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3540 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3542 g_return_if_fail (TNY_IS_MIME_PART (part));
3543 tny_list_prepend (priv->attachments, (GObject *) part);
3544 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3545 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3546 gtk_widget_show_all (priv->attachments_caption);
3547 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3551 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3553 ModestMsgEditWindowPrivate *priv;
3555 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3556 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3558 return priv->msg_uid;
3562 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3563 ModestMsgEditWindowWidgetType widget_type)
3565 ModestMsgEditWindowPrivate *priv;
3567 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3568 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3570 switch (widget_type) {
3571 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3572 return priv->msg_body;
3574 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3575 return priv->to_field;
3577 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3578 return priv->cc_field;
3580 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3581 return priv->bcc_field;
3583 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3584 return priv->subject_field;
3586 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3587 return priv->attachments_view;
3595 remove_tags (WPTextBuffer *buffer)
3597 GtkTextIter start, end;
3599 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3600 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3602 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3606 on_account_removed (TnyAccountStore *account_store,
3607 TnyAccount *account,
3610 /* Do nothing if it's a store account, because we use the
3611 transport to send the messages */
3612 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3613 const gchar *parent_acc = NULL;
3614 const gchar *our_acc = NULL;
3616 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3617 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3618 /* Close this window if I'm showing a message of the removed account */
3619 if (strcmp (parent_acc, our_acc) == 0)
3620 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3624 typedef struct _MessageSettingsHelper {
3625 ModestMsgEditWindow *window;
3626 GSList *priority_group;
3627 GSList *format_group;
3628 } MessageSettingsHelper;
3631 on_priority_toggle (GtkToggleButton *button,
3632 MessageSettingsHelper *helper)
3635 ModestMsgEditWindowPrivate *priv;
3637 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3638 if (gtk_toggle_button_get_active (button)) {
3640 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3641 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3642 if ((node_button != button) &&
3643 gtk_toggle_button_get_active (node_button)) {
3644 gtk_toggle_button_set_active (node_button, FALSE);
3647 if (priv->priority_flags != (TnyHeaderFlags) g_object_get_data (G_OBJECT (button), "priority"))
3648 modest_msg_edit_window_set_priority_flags (helper->window,
3650 g_object_get_data (G_OBJECT (button),
3654 gboolean found = FALSE;
3655 /* If no one is active, activate it again */
3656 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3657 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3658 if (gtk_toggle_button_get_active (node_button)) {
3664 gtk_toggle_button_set_active (button, TRUE);
3670 on_format_toggle (GtkToggleButton *button,
3671 MessageSettingsHelper *helper)
3674 ModestMsgEditWindowPrivate *priv;
3675 ModestMsgEditFormat old_format;
3677 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3678 old_format = modest_msg_edit_window_get_format (helper->window);
3679 if (gtk_toggle_button_get_active (button)) {
3681 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
3682 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3683 if ((node_button != button) &&
3684 gtk_toggle_button_get_active (node_button)) {
3685 gtk_toggle_button_set_active (node_button, FALSE);
3688 if (old_format != (ModestMsgEditFormat) g_object_get_data (G_OBJECT (button), "format")) {
3689 modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (helper->window),
3690 GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button), "file-format")));
3694 gboolean found = FALSE;
3695 /* If no one is active, activate it again */
3696 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
3697 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3698 if (gtk_toggle_button_get_active (node_button)) {
3704 gtk_toggle_button_set_active (button, TRUE);
3711 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
3715 GtkWidget *priority_hbox;
3716 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
3717 GtkWidget *captioned;
3718 GtkSizeGroup *title_sizegroup, *value_sizegroup;
3719 GtkWidget *format_hbox;
3720 GtkWidget *html_toggle, *text_toggle;
3721 ModestMsgEditWindowPrivate *priv;
3722 MessageSettingsHelper helper = {0,};
3724 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3725 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3726 helper.window = window;
3727 helper.priority_group = NULL;
3729 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3730 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3732 dialog = gtk_dialog_new ();
3733 vbox = gtk_vbox_new (FALSE, 0);
3734 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), vbox);
3735 gtk_widget_show (vbox);
3737 /* Priority toggles */
3738 priority_hbox = gtk_hbox_new (TRUE, 0);
3739 high_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3740 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
3741 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
3742 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
3743 medium_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3744 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
3745 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
3746 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
3747 low_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3748 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
3749 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
3750 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
3751 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, TRUE, TRUE, 0);
3752 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, TRUE, TRUE, 0);
3753 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, TRUE, TRUE, 0);
3754 gtk_widget_show_all (priority_hbox);
3755 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
3756 _("mcen_me_editor_message_priority"), FALSE, priority_hbox);
3757 gtk_widget_show (captioned);
3758 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
3760 /* format toggles */
3761 format_hbox = gtk_hbox_new (TRUE, 0);
3762 html_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3763 gtk_button_set_label (GTK_BUTTON (html_toggle), _("mcen_me_editor_formatted_text"));
3764 helper.format_group = g_slist_prepend (helper.format_group, html_toggle);
3765 g_object_set_data (G_OBJECT (html_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_HTML));
3766 g_object_set_data (G_OBJECT (html_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_FORMATTED_TEXT));
3767 text_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3768 gtk_button_set_label (GTK_BUTTON (text_toggle), _("mcen_me_editor_plain_text"));
3769 helper.format_group = g_slist_prepend (helper.format_group, text_toggle);
3770 g_object_set_data (G_OBJECT (text_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_TEXT));
3771 g_object_set_data (G_OBJECT (text_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_PLAIN_TEXT));
3772 gtk_box_pack_start (GTK_BOX (format_hbox), html_toggle, TRUE, TRUE, 0);
3773 gtk_box_pack_start (GTK_BOX (format_hbox), text_toggle, TRUE, TRUE, 0);
3774 gtk_widget_show_all (format_hbox);
3775 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
3776 _("mcen_me_editor_format"), FALSE, format_hbox);
3777 gtk_widget_show (captioned);
3778 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
3781 g_object_unref (title_sizegroup);
3782 g_object_unref (value_sizegroup);
3783 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_me_message_settings"));
3785 /* Set current values */
3786 switch (priv->priority_flags) {
3787 case TNY_HEADER_FLAG_HIGH_PRIORITY:
3788 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (high_toggle), TRUE);
3790 case TNY_HEADER_FLAG_LOW_PRIORITY:
3791 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (low_toggle), TRUE);
3794 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (medium_toggle), TRUE);
3798 switch (modest_msg_edit_window_get_format (window)) {
3799 case MODEST_MSG_EDIT_FORMAT_TEXT:
3800 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_toggle), TRUE);
3802 case MODEST_MSG_EDIT_FORMAT_HTML:
3804 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (html_toggle), TRUE);
3808 /* Signal connects */
3809 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3810 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3811 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3812 g_signal_connect (G_OBJECT (html_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
3813 g_signal_connect (G_OBJECT (text_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
3815 gtk_dialog_run (GTK_DIALOG (dialog));
3817 /* Read new values */
3819 gtk_widget_destroy (dialog);
3820 g_slist_free (helper.priority_group);
3824 static void on_message_settings (GtkAction *action,
3825 ModestMsgEditWindow *window)
3827 modest_msg_edit_window_show_msg_settings_dialog (window);
3831 on_cc_button_toggled (HildonCheckButton *button,
3832 ModestMsgEditWindow *window)
3834 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
3836 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
3837 hildon_check_button_get_active (button));
3841 on_bcc_button_toggled (HildonCheckButton *button,
3842 ModestMsgEditWindow *window)
3844 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
3846 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
3847 hildon_check_button_get_active (button));
3851 setup_menu (ModestMsgEditWindow *self)
3853 ModestMsgEditWindowPrivate *priv = NULL;
3855 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
3857 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3859 /* Settings menu buttons */
3860 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_checknames"), NULL,
3861 APP_MENU_CALLBACK (modest_ui_actions_on_check_names),
3863 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_undo"), "<Ctrl>z",
3864 APP_MENU_CALLBACK (modest_ui_actions_on_undo),
3865 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_undo));
3867 priv->cc_button = hildon_check_button_new (0);
3868 gtk_button_set_label (GTK_BUTTON (priv->cc_button), _("mcen_me_editor_showcc"));
3869 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button),
3871 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->cc_button),
3873 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
3874 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
3875 priv->bcc_button = hildon_check_button_new (0);
3876 gtk_button_set_label (GTK_BUTTON (priv->bcc_button), _("mcen_me_editor_showbcc"));
3877 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button),
3879 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->bcc_button),
3881 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
3882 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
3884 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_attach_inlineimage"), NULL,
3885 APP_MENU_CALLBACK (modest_ui_actions_on_insert_image),
3886 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_set_style));
3887 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_remove_attachments"), NULL,
3888 APP_MENU_CALLBACK (modest_ui_actions_on_remove_attachments),
3889 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
3890 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_message_settings"), NULL,
3891 APP_MENU_CALLBACK (on_message_settings),
3893 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_viewer_find"), "<Ctrl>f",
3894 APP_MENU_CALLBACK (modest_ui_actions_on_toggle_find_in_page),