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_("TODO: settings..."), NULL, NULL, G_CALLBACK (on_message_settings)},
218 /* static gboolean */
219 /* on_key_pressed (GtkWidget *self, */
220 /* GdkEventKey *event, */
221 /* gpointer user_data); */
223 /* list my signals */
230 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
231 struct _ModestMsgEditWindowPrivate {
234 GtkWidget *header_box;
236 ModestPairList *from_field_protos;
237 GtkWidget *from_field;
238 gchar *original_account_name;
242 GtkWidget *bcc_field;
243 GtkWidget *subject_field;
244 GtkWidget *attachments_view;
245 GtkWidget *priority_icon;
246 GtkWidget *add_attachment_button;
248 GtkWidget *cc_caption;
249 GtkWidget *bcc_caption;
250 gboolean update_caption_visibility;
251 GtkWidget *attachments_caption;
253 GtkTextBuffer *text_buffer;
255 GtkWidget *font_size_toolitem;
256 GtkWidget *font_face_toolitem;
257 GtkWidget *font_color_button;
258 GtkWidget *font_color_toolitem;
259 GSList *font_items_group;
260 GtkWidget *font_tool_button_label;
261 GSList *size_items_group;
262 GtkWidget *size_tool_button_label;
264 GtkWidget *find_toolbar;
267 GtkWidget *font_dialog;
270 guint scroll_drag_timeout_id;
274 TnyList *attachments;
279 TnyHeaderFlags priority_flags;
281 gboolean can_undo, can_redo;
282 gulong clipboard_change_handler_id;
283 gulong default_clipboard_change_handler_id;
284 gulong account_removed_handler_id;
285 guint clipboard_owner_idle;
286 gchar *clipboard_text;
295 GtkWidget *cc_button;
296 GtkWidget *bcc_button;
297 GtkWidget *find_toolbar_button;
300 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
301 MODEST_TYPE_MSG_EDIT_WINDOW, \
302 ModestMsgEditWindowPrivate))
304 static GtkWindowClass *parent_class = NULL;
306 /* uncomment the following if you have defined any signals */
307 /* static guint signals[LAST_SIGNAL] = {0}; */
310 modest_msg_edit_window_get_type (void)
312 static GType my_type = 0;
314 static const GTypeInfo my_info = {
315 sizeof(ModestMsgEditWindowClass),
316 NULL, /* base init */
317 NULL, /* base finalize */
318 (GClassInitFunc) modest_msg_edit_window_class_init,
319 NULL, /* class finalize */
320 NULL, /* class data */
321 sizeof(ModestMsgEditWindow),
323 (GInstanceInitFunc) modest_msg_edit_window_init,
326 my_type = g_type_register_static (MODEST_TYPE_HILDON2_WINDOW,
327 "ModestMsgEditWindow",
335 save_state (ModestWindow *self)
337 modest_widget_memory_save (modest_runtime_get_conf(),
338 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
343 restore_settings (ModestMsgEditWindow *self)
345 ModestConf *conf = NULL;
347 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
349 conf = modest_runtime_get_conf ();
351 /* Dim at start clipboard actions */
352 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
353 gtk_action_set_sensitive (action, FALSE);
354 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
355 gtk_action_set_sensitive (action, FALSE);
356 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
357 gtk_action_set_sensitive (action, FALSE);
359 modest_widget_memory_restore (conf, G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
364 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
366 GObjectClass *gobject_class;
367 ModestWindowClass *modest_window_class;
368 gobject_class = (GObjectClass*) klass;
369 modest_window_class = (ModestWindowClass*) klass;
371 parent_class = g_type_class_peek_parent (klass);
372 gobject_class->finalize = modest_msg_edit_window_finalize;
374 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
375 modest_window_class->save_state_func = save_state;
376 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
378 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
382 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
384 ModestMsgEditWindowPrivate *priv;
385 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
387 priv->msg_body = NULL;
389 priv->from_field = NULL;
390 priv->to_field = NULL;
391 priv->cc_field = NULL;
392 priv->bcc_field = NULL;
393 priv->subject_field = NULL;
394 priv->attachments = TNY_LIST (tny_simple_list_new ());
395 priv->images = TNY_LIST (tny_simple_list_new ());
396 priv->images_size = 0;
397 priv->images_count = 0;
400 priv->cc_caption = NULL;
401 priv->bcc_caption = NULL;
402 priv->update_caption_visibility = FALSE;
404 priv->priority_flags = 0;
406 priv->find_toolbar = NULL;
407 priv->last_search = NULL;
409 priv->draft_msg = NULL;
410 priv->outbox_msg = NULL;
411 priv->msg_uid = NULL;
413 priv->can_undo = FALSE;
414 priv->can_redo = FALSE;
415 priv->clipboard_change_handler_id = 0;
416 priv->default_clipboard_change_handler_id = 0;
417 priv->account_removed_handler_id = 0;
418 priv->clipboard_owner_idle = 0;
419 priv->clipboard_text = NULL;
422 priv->scroll_drag_timeout_id = 0;
423 priv->last_upper = 0.0;
425 priv->font_dialog = NULL;
426 priv->app_menu = NULL;
428 if (!is_wp_text_buffer_started) {
429 is_wp_text_buffer_started = TRUE;
430 wp_text_buffer_library_init ();
435 hildon_program_add_window (hildon_program_get_instance(),
441 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
443 static ModestPairList*
444 get_transports (void)
446 GSList *transports = NULL;
448 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
449 GSList *accounts = modest_account_mgr_account_names (account_mgr,
450 TRUE /* only enabled accounts. */);
452 GSList *cursor = accounts;
454 gchar *account_name = cursor->data;
455 gchar *from_string = NULL;
457 from_string = modest_account_mgr_get_from_string (account_mgr,
461 if (from_string && account_name) {
462 gchar *name = account_name;
463 ModestPair *pair = modest_pair_new ((gpointer) name,
464 (gpointer) from_string , TRUE);
465 transports = g_slist_prepend (transports, pair);
468 cursor = cursor->next;
470 g_slist_free (accounts); /* only free the accounts, not the elements,
471 * because they are used in the pairlist */
475 static void window_focus (GtkWindow *window,
479 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
483 scroll_drag_timeout (gpointer userdata)
485 ModestMsgEditWindow *win = (ModestMsgEditWindow *) userdata;
486 ModestMsgEditWindowPrivate *priv;
488 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(win);
490 correct_scroll_without_drag_check (win, TRUE);
492 priv->scroll_drag_timeout_id = 0;
498 correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused)
500 ModestMsgEditWindowPrivate *priv;
503 GdkRectangle rectangle;
507 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
509 if (only_if_focused && !gtk_widget_is_focus (priv->msg_body))
512 insert = gtk_text_buffer_get_insert (priv->text_buffer);
513 gtk_text_buffer_get_iter_at_mark (priv->text_buffer, &iter, insert);
515 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &iter, &rectangle);
516 offset = priv->msg_body->allocation.y;
518 new_value = (offset + rectangle.y);
520 hildon_pannable_area_jump_to (HILDON_PANNABLE_AREA (priv->pannable), -1, new_value);
524 correct_scroll (ModestMsgEditWindow *w)
526 ModestMsgEditWindowPrivate *priv;
528 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
529 if (gtk_grab_get_current () == priv->msg_body) {
530 if (priv->scroll_drag_timeout_id == 0) {
531 priv->scroll_drag_timeout_id = g_timeout_add (500, (GSourceFunc) scroll_drag_timeout,
537 correct_scroll_without_drag_check (w, TRUE);
541 text_buffer_end_user_action (GtkTextBuffer *buffer,
542 ModestMsgEditWindow *userdata)
545 correct_scroll (userdata);
549 text_buffer_mark_set (GtkTextBuffer *buffer,
552 ModestMsgEditWindow *userdata)
554 gtk_text_buffer_begin_user_action (buffer);
555 gtk_text_buffer_end_user_action (buffer);
559 cut_clipboard_check (GtkTextView *text_view,
562 GtkTextBuffer *buffer;
564 buffer = gtk_text_view_get_buffer (text_view);
565 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
566 g_signal_stop_emission_by_name ((gpointer )text_view, "cut-clipboard");
571 copy_clipboard_check (GtkTextView *text_view,
574 GtkTextBuffer *buffer;
576 buffer = gtk_text_view_get_buffer (text_view);
577 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
578 g_signal_stop_emission_by_name ((gpointer )text_view, "copy-clipboard");
583 attachment_deleted (ModestAttachmentsView *attachments_view,
586 modest_msg_edit_window_remove_attachments (MODEST_MSG_EDIT_WINDOW (user_data),
591 connect_signals (ModestMsgEditWindow *obj)
593 ModestMsgEditWindowPrivate *priv;
595 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
597 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
598 G_CALLBACK (text_buffer_refresh_attributes), obj);
599 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
600 G_CALLBACK (text_buffer_can_undo), obj);
601 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
602 G_CALLBACK (text_buffer_can_redo), obj);
603 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
604 G_CALLBACK (body_changed), obj);
605 g_signal_connect (G_OBJECT (priv->text_buffer), "modified-changed",
606 G_CALLBACK (body_changed), obj);
607 g_signal_connect (G_OBJECT (priv->text_buffer), "end-user-action",
608 G_CALLBACK (text_buffer_end_user_action), obj);
609 g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
610 G_CALLBACK (text_buffer_mark_set), obj);
611 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
612 G_CALLBACK (text_buffer_apply_tag), obj);
613 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
614 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
615 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
616 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
617 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
618 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
620 g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
621 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
623 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
624 G_CALLBACK (msg_body_focus), obj);
625 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
626 G_CALLBACK (msg_body_focus), obj);
627 g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
628 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
629 "changed", G_CALLBACK (recpt_field_changed), obj);
630 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
631 "changed", G_CALLBACK (recpt_field_changed), obj);
632 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
633 "changed", G_CALLBACK (recpt_field_changed), obj);
634 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
635 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
636 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
638 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
639 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
641 priv->clipboard_change_handler_id =
642 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
643 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
644 priv->default_clipboard_change_handler_id =
645 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
646 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
648 g_signal_connect (G_OBJECT (priv->msg_body), "cut-clipboard", G_CALLBACK (cut_clipboard_check), NULL);
649 g_signal_connect (G_OBJECT (priv->msg_body), "copy-clipboard", G_CALLBACK (copy_clipboard_check), NULL);
650 g_signal_connect (G_OBJECT (priv->attachments_view), "delete", G_CALLBACK (attachment_deleted), obj);
654 init_wp_text_view_style ()
656 static gboolean initialized = FALSE;
659 gtk_rc_parse_string ("class \"WPTextView\" style \"fremantle-textview\"");
665 init_window (ModestMsgEditWindow *obj)
667 GtkWidget *to_caption, *subject_caption;
668 GtkWidget *main_vbox;
669 ModestMsgEditWindowPrivate *priv;
670 GtkActionGroup *action_group;
671 ModestWindowPrivate *parent_priv;
672 GdkPixbuf *window_icon = NULL;
673 GError *error = NULL;
675 GtkSizeGroup *title_size_group;
676 GtkSizeGroup *value_size_group;
677 GtkWidget *subject_box;
678 GtkWidget *attachment_icon;
679 GtkWidget *window_box;
680 #if (GTK_MINOR_VERSION >= 10)
681 GdkAtom deserialize_type;
684 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
685 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
687 parent_priv->ui_manager = gtk_ui_manager_new();
688 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
689 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
691 /* Add common actions */
692 gtk_action_group_add_actions (action_group,
693 modest_msg_edit_action_entries,
694 G_N_ELEMENTS (modest_msg_edit_action_entries),
696 gtk_action_group_add_actions (action_group,
697 hildon2_msg_edit_action_entries,
698 G_N_ELEMENTS (hildon2_msg_edit_action_entries),
700 gtk_action_group_add_toggle_actions (action_group,
701 modest_msg_edit_toggle_action_entries,
702 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
704 gtk_action_group_add_radio_actions (action_group,
705 modest_msg_edit_alignment_radio_action_entries,
706 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
708 G_CALLBACK (modest_ui_actions_on_change_justify),
710 gtk_action_group_add_radio_actions (action_group,
711 modest_msg_edit_priority_action_entries,
712 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
714 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
716 gtk_action_group_add_radio_actions (action_group,
717 modest_msg_edit_file_format_action_entries,
718 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
719 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
720 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
722 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
723 g_object_unref (action_group);
725 /* Load the UI definition */
726 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
729 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
730 g_clear_error (&error);
733 /* Add accelerators */
734 gtk_window_add_accel_group (GTK_WINDOW (obj),
735 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
737 parent_priv->menubar = NULL;
739 title_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
740 value_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
742 /* Note: This ModestPairList* must exist for as long as the picker
743 * that uses it, because the ModestSelectorPicker uses the ID opaquely,
744 * so it can't know how to manage its memory. */
745 priv->from_field = modest_selector_picker_new (MODEST_EDITABLE_SIZE,
746 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL,
748 modest_maemo_utils_set_hbutton_layout (title_size_group, value_size_group,
749 _("mail_va_from"), priv->from_field);
751 priv->to_field = modest_recpt_editor_new ();
752 priv->cc_field = modest_recpt_editor_new ();
753 priv->bcc_field = modest_recpt_editor_new ();
754 subject_box = gtk_hbox_new (FALSE, 0);
755 priv->priority_icon = gtk_image_new ();
756 gtk_box_pack_start (GTK_BOX (subject_box), priv->priority_icon, FALSE, FALSE, 0);
757 priv->subject_field = hildon_entry_new (MODEST_EDITABLE_SIZE);
758 gtk_entry_set_max_length (GTK_ENTRY (priv->subject_field) ,SUBJECT_MAX_LENGTH);
759 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
760 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
761 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
762 gtk_box_pack_start (GTK_BOX (subject_box), priv->subject_field, TRUE, TRUE, 0);
763 priv->add_attachment_button = gtk_button_new ();
764 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
765 gtk_button_set_relief (GTK_BUTTON (priv->add_attachment_button), GTK_RELIEF_NONE);
766 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
767 gtk_button_set_alignment (GTK_BUTTON (priv->add_attachment_button), 1.0, 0.5);
768 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, HILDON_ICON_SIZE_FINGER);
769 gtk_container_add (GTK_CONTAINER (priv->add_attachment_button), attachment_icon);
770 gtk_box_pack_start (GTK_BOX (subject_box), priv->add_attachment_button, FALSE, FALSE, 0);
771 priv->attachments_view = modest_attachments_view_new (NULL);
773 priv->header_box = gtk_vbox_new (FALSE, 0);
775 to_caption = modest_maemo_utils_create_captioned_with_size_type
776 (title_size_group, value_size_group,
777 _("mail_va_to"), priv->to_field,
778 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
779 priv->cc_caption = modest_maemo_utils_create_captioned_with_size_type
780 (title_size_group, value_size_group,
781 _("mail_va_cc"), priv->cc_field,
782 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
783 priv->bcc_caption = modest_maemo_utils_create_captioned_with_size_type
784 (title_size_group, value_size_group,
785 _("mail_va_hotfix1"), priv->bcc_field,
786 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
787 subject_caption = modest_maemo_utils_create_captioned (title_size_group, value_size_group,
788 _("mail_va_subject"), subject_box);
789 priv->attachments_caption = modest_maemo_utils_create_captioned_with_size_type (title_size_group, value_size_group,
790 _("mail_va_attachment"),
791 priv->attachments_view,
792 HILDON_SIZE_AUTO_WIDTH |
793 HILDON_SIZE_AUTO_HEIGHT);
794 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), value_size_group); */
795 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), value_size_group); */
796 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), value_size_group); */
797 g_object_unref (title_size_group);
798 g_object_unref (value_size_group);
800 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->from_field, FALSE, FALSE, 0);
801 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
802 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
803 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
804 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
805 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
806 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
808 init_wp_text_view_style ();
810 priv->msg_body = wp_text_view_new ();
813 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
814 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
815 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
816 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
817 #if (GTK_MINOR_VERSION >= 10)
818 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
819 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
821 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
822 deserialize_type, TRUE);
824 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
826 priv->find_toolbar = hildon_find_toolbar_new (NULL);
827 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
829 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
831 priv->pannable = hildon_pannable_area_new ();
833 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
835 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
836 priv->frame = gtk_frame_new (NULL);
837 gtk_box_pack_start (GTK_BOX(main_vbox), priv->frame, TRUE, TRUE, 0);
839 hildon_pannable_area_add_with_viewport (HILDON_PANNABLE_AREA (priv->pannable), main_vbox);
840 gtk_widget_show_all (GTK_WIDGET(priv->pannable));
842 window_box = gtk_vbox_new (FALSE, 0);
843 gtk_container_add (GTK_CONTAINER(obj), window_box);
845 gtk_box_pack_start (GTK_BOX (window_box), priv->pannable, TRUE, TRUE, 0);
847 gtk_container_add (GTK_CONTAINER (priv->frame), priv->msg_body);
849 /* Set window icon */
850 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
852 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
853 g_object_unref (window_icon);
858 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
860 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
862 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
863 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
864 priv->clipboard_change_handler_id))
865 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
866 priv->clipboard_change_handler_id);
867 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
868 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
869 priv->default_clipboard_change_handler_id))
870 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
871 priv->default_clipboard_change_handler_id);
873 if (priv->account_removed_handler_id &&
874 g_signal_handler_is_connected (modest_runtime_get_account_store (),
875 priv->account_removed_handler_id))
876 g_signal_handler_disconnect(modest_runtime_get_account_store (),
877 priv->account_removed_handler_id);
881 modest_msg_edit_window_finalize (GObject *obj)
883 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
885 /* Sanity check: shouldn't be needed, the window mgr should
886 call this function before */
887 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
889 if (priv->font_dialog != NULL) {
890 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
893 if (priv->clipboard_text != NULL) {
894 g_free (priv->clipboard_text);
895 priv->clipboard_text = NULL;
898 if (priv->draft_msg != NULL) {
899 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
900 if (TNY_IS_HEADER (header)) {
901 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
902 modest_window_mgr_unregister_header (mgr, header);
904 g_object_unref (priv->draft_msg);
905 priv->draft_msg = NULL;
907 if (priv->outbox_msg != NULL) {
908 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
909 if (TNY_IS_HEADER (header)) {
910 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
911 modest_window_mgr_unregister_header (mgr, header);
913 g_object_unref (priv->outbox_msg);
914 priv->outbox_msg = NULL;
916 if (priv->scroll_drag_timeout_id > 0) {
917 g_source_remove (priv->scroll_drag_timeout_id);
918 priv->scroll_drag_timeout_id = 0;
920 if (priv->clipboard_owner_idle > 0) {
921 g_source_remove (priv->clipboard_owner_idle);
922 priv->clipboard_owner_idle = 0;
924 if (priv->original_account_name)
925 g_free (priv->original_account_name);
926 g_free (priv->msg_uid);
927 g_free (priv->last_search);
928 g_slist_free (priv->font_items_group);
929 g_slist_free (priv->size_items_group);
930 g_object_unref (priv->attachments);
931 g_object_unref (priv->images);
933 /* This had to stay alive for as long as the picker that used it: */
934 modest_pair_list_free (priv->from_field_protos);
936 G_OBJECT_CLASS(parent_class)->finalize (obj);
940 pixbuf_from_stream (TnyStream *stream, const gchar *mime_type, guint64 *stream_size)
942 GdkPixbufLoader *loader;
948 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
950 if (loader == NULL) {
956 tny_stream_reset (TNY_STREAM (stream));
957 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
958 GError *error = NULL;
959 unsigned char read_buffer[128];
961 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
963 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
965 g_error_free (error);
970 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
972 g_object_ref (pixbuf);
973 gdk_pixbuf_loader_close (loader, NULL);
974 g_object_unref (loader);
979 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
980 GdkPixbuf *new_pixbuf;
982 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
983 gdk_pixbuf_get_width (pixbuf);
984 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
985 g_object_unref (pixbuf);
996 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
998 ModestMsgEditWindowPrivate *priv;
1001 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1003 for (iter = tny_list_create_iterator (attachments);
1004 !tny_iterator_is_done (iter);
1005 tny_iterator_next (iter)) {
1006 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1007 const gchar *cid = tny_mime_part_get_content_id (part);
1008 const gchar *mime_type = tny_mime_part_get_content_type (part);
1009 if ((cid != NULL)&&(mime_type != NULL)) {
1010 guint64 stream_size;
1011 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1012 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
1015 g_object_unref (stream);
1017 if (pixbuf != NULL) {
1018 priv->images_count ++;
1019 priv->images_size += stream_size;
1020 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1021 g_object_unref (pixbuf);
1024 g_object_unref (part);
1026 g_object_unref (iter);
1030 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1032 TnyMimePart *parent = NULL;
1033 const gchar *content_type = NULL;
1034 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1036 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1038 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1039 parent = g_object_ref (msg);
1040 } else if (content_type && !g_strcasecmp (content_type, "multipart/mixed")) {
1041 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1044 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1045 iter = tny_list_create_iterator (parts);
1046 while (!tny_iterator_is_done (iter)) {
1048 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1049 content_type = tny_mime_part_get_content_type (part);
1050 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1054 g_object_unref (part);
1056 tny_iterator_next (iter);
1058 g_object_unref (iter);
1059 g_object_unref (parts);
1062 if (parent != NULL) {
1063 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1066 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1067 iter = tny_list_create_iterator (parts);
1068 while (!tny_iterator_is_done (iter)) {
1070 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1071 content_type = tny_mime_part_get_content_type (part);
1072 if (content_type && g_str_has_prefix (content_type, "image/")) {
1073 tny_list_prepend (priv->images, (GObject *) part);
1075 g_object_unref (part);
1076 tny_iterator_next (iter);
1078 g_object_unref (iter);
1079 g_object_unref (parts);
1080 g_object_unref (parent);
1085 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1088 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1090 for (iter = tny_list_create_iterator (attachments) ;
1091 !tny_iterator_is_done (iter);
1092 tny_iterator_next (iter)) {
1093 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1094 const gchar *cid = tny_mime_part_get_content_id (part);
1096 char *invalid = NULL;
1097 gint int_cid = strtol (cid, &invalid, 10);
1098 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1099 priv->next_cid = int_cid + 1;
1102 g_object_unref (part);
1104 g_object_unref (iter);
1108 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1111 gchar *to, *cc, *bcc, *subject;
1113 ModestMsgEditWindowPrivate *priv;
1114 ModestWindowPrivate *parent_priv;
1116 TnyHeaderFlags priority_flags;
1117 TnyFolder *msg_folder;
1118 gboolean is_html = FALSE;
1119 gboolean field_view_set;
1121 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1122 g_return_if_fail (TNY_IS_MSG (msg));
1124 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1125 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1127 header = tny_msg_get_header (msg);
1128 to = tny_header_dup_to (header);
1129 cc = tny_header_dup_cc (header);
1130 bcc = tny_header_dup_bcc (header);
1131 subject = tny_header_dup_subject (header);
1132 priority_flags = tny_header_get_priority (header);
1135 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
1137 field_view_set = TRUE;
1139 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
1140 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1141 gtk_widget_show (priv->cc_caption);
1142 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1143 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1144 gtk_widget_hide (priv->cc_caption);
1145 field_view_set = FALSE;
1147 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button), field_view_set);
1149 field_view_set = TRUE;
1151 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
1152 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1153 gtk_widget_show (priv->bcc_caption);
1154 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1155 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1156 gtk_widget_hide (priv->bcc_caption);
1157 field_view_set = FALSE;
1159 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button), field_view_set);
1163 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1164 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1167 update_window_title (self);
1169 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1170 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1172 if ((body == NULL)||(body[0] == '\0')) {
1174 body = modest_text_utils_convert_to_html ("");
1177 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1178 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1181 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1184 /* Add attachments to the view */
1185 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1186 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1187 if (tny_list_get_length (priv->attachments) == 0) {
1188 gtk_widget_hide (priv->attachments_caption);
1190 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1191 gtk_widget_show_all (priv->attachments_caption);
1193 get_related_images (self, msg);
1194 update_next_cid (self, priv->attachments);
1195 update_next_cid (self, priv->images);
1196 replace_with_images (self, priv->images);
1198 if (preserve_is_rich && !is_html) {
1199 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1200 /* Get the default format required from configuration */
1201 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1202 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1205 /* Set the default focus depending on having already a To: field or not */
1206 if ((!to)||(*to == '\0')) {
1207 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1209 gtk_widget_grab_focus (priv->msg_body);
1212 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1214 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1215 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1217 modest_msg_edit_window_set_modified (self, FALSE);
1219 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1220 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1221 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1222 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1224 if (priv->msg_uid) {
1225 g_free (priv->msg_uid);
1226 priv->msg_uid = NULL;
1229 /* we should set a reference to the incoming message if it is a draft */
1230 msg_folder = tny_msg_get_folder (msg);
1232 if (modest_tny_folder_is_local_folder (msg_folder)) {
1233 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1234 if (type == TNY_FOLDER_TYPE_INVALID)
1235 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1237 if (type == TNY_FOLDER_TYPE_DRAFTS)
1238 priv->draft_msg = g_object_ref(msg);
1239 if (type == TNY_FOLDER_TYPE_OUTBOX)
1240 priv->outbox_msg = g_object_ref(msg);
1241 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1243 g_object_unref (msg_folder);
1253 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
1256 GList *item_children, *node;
1257 GtkWidget *bin_child;
1259 bin_child = gtk_bin_get_child (GTK_BIN(item));
1261 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
1263 for (node = item_children; node != NULL; node = g_list_next (node)) {
1264 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
1265 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
1268 g_list_free (item_children);
1272 menu_tool_button_dont_expand (GtkMenuToolButton *item)
1275 GList *item_children, *node;
1277 box = gtk_bin_get_child (GTK_BIN (item));
1278 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
1279 item_children = gtk_container_get_children (GTK_CONTAINER (box));
1281 for (node = item_children; node != NULL; node = g_list_next (node)) {
1282 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
1283 if (GTK_IS_TOGGLE_BUTTON (node->data))
1284 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
1285 else if (GTK_IS_BUTTON (node->data))
1286 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
1288 g_list_free (item_children);
1293 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1295 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1296 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1297 GtkWidget *placeholder;
1298 GtkWidget *tool_item;
1303 GtkWidget *sizes_menu;
1304 GtkWidget *fonts_menu;
1305 GSList *radio_group = NULL;
1306 GSList *node = NULL;
1310 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1311 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1313 /* Font color placeholder */
1314 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1315 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1318 priv->font_color_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1319 priv->font_color_button = hildon_color_button_new ();
1320 GTK_WIDGET_UNSET_FLAGS (tool_item, GTK_CAN_FOCUS);
1321 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1322 gtk_container_add (GTK_CONTAINER (priv->font_color_toolitem), priv->font_color_button);
1323 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1324 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1325 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->font_color_toolitem), insert_index);
1326 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1328 G_CALLBACK (modest_msg_edit_window_color_button_change),
1331 /* Font size and face placeholder */
1332 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1333 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1335 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1336 priv->size_tool_button_label = gtk_label_new (NULL);
1337 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1338 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1339 size_text,"</span>", NULL);
1340 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1342 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
1343 sizes_menu = gtk_menu_new ();
1344 priv->size_items_group = NULL;
1346 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1347 GtkWidget *size_menu_item;
1349 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1350 size_menu_item = gtk_radio_menu_item_new_with_label (radio_group, size_text);
1351 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (size_menu_item));
1352 gtk_menu_shell_append (GTK_MENU_SHELL (sizes_menu), size_menu_item);
1353 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (size_menu_item), (wp_font_size[size_index] == 12));
1354 gtk_widget_show (size_menu_item);
1356 priv->size_items_group = g_slist_prepend (priv->size_items_group, size_menu_item);
1360 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1361 GtkWidget *item = (GtkWidget *) node->data;
1362 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_size_change),
1366 priv->size_items_group = g_slist_reverse (priv->size_items_group);
1367 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), sizes_menu);
1368 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1369 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1370 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1371 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1372 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1373 priv->font_size_toolitem = tool_item;
1376 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1377 priv->font_tool_button_label = gtk_label_new (NULL);
1378 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1379 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1381 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
1382 fonts_menu = gtk_menu_new ();
1383 priv->font_items_group = NULL;
1385 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1386 GtkWidget *font_menu_item;
1387 GtkWidget *child_label;
1389 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
1390 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
1391 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
1392 wp_get_font_name (font_index), "</span>", NULL);
1393 gtk_label_set_markup (GTK_LABEL (child_label), markup);
1396 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
1397 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
1398 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
1399 gtk_widget_show (font_menu_item);
1401 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
1404 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1405 GtkWidget *item = (GtkWidget *) node->data;
1406 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
1409 priv->font_items_group = g_slist_reverse (priv->font_items_group);
1410 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
1411 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1412 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1413 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1414 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1415 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1416 priv->font_face_toolitem = tool_item;
1418 /* Set expand and homogeneous for remaining items */
1419 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
1420 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1421 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1422 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1423 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1424 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1425 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1426 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1427 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1429 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1430 will not show the tool items added to the placeholders) */
1431 gtk_widget_show_all (parent_priv->toolbar);
1433 /* Set the no show all *after* showing all items. We do not
1434 want the toolbar to be shown with a show all because it
1435 could go agains the gconf setting regarding showing or not
1436 the toolbar of the editor window */
1437 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1443 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, gboolean preserve_is_rich)
1446 ModestWindowPrivate *parent_priv;
1447 ModestMsgEditWindowPrivate *priv;
1448 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1449 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1450 ModestWindowMgr *mgr = NULL;
1452 g_return_val_if_fail (msg, NULL);
1453 g_return_val_if_fail (account_name, NULL);
1455 mgr = modest_runtime_get_window_mgr ();
1457 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1459 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1460 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1462 /* Menubar. Update the state of some toggles */
1463 priv->from_field_protos = get_transports ();
1464 modest_selector_picker_set_pair_list (MODEST_SELECTOR_PICKER (priv->from_field), priv->from_field_protos);
1465 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1466 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1468 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1469 hildon_touch_selector_get_current_text
1470 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1471 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1472 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1475 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1477 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1479 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1481 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1483 parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new ();
1484 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1485 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1486 /* Add common dimming rules */
1487 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1488 modest_msg_edit_window_toolbar_dimming_entries,
1489 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1490 MODEST_WINDOW (obj));
1491 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_toolitem,
1492 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1493 MODEST_WINDOW (obj));
1494 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1495 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1496 MODEST_WINDOW (obj));
1497 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1498 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1499 MODEST_WINDOW (obj));
1500 /* Insert dimming rules group for this window */
1501 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1502 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1504 /* Setup app menu */
1505 setup_menu (MODEST_MSG_EDIT_WINDOW (obj));
1507 /* Checks the dimming rules */
1508 g_object_unref (toolbar_rules_group);
1509 g_object_unref (clipboard_rules_group);
1510 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1512 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1514 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1515 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1516 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1517 priv->update_caption_visibility = TRUE;
1519 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1521 /* Track account-removed signal, this window should be closed
1522 in the case we're creating a mail associated to the account
1524 priv->account_removed_handler_id =
1525 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1527 G_CALLBACK(on_account_removed),
1530 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1532 return (ModestWindow*) obj;
1536 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1538 GString **string_buffer = (GString **) user_data;
1540 *string_buffer = g_string_append (*string_buffer, buffer);
1546 * @result: A new string which should be freed with g_free().
1549 get_formatted_data (ModestMsgEditWindow *edit_window)
1551 ModestMsgEditWindowPrivate *priv;
1552 GString *string_buffer = g_string_new ("");
1554 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1556 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1558 modest_text_utils_hyperlinkify (string_buffer);
1560 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1562 return g_string_free (string_buffer, FALSE);
1567 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1570 const gchar *account_name;
1571 ModestMsgEditWindowPrivate *priv;
1572 TnyIterator *att_iter;
1574 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1576 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1578 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1579 g_return_val_if_fail (account_name, NULL);
1582 /* don't free these (except from) */
1583 data = g_slice_new0 (MsgData);
1584 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1586 data->account_name = g_strdup (account_name);
1587 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1588 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1589 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1590 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1591 if (priv->draft_msg) {
1592 data->draft_msg = g_object_ref (priv->draft_msg);
1593 } else if (priv->outbox_msg) {
1594 data->draft_msg = g_object_ref (priv->outbox_msg);
1596 data->draft_msg = NULL;
1599 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1601 gtk_text_buffer_get_bounds (buf, &b, &e);
1602 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1604 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1605 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1607 data->html_body = NULL;
1609 /* deep-copy the data */
1610 att_iter = tny_list_create_iterator (priv->attachments);
1611 data->attachments = NULL;
1612 while (!tny_iterator_is_done (att_iter)) {
1613 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1614 if (!(TNY_IS_MIME_PART(part))) {
1615 g_warning ("strange data in attachment list");
1616 g_object_unref (part);
1617 tny_iterator_next (att_iter);
1620 data->attachments = g_list_append (data->attachments,
1622 tny_iterator_next (att_iter);
1624 g_object_unref (att_iter);
1626 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1627 att_iter = tny_list_create_iterator (priv->images);
1628 data->images = NULL;
1629 while (!tny_iterator_is_done (att_iter)) {
1630 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1632 if (!(TNY_IS_MIME_PART(part))) {
1633 g_warning ("strange data in attachment list");
1634 g_object_unref (part);
1635 tny_iterator_next (att_iter);
1638 cid = tny_mime_part_get_content_id (part);
1640 gchar *image_tag_id;
1641 GtkTextTag *image_tag;
1643 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1644 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1645 g_free (image_tag_id);
1647 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1649 ((gtk_text_iter_has_tag (&iter, image_tag))||
1650 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1651 data->images = g_list_append (data->images,
1652 g_object_ref (part));
1654 g_object_unref (part);
1655 tny_iterator_next (att_iter);
1657 g_object_unref (att_iter);
1659 data->priority_flags = priv->priority_flags;
1666 unref_gobject (GObject *obj, gpointer data)
1668 if (!G_IS_OBJECT(obj))
1670 g_object_unref (obj);
1674 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1677 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1685 g_free (data->from);
1686 g_free (data->subject);
1687 g_free (data->plain_body);
1688 g_free (data->html_body);
1689 g_free (data->account_name);
1691 if (data->draft_msg != NULL) {
1692 g_object_unref (data->draft_msg);
1693 data->draft_msg = NULL;
1696 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1697 g_list_free (data->attachments);
1698 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1699 g_list_free (data->images);
1701 g_slice_free (MsgData, data);
1705 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1707 guint64 *parts_size)
1709 ModestMsgEditWindowPrivate *priv;
1711 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1713 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1715 /* TODO: add images */
1716 *parts_size += priv->images_size;
1717 *parts_count += priv->images_count;
1722 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1725 ModestMsgEditWindowPrivate *priv = NULL;
1726 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1728 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1730 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1732 return MODEST_MSG_EDIT_FORMAT_HTML;
1734 return MODEST_MSG_EDIT_FORMAT_TEXT;
1738 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1739 ModestMsgEditFormat format)
1741 ModestMsgEditWindowPrivate *priv;
1743 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1744 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1747 case MODEST_MSG_EDIT_FORMAT_HTML:
1748 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1750 case MODEST_MSG_EDIT_FORMAT_TEXT:
1751 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1754 g_return_if_reached ();
1758 ModestMsgEditFormatState *
1759 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1761 ModestMsgEditFormatState *format_state = NULL;
1762 ModestMsgEditWindowPrivate *priv;
1763 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1765 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1766 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1768 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1770 format_state = g_new0 (ModestMsgEditFormatState, 1);
1771 format_state->bold = buffer_format->bold&0x1;
1772 format_state->italics = buffer_format->italic&0x1;
1773 format_state->bullet = buffer_format->bullet&0x1;
1774 format_state->color = buffer_format->color;
1775 format_state->font_size = buffer_format->font_size;
1776 format_state->font_family = wp_get_font_name (buffer_format->font);
1777 format_state->justification = buffer_format->justification;
1778 g_free (buffer_format);
1780 return format_state;
1785 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1786 const ModestMsgEditFormatState *format_state)
1788 ModestMsgEditWindowPrivate *priv;
1789 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1790 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1791 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1792 g_return_if_fail (format_state != NULL);
1794 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1795 gtk_widget_grab_focus (priv->msg_body);
1796 buffer_format->bold = (format_state->bold != FALSE);
1797 buffer_format->italic = (format_state->italics != FALSE);
1798 buffer_format->color = format_state->color;
1799 buffer_format->font_size = format_state->font_size;
1800 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1801 buffer_format->justification = format_state->justification;
1802 buffer_format->bullet = format_state->bullet;
1804 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1806 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1807 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1808 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1809 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1810 buffer_format->cs.font = (buffer_format->font != current_format->font);
1811 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1812 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1814 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1815 if (buffer_format->cs.bold) {
1816 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
1817 GINT_TO_POINTER (buffer_format->bold&0x1));
1819 if (buffer_format->cs.italic) {
1820 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
1821 GINT_TO_POINTER (buffer_format->italic&0x1));
1823 if (buffer_format->cs.color) {
1824 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1825 GINT_TO_POINTER (&(buffer_format->color)));
1827 if (buffer_format->cs.font_size) {
1828 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1829 GINT_TO_POINTER (buffer_format->font_size));
1831 if (buffer_format->cs.justification) {
1832 switch (buffer_format->justification) {
1833 case GTK_JUSTIFY_LEFT:
1834 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
1835 GINT_TO_POINTER(TRUE));
1837 case GTK_JUSTIFY_CENTER:
1838 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
1839 GINT_TO_POINTER(TRUE));
1841 case GTK_JUSTIFY_RIGHT:
1842 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
1843 GINT_TO_POINTER(TRUE));
1850 if (buffer_format->cs.font) {
1851 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1852 GINT_TO_POINTER (buffer_format->font));
1854 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1855 if (buffer_format->cs.bullet) {
1856 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
1857 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
1859 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1861 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
1863 g_free (buffer_format);
1864 g_free (current_format);
1866 /* Check dimming rules */
1867 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1868 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1872 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1874 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1876 ModestWindowPrivate *parent_priv;
1877 ModestMsgEditWindowPrivate *priv;
1878 GtkWidget *new_size_menuitem;
1879 GtkWidget *new_font_menuitem;
1881 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1882 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1884 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1885 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu");
1886 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1887 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1889 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatPlainTextMenu");
1890 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1891 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1894 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1896 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1897 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1899 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1900 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1902 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
1903 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
1906 switch (buffer_format->justification)
1908 case GTK_JUSTIFY_LEFT:
1909 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
1911 case GTK_JUSTIFY_CENTER:
1912 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
1914 case GTK_JUSTIFY_RIGHT:
1915 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
1922 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
1924 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1925 G_CALLBACK (modest_msg_edit_window_color_button_change),
1927 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1928 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1929 G_CALLBACK (modest_msg_edit_window_color_button_change),
1932 new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group,
1933 buffer_format->font_size))->data);
1934 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1938 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1939 markup = g_strconcat ("<span font_family='Sans'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1940 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1942 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1943 G_CALLBACK (modest_msg_edit_window_size_change),
1945 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
1946 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
1947 G_CALLBACK (modest_msg_edit_window_size_change),
1951 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
1952 buffer_format->font))->data);
1953 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
1957 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
1958 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1959 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1961 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
1962 G_CALLBACK (modest_msg_edit_window_font_change),
1964 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
1965 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
1966 G_CALLBACK (modest_msg_edit_window_font_change),
1970 g_free (buffer_format);
1974 #ifdef MODEST_HILDON_VERSION_0
1976 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
1979 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1980 ModestMsgEditWindowPrivate *priv;
1981 GtkWidget *dialog = NULL;
1983 GdkColor *new_color = NULL;
1985 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1986 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1988 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1989 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
1990 g_free (buffer_format);
1992 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
1993 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1994 if (new_color != NULL) {
1995 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1996 (gpointer) new_color);
1999 gtk_widget_destroy (dialog);
2004 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2007 ModestMsgEditWindowPrivate *priv;
2008 GtkWidget *dialog = NULL;
2010 GdkColor *old_color = NULL;
2011 const GdkColor *new_color = NULL;
2013 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2014 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2016 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2017 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2019 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2020 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2021 if (new_color != NULL)
2022 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2024 gtk_widget_destroy (dialog);
2030 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2033 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2034 ModestMsgEditWindowPrivate *priv;
2035 GtkWidget *dialog = NULL;
2037 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2038 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2040 dialog = hildon_color_chooser_new ();
2041 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2042 g_free (buffer_format);
2044 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2046 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2047 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2050 gtk_widget_destroy (dialog);
2055 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2058 ModestMsgEditWindowPrivate *priv;
2059 GtkWidget *dialog = NULL;
2060 GdkColor *old_color = NULL;
2062 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2063 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2065 dialog = hildon_color_chooser_new ();
2066 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
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_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2073 gtk_widget_destroy (dialog);
2076 #endif /*!MODEST_HILDON_VERSION_0*/
2081 create_stream_for_uri (const gchar* uri)
2086 TnyStream *result = NULL;
2088 GnomeVFSHandle *handle = NULL;
2089 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2090 if (test == GNOME_VFS_OK) {
2091 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2092 /* Streams over OBEX (Bluetooth) are not seekable but
2093 * we expect them to be (we might need to read them
2094 * several times). So if this is a Bluetooth URI just
2095 * read the whole file into memory (this is not a fast
2096 * protocol so we can assume that these files are not
2097 * going to be very big) */
2098 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2099 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2100 TnyStream *memstream = tny_camel_mem_stream_new ();
2101 tny_stream_write_to_stream (vfssstream, memstream);
2102 g_object_unref (vfssstream);
2105 result = vfssstream;
2113 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2116 ModestMsgEditWindowPrivate *priv;
2117 GtkWidget *dialog = NULL;
2119 GSList *uris = NULL;
2120 GSList *uri_node = NULL;
2122 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2124 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2125 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2126 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2128 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2130 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2131 GTK_WINDOW (dialog), GTK_WINDOW (window));
2133 response = gtk_dialog_run (GTK_DIALOG (dialog));
2135 case GTK_RESPONSE_OK:
2136 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2141 gtk_widget_destroy (dialog);
2143 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2145 GnomeVFSHandle *handle = NULL;
2146 GnomeVFSResult result;
2147 GtkTextIter position;
2148 GtkTextMark *insert_mark;
2150 uri = (const gchar *) uri_node->data;
2151 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2152 if (result == GNOME_VFS_OK) {
2154 GnomeVFSFileInfo *info;
2155 gchar *filename, *basename, *escaped_filename;
2156 TnyMimePart *mime_part;
2158 const gchar *mime_type = NULL;
2159 GnomeVFSURI *vfs_uri;
2160 guint64 stream_size;
2162 gnome_vfs_close (handle);
2163 vfs_uri = gnome_vfs_uri_new (uri);
2165 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2166 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2167 g_free (escaped_filename);
2168 gnome_vfs_uri_unref (vfs_uri);
2169 info = gnome_vfs_file_info_new ();
2171 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2172 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2174 mime_type = gnome_vfs_file_info_get_mime_type (info);
2176 mime_part = tny_platform_factory_new_mime_part
2177 (modest_runtime_get_platform_factory ());
2179 TnyStream *stream = create_stream_for_uri (uri);
2181 if (stream == NULL) {
2183 modest_platform_information_banner (NULL, NULL, dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2185 g_object_unref (mime_part);
2186 gnome_vfs_file_info_unref (info);
2190 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2192 content_id = g_strdup_printf ("%d", priv->next_cid);
2193 tny_mime_part_set_content_id (mime_part, content_id);
2194 g_free (content_id);
2197 basename = g_path_get_basename (filename);
2198 tny_mime_part_set_filename (mime_part, basename);
2201 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
2203 if (pixbuf != NULL) {
2204 priv->images_size += stream_size;
2205 priv->images_count ++;
2206 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2207 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2208 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
2209 g_object_unref (pixbuf);
2212 tny_list_prepend (priv->images, (GObject *) mime_part);
2213 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2215 g_object_unref (mime_part);
2216 gnome_vfs_file_info_unref (info);
2225 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2227 GtkWidget *dialog = NULL;
2229 GSList *uris = NULL;
2231 GnomeVFSFileSize total_size, allowed_size;
2232 ModestMsgEditWindowPrivate *priv;
2236 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2238 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2240 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2243 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2244 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2245 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2246 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), GTK_WINDOW (dialog), GTK_WINDOW (window));
2248 response = gtk_dialog_run (GTK_DIALOG (dialog));
2250 case GTK_RESPONSE_OK:
2251 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2256 gtk_widget_destroy (dialog);
2258 /* allowed size is the maximum size - what's already there */
2259 modest_attachments_view_get_sizes (
2260 MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2261 &att_num, &att_size);
2262 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2265 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2267 const gchar *uri = (const gchar *) uri_node->data;
2269 total_size += modest_msg_edit_window_attach_file_one
2270 (window, uri, allowed_size);
2272 if (total_size > allowed_size) {
2273 g_warning ("%s: total size: %u",
2274 __FUNCTION__, (unsigned int)total_size);
2278 allowed_size -= total_size;
2282 g_slist_foreach (uris, (GFunc) g_free, NULL);
2283 g_slist_free (uris);
2288 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2290 GnomeVFSFileSize allowed_size)
2293 GnomeVFSHandle *handle = NULL;
2294 ModestMsgEditWindowPrivate *priv;
2295 GnomeVFSResult result;
2296 GnomeVFSFileSize size = 0;
2297 g_return_val_if_fail (window, 0);
2298 g_return_val_if_fail (uri, 0);
2300 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2302 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2303 if (result == GNOME_VFS_OK) {
2304 TnyMimePart *mime_part;
2306 const gchar *mime_type = NULL;
2308 gchar *escaped_filename;
2311 GnomeVFSFileInfo *info;
2312 GnomeVFSURI *vfs_uri;
2314 gnome_vfs_close (handle);
2315 vfs_uri = gnome_vfs_uri_new (uri);
2318 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2319 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2320 g_free (escaped_filename);
2321 gnome_vfs_uri_unref (vfs_uri);
2323 info = gnome_vfs_file_info_new ();
2325 if (gnome_vfs_get_file_info (uri,
2327 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2329 mime_type = gnome_vfs_file_info_get_mime_type (info);
2330 mime_part = tny_platform_factory_new_mime_part
2331 (modest_runtime_get_platform_factory ());
2333 /* try to get the attachment's size; this may fail for weird
2334 * file systems, like obex, upnp... */
2335 if (allowed_size != 0 &&
2336 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2338 if (size > allowed_size) {
2339 modest_platform_information_banner (NULL, NULL,
2340 dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2344 g_warning ("%s: could not get attachment size", __FUNCTION__);
2346 stream = create_stream_for_uri (uri);
2348 if (stream == NULL) {
2350 modest_platform_information_banner (NULL, NULL, dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2352 g_object_unref (mime_part);
2353 gnome_vfs_file_info_unref (info);
2357 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2358 g_object_unref (stream);
2360 content_id = g_strdup_printf ("%d", priv->next_cid);
2361 tny_mime_part_set_content_id (mime_part, content_id);
2362 g_free (content_id);
2365 basename = g_path_get_basename (filename);
2366 tny_mime_part_set_filename (mime_part, basename);
2369 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2370 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2372 info->size == 0, info->size);
2373 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2374 gtk_widget_show_all (priv->attachments_caption);
2375 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2377 g_object_unref (mime_part);
2378 gnome_vfs_file_info_unref (info);
2385 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2388 ModestMsgEditWindowPrivate *priv;
2391 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2392 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2394 if (att_list == NULL) {
2395 att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2397 g_object_ref (att_list);
2400 if (tny_list_get_length (att_list) == 0) {
2401 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2403 gboolean dialog_response;
2404 gchar *message = NULL;
2405 gchar *filename = NULL;
2407 if (tny_list_get_length (att_list) == 1) {
2409 iter = tny_list_create_iterator (att_list);
2410 part = (TnyMimePart *) tny_iterator_get_current (iter);
2411 g_object_unref (iter);
2412 if (TNY_IS_MSG (part)) {
2413 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2415 filename = tny_header_dup_subject (header);
2416 g_object_unref (header);
2418 if (filename == NULL) {
2419 filename = g_strdup (_("mail_va_no_subject"));
2422 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2424 g_object_unref (part);
2426 filename = g_strdup ("");
2428 message = g_strdup_printf (ngettext("emev_nc_delete_attachment", "emev_nc_delete_attachments",
2429 tny_list_get_length (att_list)), filename);
2432 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window), message);
2435 if (dialog_response != GTK_RESPONSE_OK) {
2436 g_object_unref (att_list);
2439 hildon_banner_show_information (NULL, NULL, _("mcen_me_inbox_remove_attachments"));
2441 for (iter = tny_list_create_iterator (att_list);
2442 !tny_iterator_is_done (iter);
2443 tny_iterator_next (iter)) {
2444 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2445 const gchar *att_id;
2446 tny_list_remove (priv->attachments, (GObject *) mime_part);
2448 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2450 if (tny_list_get_length (priv->attachments) == 0)
2451 gtk_widget_hide (priv->attachments_caption);
2452 att_id = tny_mime_part_get_content_id (mime_part);
2454 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2456 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2457 g_object_unref (mime_part);
2459 g_object_unref (iter);
2462 g_object_unref (att_list);
2464 /* if the last attachment has been removed, focus the Subject: field */
2465 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2466 gtk_widget_grab_focus (priv->subject_field);
2470 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2473 ModestMsgEditWindowPrivate *priv;
2474 GdkColor *new_color;
2475 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2477 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2478 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2481 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2483 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2485 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2487 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2492 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
2495 ModestMsgEditWindowPrivate *priv;
2496 gint new_size_index;
2497 ModestMsgEditWindow *window;
2500 window = MODEST_MSG_EDIT_WINDOW (userdata);
2501 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2502 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2504 if (gtk_check_menu_item_get_active (menu_item)) {
2506 WPTextBufferFormat format;
2508 memset (&format, 0, sizeof (format));
2509 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2511 label = gtk_bin_get_child (GTK_BIN (menu_item));
2513 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
2514 format.cs.font_size = TRUE;
2515 format.cs.text_position = TRUE;
2516 format.cs.font = TRUE;
2517 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
2518 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2520 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2521 GINT_TO_POINTER (wp_get_font_size_index (new_size_index, 12))))
2522 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2524 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2525 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
2526 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2532 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
2535 ModestMsgEditWindowPrivate *priv;
2536 gint new_font_index;
2537 ModestMsgEditWindow *window;
2540 window = MODEST_MSG_EDIT_WINDOW (userdata);
2541 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2542 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2544 if (gtk_check_menu_item_get_active (menu_item)) {
2547 label = gtk_bin_get_child (GTK_BIN (menu_item));
2549 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
2551 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2552 GINT_TO_POINTER(new_font_index)))
2553 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2555 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2556 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2557 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2563 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2566 ModestMsgEditWindowPrivate *priv = NULL;
2567 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2569 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2570 if (!priv->update_caption_visibility)
2573 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2575 gtk_widget_show (priv->cc_caption);
2577 gtk_widget_hide (priv->cc_caption);
2579 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2583 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2586 ModestMsgEditWindowPrivate *priv = NULL;
2587 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2589 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2590 if (!priv->update_caption_visibility)
2593 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2595 gtk_widget_show (priv->bcc_caption);
2597 gtk_widget_hide (priv->bcc_caption);
2599 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2603 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2604 ModestRecptEditor *editor)
2606 ModestMsgEditWindowPrivate *priv;
2608 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2609 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2611 /* we check for low-mem; in that case, show a warning, and don't allow
2612 * for the addressbook
2614 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2617 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2619 if (editor == NULL) {
2620 GtkWidget *view_focus;
2621 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2623 /* This code should be kept in sync with ModestRecptEditor. The
2624 textview inside the recpt editor is the one that really gets the
2625 focus. As it's inside a scrolled window, and this one inside the
2626 hbox recpt editor inherits from, we'll need to go up in the
2627 hierarchy to know if the text view is part of the recpt editor
2628 or if it's a different text entry */
2630 if (gtk_widget_get_parent (view_focus)) {
2631 GtkWidget *first_parent;
2633 first_parent = gtk_widget_get_parent (view_focus);
2634 if (gtk_widget_get_parent (first_parent) &&
2635 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2636 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2641 editor = MODEST_RECPT_EDITOR (priv->to_field);
2645 modest_address_book_select_addresses (editor);
2650 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2652 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2654 modest_msg_edit_window_open_addressbook (window, NULL);
2658 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2659 gboolean show_toolbar)
2661 ModestWindowPrivate *parent_priv;
2663 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2664 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2666 /* We can not just use the code of
2667 modest_msg_edit_window_setup_toolbar because it has a
2668 mixture of both initialization and creation code. */
2670 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2672 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2676 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2677 TnyHeaderFlags priority_flags)
2679 ModestMsgEditWindowPrivate *priv;
2680 ModestWindowPrivate *parent_priv;
2682 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2684 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2685 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2687 if (priv->priority_flags != priority_flags) {
2688 GtkAction *priority_action = NULL;
2690 priv->priority_flags = priority_flags;
2692 switch (priority_flags) {
2693 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2694 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2695 MODEST_HEADER_ICON_HIGH,
2696 HILDON_ICON_SIZE_XSMALL);
2697 gtk_widget_show (priv->priority_icon);
2698 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2699 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2701 case TNY_HEADER_FLAG_LOW_PRIORITY:
2702 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2703 MODEST_HEADER_ICON_LOW,
2704 HILDON_ICON_SIZE_XSMALL);
2705 gtk_widget_show (priv->priority_icon);
2706 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2707 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2710 gtk_widget_hide (priv->priority_icon);
2711 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2712 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2715 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2716 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2721 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2724 ModestMsgEditWindowPrivate *priv;
2725 ModestWindowPrivate *parent_priv;
2726 gint current_format;
2728 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2730 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2731 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2733 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2734 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2736 if (current_format != file_format) {
2737 switch (file_format) {
2738 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2739 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2740 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
2742 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2746 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2747 response = gtk_dialog_run (GTK_DIALOG (dialog));
2748 gtk_widget_destroy (dialog);
2749 if (response == GTK_RESPONSE_OK) {
2750 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2752 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
2753 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
2758 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2759 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2760 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2765 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2768 ModestMsgEditWindowPrivate *priv;
2769 WPTextBufferFormat oldfmt, fmt;
2770 gint old_position = 0;
2774 GdkColor *color = NULL;
2775 gboolean bold, bold_set, italic, italic_set;
2776 gboolean underline, underline_set;
2777 gboolean strikethrough, strikethrough_set;
2778 gboolean position_set;
2779 gboolean font_size_set, font_set, color_set;
2782 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2783 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2785 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2786 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
2787 GTK_WINDOW(dialog), GTK_WINDOW (window));
2789 /* First we get the currently selected font information */
2790 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2792 switch (oldfmt.text_position) {
2793 case TEXT_POSITION_NORMAL:
2796 case TEXT_POSITION_SUPERSCRIPT:
2804 g_object_set (G_OBJECT (dialog),
2805 "bold", oldfmt.bold != FALSE,
2806 "bold-set", !oldfmt.cs.bold,
2807 "underline", oldfmt.underline != FALSE,
2808 "underline-set", !oldfmt.cs.underline,
2809 "italic", oldfmt.italic != FALSE,
2810 "italic-set", !oldfmt.cs.italic,
2811 "strikethrough", oldfmt.strikethrough != FALSE,
2812 "strikethrough-set", !oldfmt.cs.strikethrough,
2813 "color", &oldfmt.color,
2814 "color-set", !oldfmt.cs.color,
2815 "size", wp_font_size[oldfmt.font_size],
2816 "size-set", !oldfmt.cs.font_size,
2817 "position", old_position,
2818 "position-set", !oldfmt.cs.text_position,
2819 "family", wp_get_font_name (oldfmt.font),
2820 "family-set", !oldfmt.cs.font,
2823 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2824 GTK_WINDOW (dialog), GTK_WINDOW (window));
2825 gtk_widget_show_all (dialog);
2826 priv->font_dialog = dialog;
2827 response = gtk_dialog_run (GTK_DIALOG (dialog));
2828 priv->font_dialog = NULL;
2829 if (response == GTK_RESPONSE_OK) {
2831 g_object_get( dialog,
2833 "bold-set", &bold_set,
2834 "underline", &underline,
2835 "underline-set", &underline_set,
2837 "italic-set", &italic_set,
2838 "strikethrough", &strikethrough,
2839 "strikethrough-set", &strikethrough_set,
2841 "color-set", &color_set,
2843 "size-set", &font_size_set,
2844 "family", &font_name,
2845 "family-set", &font_set,
2846 "position", &position,
2847 "position-set", &position_set,
2852 if (response == GTK_RESPONSE_OK) {
2853 memset(&fmt, 0, sizeof(fmt));
2859 fmt.italic = italic;
2860 fmt.cs.italic = TRUE;
2862 if (underline_set) {
2863 fmt.underline = underline;
2864 fmt.cs.underline = TRUE;
2866 if (strikethrough_set) {
2867 fmt.strikethrough = strikethrough;
2868 fmt.cs.strikethrough = TRUE;
2873 ? TEXT_POSITION_NORMAL
2874 : ( ( position == 1 )
2875 ? TEXT_POSITION_SUPERSCRIPT
2876 : TEXT_POSITION_SUBSCRIPT );
2877 fmt.cs.text_position = TRUE;
2878 fmt.font_size = oldfmt.font_size;
2882 fmt.cs.color = TRUE;
2885 fmt.font = wp_get_font_index(font_name,
2890 if (font_size_set) {
2891 fmt.cs.font_size = TRUE;
2892 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
2894 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2895 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2897 gtk_widget_destroy (dialog);
2899 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2903 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2905 ModestMsgEditWindowPrivate *priv;
2907 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2908 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2910 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2912 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2913 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2917 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
2919 ModestMsgEditWindowPrivate *priv;
2921 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2922 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2924 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
2926 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2927 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2932 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
2934 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2936 priv->can_undo = can_undo;
2940 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
2942 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2944 priv->can_redo = can_redo;
2948 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
2950 ModestMsgEditWindowPrivate *priv;
2951 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2952 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2954 return priv->can_undo;
2958 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
2960 ModestMsgEditWindowPrivate *priv;
2961 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2962 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2964 return priv->can_redo;
2969 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
2972 GtkTextIter match_start, match_end;
2974 if (image_id == NULL)
2977 gtk_text_buffer_get_start_iter (buffer, &iter);
2979 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
2980 GSList *tags = gtk_text_iter_get_tags (&match_start);
2982 for (node = tags; node != NULL; node = g_slist_next (node)) {
2983 GtkTextTag *tag = (GtkTextTag *) node->data;
2984 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
2985 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
2986 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
2988 offset = gtk_text_iter_get_offset (&match_start);
2989 gtk_text_buffer_delete (buffer, &match_start, &match_end);
2990 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
2994 gtk_text_iter_forward_char (&iter);
2999 message_is_empty (ModestMsgEditWindow *window)
3001 ModestMsgEditWindowPrivate *priv = NULL;
3003 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3004 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3006 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3007 * so we can ignore markup.
3009 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3012 count = gtk_text_buffer_get_char_count (buf);
3018 msg_body_focus (GtkWidget *focus,
3019 GdkEventFocus *event,
3023 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3024 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3025 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3030 recpt_field_changed (GtkTextBuffer *buffer,
3031 ModestMsgEditWindow *editor)
3033 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3034 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3038 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3040 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3041 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3045 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3048 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3049 GtkTextBuffer *buffer;
3051 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3052 gtk_text_buffer_set_modified (buffer, modified);
3053 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3054 gtk_text_buffer_set_modified (buffer, modified);
3055 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3056 gtk_text_buffer_set_modified (buffer, modified);
3057 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3061 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3063 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3064 const char *account_name;
3065 GtkTextBuffer *buffer;
3067 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3068 if (gtk_text_buffer_get_modified (buffer))
3070 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3071 if (gtk_text_buffer_get_modified (buffer))
3073 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3074 if (gtk_text_buffer_get_modified (buffer))
3076 if (gtk_text_buffer_get_modified (priv->text_buffer))
3078 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3079 if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3090 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3092 ModestMsgEditWindowPrivate *priv = NULL;
3094 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3095 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3097 /* check if there's no recipient added */
3098 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3099 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3100 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3101 /* no recipient contents, then select contacts */
3102 modest_msg_edit_window_open_addressbook (window, NULL);
3106 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3107 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3110 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3111 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3114 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3115 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3119 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3120 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3121 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3128 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3129 ModestMsgEditWindow *window)
3131 modest_msg_edit_window_offer_attach_file (window);
3135 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3137 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3139 return priv->clipboard_text;
3143 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3145 ModestMsgEditWindow *window)
3147 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3148 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3150 if (!GTK_WIDGET_VISIBLE (window))
3153 g_object_ref (window);
3154 text = gtk_clipboard_wait_for_text (selection_clipboard);
3156 if (priv->clipboard_text != NULL) {
3157 g_free (priv->clipboard_text);
3159 priv->clipboard_text = text;
3161 if (GTK_WIDGET_VISIBLE (window)) {
3162 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3164 g_object_unref (window);
3167 static gboolean clipboard_owner_change_idle (gpointer userdata)
3169 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3170 ModestMsgEditWindowPrivate *priv;
3172 gdk_threads_enter ();
3173 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3174 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3176 priv->clipboard_owner_idle = 0;
3177 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3178 gdk_threads_leave ();
3184 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3186 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3187 if (priv->clipboard_owner_idle == 0) {
3188 priv->clipboard_owner_idle = g_idle_add (clipboard_owner_change_idle, window);
3193 subject_field_move_cursor (GtkEntry *entry,
3194 GtkMovementStep step,
3199 if (!GTK_WIDGET_VISIBLE (window))
3202 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3206 update_window_title (ModestMsgEditWindow *window)
3208 ModestMsgEditWindowPrivate *priv = NULL;
3209 const gchar *subject;
3211 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3212 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3213 if (subject == NULL || subject[0] == '\0')
3214 subject = _("mail_va_new_email");
3216 gtk_window_set_title (GTK_WINDOW (window), subject);
3221 subject_field_changed (GtkEditable *editable,
3222 ModestMsgEditWindow *window)
3224 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3225 update_window_title (window);
3226 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3227 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3228 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3232 subject_field_insert_text (GtkEditable *editable,
3234 gint new_text_length,
3236 ModestMsgEditWindow *window)
3238 GString *result = g_string_new ("");
3240 gint result_len = 0;
3241 const gchar *entry_text = NULL;
3244 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3245 old_length = g_utf8_strlen (entry_text, -1);
3247 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3248 gunichar c = g_utf8_get_char_validated (current, 8);
3249 /* Invalid unichar, stop */
3255 result = g_string_append_unichar (result, c);
3259 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3260 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3263 /* Prevent endless recursion */
3264 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3265 g_signal_emit_by_name (editable, "insert-text",
3266 (gpointer) result->str, (gpointer) result->len,
3267 (gpointer) position, (gpointer) window);
3268 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3272 if (result_len + old_length > 1000) {
3273 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3274 dgettext("hildon-common-strings",
3275 "ckdg_ib_maximum_characters_reached"));
3278 g_string_free (result, TRUE);
3282 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3285 ModestMsgEditWindowPrivate *priv = NULL;
3287 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3288 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3290 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3293 gtk_widget_show_all (priv->find_toolbar);
3294 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3296 gtk_widget_hide_all (priv->find_toolbar);
3297 gtk_widget_grab_focus (priv->msg_body);
3303 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3305 GtkTextIter *match_start,
3306 GtkTextIter *match_end)
3308 GtkTextIter end_iter;
3309 gchar *str_casefold;
3312 gchar *range_casefold;
3315 gboolean result = FALSE;
3322 gtk_text_iter_forward_to_end (&end_iter);
3324 str_casefold = g_utf8_casefold (str, -1);
3325 str_chars_n = strlen (str);
3327 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3328 range_casefold = g_utf8_casefold (range_text, -1);
3329 range_chars_n = strlen (range_casefold);
3331 if (range_chars_n < str_chars_n) {
3332 g_free (str_casefold);
3333 g_free (range_text);
3334 g_free (range_casefold);
3338 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3339 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3340 if (!g_utf8_collate (range_subtext, str_casefold)) {
3341 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3343 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3344 match_start, match_end, NULL);
3345 g_free (found_text);
3347 g_free (range_subtext);
3351 g_free (str_casefold);
3352 g_free (range_text);
3353 g_free (range_casefold);
3360 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3361 ModestMsgEditWindow *window)
3363 gchar *current_search = NULL;
3364 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3366 GtkTextIter selection_start, selection_end;
3367 GtkTextIter match_start, match_end;
3368 gboolean continue_search = FALSE;
3370 if (message_is_empty (window)) {
3371 g_free (priv->last_search);
3372 priv->last_search = NULL;
3373 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3377 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3378 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3379 g_free (current_search);
3380 g_free (priv->last_search);
3381 priv->last_search = NULL;
3382 /* Information banner about empty search */
3383 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-common-strings", "ecdg_ib_find_rep_enter_text"));
3387 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3388 continue_search = TRUE;
3390 g_free (priv->last_search);
3391 priv->last_search = g_strdup (current_search);
3394 if (continue_search) {
3395 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3396 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3397 &match_start, &match_end);
3399 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_search_complete"));
3401 GtkTextIter buffer_start;
3402 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3403 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3404 &match_start, &match_end);
3406 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_no_matches"));
3409 /* Mark as selected the string found in search */
3411 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3412 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3413 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3415 g_free (priv->last_search);
3416 priv->last_search = NULL;
3418 g_free (current_search);
3422 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3423 ModestMsgEditWindow *window)
3425 ModestMsgEditWindowPrivate *priv;
3427 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3429 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->find_toolbar_button), FALSE);
3433 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3435 ModestMsgEditWindowPrivate *priv;
3437 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3442 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3445 ModestMsgEditWindowPrivate *priv;
3447 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3453 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3456 ModestMsgEditWindowPrivate *priv;
3457 TnyHeader *header = NULL;
3459 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3460 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3462 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3463 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3465 if (priv->draft_msg != NULL) {
3466 g_object_unref (priv->draft_msg);
3469 if (draft != NULL) {
3470 g_object_ref (draft);
3471 header = tny_msg_get_header (draft);
3472 if (priv->msg_uid) {
3473 g_free (priv->msg_uid);
3474 priv->msg_uid = NULL;
3476 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3477 if (GTK_WIDGET_REALIZED (window)) {
3478 if (!modest_window_mgr_register_window (mgr, MODEST_WINDOW (window), NULL)) {
3479 gtk_widget_destroy (GTK_WIDGET (window));
3485 priv->draft_msg = draft;
3489 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3490 GtkTextIter *start, GtkTextIter *end,
3493 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3494 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3497 if (tag == NULL) return;
3498 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3499 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3500 replace_with_images (window, priv->images);
3505 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3508 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3510 g_return_if_fail (TNY_IS_MIME_PART (part));
3511 tny_list_prepend (priv->attachments, (GObject *) part);
3512 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3513 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3514 gtk_widget_show_all (priv->attachments_caption);
3515 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3519 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3521 ModestMsgEditWindowPrivate *priv;
3523 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3524 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3526 return priv->msg_uid;
3530 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3531 ModestMsgEditWindowWidgetType widget_type)
3533 ModestMsgEditWindowPrivate *priv;
3535 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3536 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3538 switch (widget_type) {
3539 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3540 return priv->msg_body;
3542 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3543 return priv->to_field;
3545 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3546 return priv->cc_field;
3548 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3549 return priv->bcc_field;
3551 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3552 return priv->subject_field;
3554 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3555 return priv->attachments_view;
3563 remove_tags (WPTextBuffer *buffer)
3565 GtkTextIter start, end;
3567 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3568 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3570 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3574 on_account_removed (TnyAccountStore *account_store,
3575 TnyAccount *account,
3578 /* Do nothing if it's a store account, because we use the
3579 transport to send the messages */
3580 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3581 const gchar *parent_acc = NULL;
3582 const gchar *our_acc = NULL;
3584 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3585 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3586 /* Close this window if I'm showing a message of the removed account */
3587 if (strcmp (parent_acc, our_acc) == 0)
3588 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3592 typedef struct _MessageSettingsHelper {
3593 ModestMsgEditWindow *window;
3594 GSList *priority_group;
3595 GtkWidget *align_picker;
3596 } MessageSettingsHelper;
3599 on_priority_toggle (HildonCheckButton *button,
3600 MessageSettingsHelper *helper)
3603 ModestMsgEditWindowPrivate *priv;
3605 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3606 if (hildon_check_button_get_active (button)) {
3608 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3609 HildonCheckButton *node_button = (HildonCheckButton *) node->data;
3610 if ((node_button != button) &&
3611 hildon_check_button_get_active (node_button)) {
3612 hildon_check_button_set_active (node_button, FALSE);
3614 if (priv->priority_flags != (TnyHeaderFlags) g_object_get_data (G_OBJECT (button), "priority"))
3615 modest_msg_edit_window_set_priority_flags (helper->window,
3617 g_object_get_data (G_OBJECT (button),
3623 gboolean found = FALSE;
3624 /* If no one is active, activate it again */
3625 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3626 HildonCheckButton *node_button = (HildonCheckButton *) node->data;
3627 if (hildon_check_button_get_active (node_button)) {
3633 hildon_check_button_set_active (button, TRUE);
3639 on_format_picker_value_changed (HildonPickerButton *button,
3640 MessageSettingsHelper *helper)
3642 ModestMsgEditFormat new_format, old_format;
3645 switch (hildon_picker_button_get_active (button)) {
3647 new_format = MODEST_MSG_EDIT_FORMAT_HTML;
3648 file_format = MODEST_FILE_FORMAT_FORMATTED_TEXT;
3652 new_format = MODEST_MSG_EDIT_FORMAT_TEXT;
3653 file_format = MODEST_FILE_FORMAT_PLAIN_TEXT;
3657 old_format = modest_msg_edit_window_get_format (helper->window);
3658 if (new_format != old_format) {
3659 modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (helper->window), file_format);
3661 switch (modest_msg_edit_window_get_format (helper->window)) {
3662 case MODEST_MSG_EDIT_FORMAT_TEXT:
3663 hildon_picker_button_set_active (button, 0);
3664 gtk_widget_set_sensitive (helper->align_picker, FALSE);
3666 case MODEST_MSG_EDIT_FORMAT_HTML:
3668 hildon_picker_button_set_active (button, 1);
3669 gtk_widget_set_sensitive (helper->align_picker, TRUE);
3676 on_align_picker_value_changed (HildonPickerButton *button,
3677 MessageSettingsHelper *helper)
3679 GtkJustification new_justify;
3680 ModestMsgEditFormatState *format_state = NULL;
3682 switch (hildon_picker_button_get_active (button)) {
3684 new_justify = GTK_JUSTIFY_CENTER;
3687 new_justify = GTK_JUSTIFY_RIGHT;
3691 new_justify = GTK_JUSTIFY_LEFT;
3695 format_state = modest_msg_edit_window_get_format_state (helper->window);
3696 if (format_state->justification != new_justify)
3697 format_state->justification = new_justify;
3698 modest_msg_edit_window_set_format_state (helper->window, format_state);
3699 g_free (format_state);
3703 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
3707 GtkWidget *priority_hbox;
3708 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
3709 GtkWidget *captioned;
3710 GtkSizeGroup *title_sizegroup, *value_sizegroup;
3711 GtkWidget *format_picker;
3712 GtkWidget *format_selector;
3713 GtkWidget *align_selector;
3714 ModestMsgEditWindowPrivate *priv;
3715 MessageSettingsHelper helper = {0,};
3716 ModestMsgEditFormatState *format_state = NULL;
3718 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3719 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3720 helper.window = window;
3721 helper.priority_group = NULL;
3723 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3724 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3726 dialog = gtk_dialog_new ();
3727 vbox = gtk_vbox_new (FALSE, 0);
3728 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), vbox);
3729 gtk_widget_show (vbox);
3731 /* Priority toggles */
3732 priority_hbox = gtk_hbox_new (TRUE, 0);
3733 high_toggle = hildon_check_button_new (HILDON_SIZE_FINGER_HEIGHT);
3734 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
3735 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
3736 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
3737 medium_toggle = hildon_check_button_new (HILDON_SIZE_FINGER_HEIGHT);
3738 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
3739 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
3740 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
3741 low_toggle = hildon_check_button_new (HILDON_SIZE_FINGER_HEIGHT);
3742 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
3743 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
3744 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
3745 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, FALSE, FALSE, 0);
3746 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, FALSE, FALSE, 0);
3747 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, FALSE, FALSE, 0);
3748 gtk_widget_show_all (priority_hbox);
3749 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
3750 _("mcen_me_editor_message_priority"), priority_hbox);
3751 gtk_widget_show (captioned);
3752 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
3754 /* format selector */
3755 format_selector = hildon_touch_selector_new_text ();
3756 hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (format_selector), _("mcen_me_editor_plain_text"));
3757 hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (format_selector), _("mcen_me_editor_formatted_text"));
3758 format_picker = hildon_picker_button_new (MODEST_EDITABLE_SIZE,
3759 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL);
3760 hildon_picker_button_set_selector (HILDON_PICKER_BUTTON (format_picker), HILDON_TOUCH_SELECTOR (format_selector));
3761 modest_maemo_utils_set_hbutton_layout (title_sizegroup, value_sizegroup,
3762 _("mcen_me_editor_format"), format_picker);
3763 gtk_widget_show_all (format_picker);
3764 gtk_box_pack_start (GTK_BOX (vbox), format_picker, FALSE, FALSE, 0);
3766 /* alignment selector */
3767 align_selector = hildon_touch_selector_new_text ();
3768 hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (align_selector), _("mcen_me_editor_align_left"));
3769 hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (align_selector), _("mcen_me_editor_align_centred"));
3770 hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (align_selector), _("mcen_me_editor_align_right"));
3771 helper.align_picker = hildon_picker_button_new (MODEST_EDITABLE_SIZE,
3772 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL);
3773 hildon_picker_button_set_selector (HILDON_PICKER_BUTTON (helper.align_picker), HILDON_TOUCH_SELECTOR (align_selector));
3774 modest_maemo_utils_set_hbutton_layout (title_sizegroup, value_sizegroup,
3775 _("mcen_me_editor_align"), helper.align_picker);
3776 gtk_widget_show_all (helper.align_picker);
3777 gtk_box_pack_start (GTK_BOX (vbox), helper.align_picker, FALSE, FALSE, 0);
3779 g_object_unref (title_sizegroup);
3780 g_object_unref (value_sizegroup);
3781 gtk_window_set_title (GTK_WINDOW (dialog), _("TODO: Message settings"));
3783 /* Set current values */
3784 switch (priv->priority_flags) {
3785 case TNY_HEADER_FLAG_HIGH_PRIORITY:
3786 hildon_check_button_set_active (HILDON_CHECK_BUTTON (high_toggle), TRUE);
3788 case TNY_HEADER_FLAG_LOW_PRIORITY:
3789 hildon_check_button_set_active (HILDON_CHECK_BUTTON (low_toggle), TRUE);
3792 hildon_check_button_set_active (HILDON_CHECK_BUTTON (medium_toggle), TRUE);
3796 switch (modest_msg_edit_window_get_format (window)) {
3797 case MODEST_MSG_EDIT_FORMAT_TEXT:
3798 hildon_picker_button_set_active (HILDON_PICKER_BUTTON (format_picker), 0);
3799 gtk_widget_set_sensitive (helper.align_picker, FALSE);
3801 case MODEST_MSG_EDIT_FORMAT_HTML:
3803 hildon_picker_button_set_active (HILDON_PICKER_BUTTON (format_picker), 1);
3804 gtk_widget_set_sensitive (helper.align_picker, TRUE);
3808 format_state = modest_msg_edit_window_get_format_state (window);
3809 switch (format_state->justification) {
3810 case GTK_JUSTIFY_RIGHT:
3811 hildon_picker_button_set_active (HILDON_PICKER_BUTTON (helper.align_picker), 2);
3813 case GTK_JUSTIFY_CENTER:
3814 hildon_picker_button_set_active (HILDON_PICKER_BUTTON (helper.align_picker), 1);
3817 hildon_picker_button_set_active (HILDON_PICKER_BUTTON (helper.align_picker), 0);
3821 g_free (format_state);
3823 /* Signal connects */
3824 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3825 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3826 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3827 g_signal_connect (G_OBJECT (format_picker), "value-changed", G_CALLBACK (on_format_picker_value_changed), &helper);
3828 g_signal_connect (G_OBJECT (helper.align_picker), "value-changed",
3829 G_CALLBACK (on_align_picker_value_changed), &helper);
3831 gtk_dialog_run (GTK_DIALOG (dialog));
3833 /* Read new values */
3835 gtk_widget_destroy (dialog);
3836 g_slist_free (helper.priority_group);
3840 static void on_message_settings (GtkAction *action,
3841 ModestMsgEditWindow *window)
3843 modest_msg_edit_window_show_msg_settings_dialog (window);
3847 on_cc_button_toggled (HildonCheckButton *button,
3848 ModestMsgEditWindow *window)
3850 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
3852 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
3853 hildon_check_button_get_active (button));
3857 on_bcc_button_toggled (HildonCheckButton *button,
3858 ModestMsgEditWindow *window)
3860 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
3862 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
3863 hildon_check_button_get_active (button));
3867 on_find_toolbar_button_toggled (HildonCheckButton *button,
3868 ModestMsgEditWindow *window)
3870 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
3871 modest_msg_edit_window_toggle_find_toolbar (MODEST_MSG_EDIT_WINDOW (window),
3872 hildon_check_button_get_active (button));
3877 setup_menu (ModestMsgEditWindow *self)
3879 ModestMsgEditWindowPrivate *priv = NULL;
3881 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
3883 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3885 /* Settings menu buttons */
3886 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_checknames"),
3887 APP_MENU_CALLBACK (modest_ui_actions_on_check_names),
3889 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_undo"),
3890 APP_MENU_CALLBACK (modest_ui_actions_on_undo),
3891 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_undo));
3893 priv->cc_button = hildon_check_button_new (0);
3894 gtk_button_set_label (GTK_BUTTON (priv->cc_button), _("mcen_me_editor_showcc"));
3895 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button),
3897 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->cc_button),
3899 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
3900 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
3901 priv->bcc_button = hildon_check_button_new (0);
3902 gtk_button_set_label (GTK_BUTTON (priv->bcc_button), _("mcen_me_editor_showbcc"));
3903 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button),
3905 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->bcc_button),
3907 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
3908 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
3910 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_attach_inlineimage"),
3911 APP_MENU_CALLBACK (modest_ui_actions_on_insert_image),
3912 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_set_style));
3913 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_remove_attachments"),
3914 APP_MENU_CALLBACK (modest_ui_actions_on_remove_attachments),
3915 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
3916 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("TODO: Message settings..."),
3917 APP_MENU_CALLBACK (on_message_settings),
3919 priv->find_toolbar_button = hildon_check_button_new (0);
3920 gtk_button_set_label (GTK_BUTTON (priv->find_toolbar_button), _("mcen_me_viewer_find"));
3921 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->find_toolbar_button),
3923 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->find_toolbar_button),
3925 g_signal_connect (G_OBJECT (priv->find_toolbar_button), "toggled",
3926 G_CALLBACK (on_find_toolbar_button_toggled), (gpointer) self);