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 <modest-wp-text-view.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
91 #define ATTACHMENT_BUTTON_WIDTH 118
93 static gboolean is_wp_text_buffer_started = FALSE;
95 static void modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass);
96 static void modest_msg_edit_window_init (ModestMsgEditWindow *obj);
97 static void modest_msg_edit_window_finalize (GObject *obj);
99 static gboolean msg_body_focus (GtkWidget *focus, GdkEventFocus *event, gpointer userdata);
100 static void body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
101 static void recpt_field_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
103 static void text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window);
104 static void text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window);
105 static void text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window);
106 static void text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
107 GtkTextIter *start, GtkTextIter *end,
109 static void text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id);
110 static void subject_field_changed (GtkEditable *editable, ModestMsgEditWindow *window);
111 static void subject_field_insert_text (GtkEditable *editable,
113 gint new_text_length,
115 ModestMsgEditWindow *window);
116 static void modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
118 static void modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
120 static void modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
122 static void modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
124 static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
125 ModestRecptEditor *editor);
126 static void modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
127 ModestMsgEditWindow *window);
129 /* ModestWindow methods implementation */
130 static void modest_msg_edit_window_disconnect_signals (ModestWindow *window);
131 static void modest_msg_edit_window_show_toolbar (ModestWindow *window,
132 gboolean show_toolbar);
133 static void modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
135 ModestMsgEditWindow *window);
136 static void modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window);
137 static void subject_field_move_cursor (GtkEntry *entry,
138 GtkMovementStep step,
142 static void update_window_title (ModestMsgEditWindow *window);
145 static void modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
146 ModestMsgEditWindow *window);
147 static void modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
148 ModestMsgEditWindow *window);
149 static gboolean gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
151 GtkTextIter *match_start,
152 GtkTextIter *match_end);
154 static void remove_tags (WPTextBuffer *buffer);
156 static void on_account_removed (TnyAccountStore *account_store,
160 static void init_window (ModestMsgEditWindow *obj);
162 gboolean scroll_drag_timeout (gpointer userdata);
163 static void correct_scroll (ModestMsgEditWindow *w);
164 static void correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused);
165 static void text_buffer_end_user_action (GtkTextBuffer *buffer,
166 ModestMsgEditWindow *userdata);
167 static void text_buffer_mark_set (GtkTextBuffer *buffer,
170 ModestMsgEditWindow *userdata);
171 static void on_message_settings (GtkAction *action,
172 ModestMsgEditWindow *window);
173 static void setup_menu (ModestMsgEditWindow *self);
175 static void from_field_changed (HildonPickerButton *button,
176 ModestMsgEditWindow *self);
177 static void DEBUG_BUFFER (WPTextBuffer *buffer)
181 g_message ("BEGIN BUFFER OF SIZE %d", gtk_text_buffer_get_char_count (GTK_TEXT_BUFFER (buffer)));
183 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &iter);
184 while (!gtk_text_iter_is_end (&iter)) {
185 GString *output = g_string_new ("");
186 GSList *toggled_tags;
189 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
190 g_string_append_printf (output, "%d: CLOSED [ ", gtk_text_iter_get_offset (&iter));
191 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
192 GtkTextTag *tag = (GtkTextTag *) node->data;
194 g_object_get (G_OBJECT (tag), "name", &name, NULL);
195 output = g_string_append (output, name);
196 g_string_append (output, " ");
198 output = g_string_append (output, "] OPENED [ ");
199 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
200 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
201 GtkTextTag *tag = (GtkTextTag *) node->data;
203 g_object_get (G_OBJECT (tag), "name", &name, NULL);
204 output = g_string_append (output, name);
205 g_string_append (output, " ");
207 output = g_string_append (output, "]\n");
208 g_message ("%s", output->str);
209 g_string_free (output, TRUE);
210 gtk_text_iter_forward_to_tag_toggle (&iter, NULL);
212 g_message ("END BUFFER");
216 static const GtkActionEntry hildon2_msg_edit_action_entries [] = {
217 { "MessageSettings", NULL, N_("mcen_me_message_settings"), NULL, NULL, G_CALLBACK (on_message_settings)},
221 /* static gboolean */
222 /* on_key_pressed (GtkWidget *self, */
223 /* GdkEventKey *event, */
224 /* gpointer user_data); */
226 /* list my signals */
233 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
234 struct _ModestMsgEditWindowPrivate {
236 GtkWidget *header_box;
238 ModestPairList *from_field_protos;
239 GtkWidget *from_field;
240 gchar *last_from_account;
241 gchar *original_account_name;
245 GtkWidget *bcc_field;
246 GtkWidget *subject_field;
247 GtkWidget *attachments_view;
248 GtkWidget *priority_icon;
249 GtkWidget *subject_box;
250 GtkWidget *add_attachment_button;
252 GtkWidget *cc_caption;
253 GtkWidget *bcc_caption;
254 gboolean update_caption_visibility;
255 GtkWidget *attachments_caption;
257 GtkTextBuffer *text_buffer;
259 GtkWidget *font_size_toolitem;
260 GtkWidget *font_face_toolitem;
261 GtkWidget *font_color_button;
262 GtkWidget *font_color_toolitem;
263 GSList *font_items_group;
264 GtkWidget *font_tool_button_label;
265 GSList *size_items_group;
266 GtkWidget *size_tool_button_label;
268 GtkWidget *find_toolbar;
271 GtkWidget *font_dialog;
274 guint correct_scroll_idle;
275 guint scroll_drag_timeout_id;
279 TnyList *attachments;
284 TnyHeaderFlags priority_flags;
286 gboolean can_undo, can_redo;
287 gulong clipboard_change_handler_id;
288 gulong default_clipboard_change_handler_id;
289 gulong account_removed_handler_id;
290 guint clipboard_owner_idle;
291 gchar *clipboard_text;
300 GtkWidget *cc_button;
301 GtkWidget *bcc_button;
304 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
305 MODEST_TYPE_MSG_EDIT_WINDOW, \
306 ModestMsgEditWindowPrivate))
308 static GtkWindowClass *parent_class = NULL;
310 /* uncomment the following if you have defined any signals */
311 /* static guint signals[LAST_SIGNAL] = {0}; */
314 modest_msg_edit_window_get_type (void)
316 static GType my_type = 0;
318 static const GTypeInfo my_info = {
319 sizeof(ModestMsgEditWindowClass),
320 NULL, /* base init */
321 NULL, /* base finalize */
322 (GClassInitFunc) modest_msg_edit_window_class_init,
323 NULL, /* class finalize */
324 NULL, /* class data */
325 sizeof(ModestMsgEditWindow),
327 (GInstanceInitFunc) modest_msg_edit_window_init,
330 my_type = g_type_register_static (MODEST_TYPE_HILDON2_WINDOW,
331 "ModestMsgEditWindow",
339 save_state (ModestWindow *self)
341 modest_widget_memory_save (modest_runtime_get_conf(),
342 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
347 restore_settings (ModestMsgEditWindow *self)
349 ModestConf *conf = NULL;
351 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
353 conf = modest_runtime_get_conf ();
355 /* Dim at start clipboard actions */
356 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
357 gtk_action_set_sensitive (action, FALSE);
358 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
359 gtk_action_set_sensitive (action, FALSE);
360 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
361 gtk_action_set_sensitive (action, FALSE);
363 modest_widget_memory_restore (conf, G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
368 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
370 GObjectClass *gobject_class;
371 ModestWindowClass *modest_window_class;
372 gobject_class = (GObjectClass*) klass;
373 modest_window_class = (ModestWindowClass*) klass;
375 parent_class = g_type_class_peek_parent (klass);
376 gobject_class->finalize = modest_msg_edit_window_finalize;
378 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
379 modest_window_class->save_state_func = save_state;
380 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
382 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
386 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
388 ModestMsgEditWindowPrivate *priv;
389 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
391 priv->msg_body = NULL;
392 priv->from_field = NULL;
393 priv->to_field = NULL;
394 priv->cc_field = NULL;
395 priv->bcc_field = NULL;
396 priv->subject_field = NULL;
397 priv->attachments = TNY_LIST (tny_simple_list_new ());
398 priv->images = TNY_LIST (tny_simple_list_new ());
399 priv->images_size = 0;
400 priv->images_count = 0;
403 priv->cc_caption = NULL;
404 priv->bcc_caption = NULL;
405 priv->update_caption_visibility = FALSE;
407 priv->priority_flags = 0;
409 priv->find_toolbar = NULL;
410 priv->last_search = NULL;
412 priv->draft_msg = NULL;
413 priv->outbox_msg = NULL;
414 priv->msg_uid = NULL;
416 priv->can_undo = FALSE;
417 priv->can_redo = FALSE;
418 priv->clipboard_change_handler_id = 0;
419 priv->default_clipboard_change_handler_id = 0;
420 priv->account_removed_handler_id = 0;
421 priv->clipboard_owner_idle = 0;
422 priv->clipboard_text = NULL;
425 priv->scroll_drag_timeout_id = 0;
426 priv->correct_scroll_idle = 0;
427 priv->last_upper = 0.0;
429 priv->font_dialog = NULL;
430 priv->app_menu = NULL;
432 if (!is_wp_text_buffer_started) {
433 is_wp_text_buffer_started = TRUE;
434 wp_text_buffer_library_init ();
439 hildon_program_add_window (hildon_program_get_instance(),
445 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
447 static ModestPairList*
448 get_transports (void)
450 GSList *transports = NULL;
452 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
453 GSList *accounts = modest_account_mgr_account_names (account_mgr,
454 TRUE /* only enabled accounts. */);
456 GSList *cursor = accounts;
458 gchar *account_name = cursor->data;
459 gchar *from_string = NULL;
461 from_string = modest_account_mgr_get_from_string (account_mgr,
465 if (from_string && account_name) {
466 gchar *name = account_name;
467 ModestPair *pair = modest_pair_new ((gpointer) name,
468 (gpointer) from_string , TRUE);
469 transports = g_slist_prepend (transports, pair);
472 cursor = cursor->next;
474 g_slist_free (accounts); /* only free the accounts, not the elements,
475 * because they are used in the pairlist */
479 static void window_focus (GtkWindow *window,
483 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
487 scroll_drag_timeout (gpointer userdata)
489 ModestMsgEditWindow *win = (ModestMsgEditWindow *) userdata;
490 ModestMsgEditWindowPrivate *priv;
492 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(win);
494 correct_scroll_without_drag_check (win, TRUE);
496 priv->scroll_drag_timeout_id = 0;
502 correct_scroll_without_drag_check_idle (gpointer userdata)
504 ModestMsgEditWindow *w = (ModestMsgEditWindow *) userdata;
505 ModestMsgEditWindowPrivate *priv;
507 GdkRectangle rectangle;
508 gint offset_min, offset_max;
512 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
514 insert = gtk_text_buffer_get_insert (priv->text_buffer);
515 gtk_text_buffer_get_iter_at_mark (priv->text_buffer, &iter, insert);
517 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &iter, &rectangle);
518 offset_min = priv->msg_body->allocation.y + rectangle.y;
519 offset_max = offset_min + rectangle.height;
521 vadj = hildon_pannable_area_get_vadjustment (HILDON_PANNABLE_AREA (priv->pannable));
522 offset_min = MAX (offset_min - 48, 0);
523 offset_max = MIN (offset_max + 48, vadj->upper);
525 gtk_adjustment_clamp_page (vadj, (gdouble) offset_min, (gdouble) offset_max);
527 priv->correct_scroll_idle = 0;
532 correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused)
534 ModestMsgEditWindowPrivate *priv;
536 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
538 if (only_if_focused && !gtk_widget_is_focus (priv->msg_body))
541 if (priv->correct_scroll_idle > 0) {
545 priv->correct_scroll_idle = g_idle_add ((GSourceFunc) correct_scroll_without_drag_check_idle,
550 correct_scroll (ModestMsgEditWindow *w)
552 ModestMsgEditWindowPrivate *priv;
554 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
555 if (gtk_grab_get_current () == priv->msg_body) {
556 if (priv->scroll_drag_timeout_id == 0) {
557 priv->scroll_drag_timeout_id = g_timeout_add (500, (GSourceFunc) scroll_drag_timeout,
563 correct_scroll_without_drag_check (w, TRUE);
567 text_buffer_end_user_action (GtkTextBuffer *buffer,
568 ModestMsgEditWindow *userdata)
571 correct_scroll (userdata);
575 text_buffer_mark_set (GtkTextBuffer *buffer,
578 ModestMsgEditWindow *userdata)
580 gtk_text_buffer_begin_user_action (buffer);
581 gtk_text_buffer_end_user_action (buffer);
585 cut_clipboard_check (GtkTextView *text_view,
588 GtkTextBuffer *buffer;
590 buffer = gtk_text_view_get_buffer (text_view);
591 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
592 g_signal_stop_emission_by_name ((gpointer )text_view, "cut-clipboard");
597 copy_clipboard_check (GtkTextView *text_view,
600 GtkTextBuffer *buffer;
602 buffer = gtk_text_view_get_buffer (text_view);
603 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
604 g_signal_stop_emission_by_name ((gpointer )text_view, "copy-clipboard");
609 attachment_deleted (ModestAttachmentsView *attachments_view,
612 modest_msg_edit_window_remove_attachments (MODEST_MSG_EDIT_WINDOW (user_data),
617 connect_signals (ModestMsgEditWindow *obj)
619 ModestMsgEditWindowPrivate *priv;
621 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
623 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
624 G_CALLBACK (text_buffer_refresh_attributes), obj);
625 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
626 G_CALLBACK (text_buffer_can_undo), obj);
627 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
628 G_CALLBACK (text_buffer_can_redo), obj);
629 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
630 G_CALLBACK (body_changed), obj);
631 g_signal_connect (G_OBJECT (priv->text_buffer), "modified-changed",
632 G_CALLBACK (body_changed), obj);
633 g_signal_connect (G_OBJECT (priv->text_buffer), "end-user-action",
634 G_CALLBACK (text_buffer_end_user_action), obj);
635 g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
636 G_CALLBACK (text_buffer_mark_set), obj);
637 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
638 G_CALLBACK (text_buffer_apply_tag), obj);
639 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
640 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
641 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
642 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
643 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
644 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
646 g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
647 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
648 g_signal_connect (G_OBJECT (priv->from_field), "value-changed",
649 G_CALLBACK (from_field_changed), obj);
651 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
652 G_CALLBACK (msg_body_focus), obj);
653 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
654 G_CALLBACK (msg_body_focus), obj);
655 g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
656 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
657 "changed", G_CALLBACK (recpt_field_changed), obj);
658 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
659 "changed", G_CALLBACK (recpt_field_changed), obj);
660 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
661 "changed", G_CALLBACK (recpt_field_changed), obj);
662 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
663 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
664 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
666 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
667 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
669 priv->clipboard_change_handler_id =
670 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
671 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
672 priv->default_clipboard_change_handler_id =
673 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
674 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
676 g_signal_connect (G_OBJECT (priv->msg_body), "cut-clipboard", G_CALLBACK (cut_clipboard_check), NULL);
677 g_signal_connect (G_OBJECT (priv->msg_body), "copy-clipboard", G_CALLBACK (copy_clipboard_check), NULL);
678 g_signal_connect (G_OBJECT (priv->attachments_view), "delete", G_CALLBACK (attachment_deleted), obj);
682 init_wp_text_view_style ()
684 static gboolean initialized = FALSE;
687 gtk_rc_parse_string ("class \"WPTextView\" style \"fremantle-textview\"");
693 init_window (ModestMsgEditWindow *obj)
695 GtkWidget *to_caption, *subject_caption;
696 GtkWidget *main_vbox;
697 GtkWidget *add_attachment_align;
698 ModestMsgEditWindowPrivate *priv;
699 GtkActionGroup *action_group;
700 ModestWindowPrivate *parent_priv;
701 GdkPixbuf *window_icon = NULL;
702 GError *error = NULL;
704 GtkSizeGroup *title_size_group;
705 GtkSizeGroup *value_size_group;
706 GtkWidget *attachment_icon;
707 GtkWidget *window_box;
708 GtkWidget *window_align;
709 #if (GTK_MINOR_VERSION >= 10)
710 GdkAtom deserialize_type;
713 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
714 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
716 parent_priv->ui_manager = gtk_ui_manager_new();
717 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
718 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
720 /* Add common actions */
721 gtk_action_group_add_actions (action_group,
722 modest_msg_edit_action_entries,
723 G_N_ELEMENTS (modest_msg_edit_action_entries),
725 gtk_action_group_add_actions (action_group,
726 hildon2_msg_edit_action_entries,
727 G_N_ELEMENTS (hildon2_msg_edit_action_entries),
729 gtk_action_group_add_toggle_actions (action_group,
730 modest_msg_edit_toggle_action_entries,
731 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
733 gtk_action_group_add_radio_actions (action_group,
734 modest_msg_edit_alignment_radio_action_entries,
735 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
737 G_CALLBACK (modest_ui_actions_on_change_justify),
739 gtk_action_group_add_radio_actions (action_group,
740 modest_msg_edit_priority_action_entries,
741 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
743 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
745 gtk_action_group_add_radio_actions (action_group,
746 modest_msg_edit_file_format_action_entries,
747 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
748 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
749 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
751 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
752 g_object_unref (action_group);
754 /* Load the UI definition */
755 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
758 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
759 g_clear_error (&error);
762 /* Add accelerators */
763 gtk_window_add_accel_group (GTK_WINDOW (obj),
764 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
766 parent_priv->menubar = NULL;
768 title_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
769 value_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
771 /* Note: This ModestPairList* must exist for as long as the picker
772 * that uses it, because the ModestSelectorPicker uses the ID opaquely,
773 * so it can't know how to manage its memory. */
774 priv->from_field = modest_selector_picker_new (MODEST_EDITABLE_SIZE,
775 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL,
777 modest_maemo_utils_set_hbutton_layout (title_size_group, value_size_group,
778 _("mail_va_from"), priv->from_field);
780 priv->to_field = modest_recpt_editor_new ();
781 priv->cc_field = modest_recpt_editor_new ();
782 priv->bcc_field = modest_recpt_editor_new ();
783 priv->subject_box = gtk_hbox_new (FALSE, MODEST_MARGIN_NONE);
784 priv->priority_icon = gtk_image_new ();
785 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->priority_icon, FALSE, FALSE, 0);
786 priv->subject_field = hildon_entry_new (MODEST_EDITABLE_SIZE);
787 gtk_entry_set_max_length (GTK_ENTRY (priv->subject_field) ,SUBJECT_MAX_LENGTH);
788 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
789 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
790 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
791 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->subject_field, TRUE, TRUE, 0);
792 priv->add_attachment_button = hildon_button_new (MODEST_EDITABLE_SIZE, HILDON_BUTTON_ARRANGEMENT_VERTICAL);
793 gtk_widget_set_size_request (priv->add_attachment_button, ATTACHMENT_BUTTON_WIDTH, -1);
794 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
795 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
796 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, HILDON_ICON_SIZE_FINGER);
797 hildon_button_set_image (HILDON_BUTTON (priv->add_attachment_button), attachment_icon);
798 add_attachment_align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
799 gtk_alignment_set_padding (GTK_ALIGNMENT (add_attachment_align), 0, 0, MODEST_MARGIN_DEFAULT, 0);
800 gtk_container_add (GTK_CONTAINER (add_attachment_align), priv->add_attachment_button);
801 gtk_box_pack_start (GTK_BOX (priv->subject_box), add_attachment_align, FALSE, FALSE, 0);
802 priv->attachments_view = modest_attachments_view_new (NULL);
803 modest_attachments_view_set_style (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
804 MODEST_ATTACHMENTS_VIEW_STYLE_NO_FOCUS);
806 priv->header_box = gtk_vbox_new (FALSE, 0);
808 to_caption = modest_maemo_utils_create_captioned_with_size_type
809 (title_size_group, value_size_group,
810 _("mail_va_to"), FALSE, priv->to_field,
811 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
812 priv->cc_caption = modest_maemo_utils_create_captioned_with_size_type
813 (title_size_group, value_size_group,
814 _("mail_va_cc"), FALSE, priv->cc_field,
815 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
816 priv->bcc_caption = modest_maemo_utils_create_captioned_with_size_type
817 (title_size_group, value_size_group,
818 _("mail_va_hotfix1"), FALSE, priv->bcc_field,
819 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
820 subject_caption = modest_maemo_utils_create_captioned (title_size_group, value_size_group,
821 _("mail_va_subject"), FALSE, priv->subject_box);
822 priv->attachments_caption = modest_maemo_utils_create_captioned_with_size_type (title_size_group, value_size_group,
823 _("mail_va_attachment"),
825 priv->attachments_view,
826 HILDON_SIZE_AUTO_WIDTH |
827 HILDON_SIZE_AUTO_HEIGHT);
828 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), value_size_group); */
829 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), value_size_group); */
830 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), value_size_group); */
831 g_object_unref (title_size_group);
832 g_object_unref (value_size_group);
834 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->from_field, FALSE, FALSE, 0);
835 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
836 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
837 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
838 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
839 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
840 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
842 init_wp_text_view_style ();
844 priv->msg_body = modest_wp_text_view_new ();
847 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
848 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
849 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
850 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
851 #if (GTK_MINOR_VERSION >= 10)
852 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
853 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
855 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
856 deserialize_type, TRUE);
858 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
860 priv->find_toolbar = hildon_find_toolbar_new (NULL);
861 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
863 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
865 priv->pannable = hildon_pannable_area_new ();
867 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
868 window_align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
869 gtk_alignment_set_padding (GTK_ALIGNMENT (window_align), 0, 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DEFAULT);
871 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
872 gtk_box_pack_start (GTK_BOX(main_vbox), priv->msg_body, TRUE, TRUE, 0);
873 gtk_container_add (GTK_CONTAINER (window_align), main_vbox);
875 hildon_pannable_area_add_with_viewport (HILDON_PANNABLE_AREA (priv->pannable), window_align);
876 gtk_container_set_focus_vadjustment (GTK_CONTAINER (main_vbox),
877 hildon_pannable_area_get_vadjustment (HILDON_PANNABLE_AREA (priv->pannable)));
878 gtk_widget_show_all (GTK_WIDGET(priv->pannable));
880 window_box = gtk_vbox_new (FALSE, 0);
881 gtk_container_add (GTK_CONTAINER(obj), window_box);
883 gtk_box_pack_start (GTK_BOX (window_box), priv->pannable, TRUE, TRUE, 0);
885 /* Set window icon */
886 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
888 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
889 g_object_unref (window_icon);
894 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
896 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
898 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
899 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
900 priv->clipboard_change_handler_id))
901 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
902 priv->clipboard_change_handler_id);
903 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
904 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
905 priv->default_clipboard_change_handler_id))
906 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
907 priv->default_clipboard_change_handler_id);
909 if (priv->account_removed_handler_id &&
910 g_signal_handler_is_connected (modest_runtime_get_account_store (),
911 priv->account_removed_handler_id))
912 g_signal_handler_disconnect(modest_runtime_get_account_store (),
913 priv->account_removed_handler_id);
917 modest_msg_edit_window_finalize (GObject *obj)
919 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
921 /* Sanity check: shouldn't be needed, the window mgr should
922 call this function before */
923 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
925 if (priv->font_dialog != NULL) {
926 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
929 if (priv->clipboard_text != NULL) {
930 g_free (priv->clipboard_text);
931 priv->clipboard_text = NULL;
934 if (priv->draft_msg != NULL) {
935 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
936 if (TNY_IS_HEADER (header)) {
937 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
938 modest_window_mgr_unregister_header (mgr, header);
940 g_object_unref (priv->draft_msg);
941 priv->draft_msg = NULL;
943 if (priv->outbox_msg != NULL) {
944 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
945 if (TNY_IS_HEADER (header)) {
946 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
947 modest_window_mgr_unregister_header (mgr, header);
949 g_object_unref (priv->outbox_msg);
950 priv->outbox_msg = NULL;
952 if (priv->correct_scroll_idle > 0) {
953 g_source_remove (priv->correct_scroll_idle);
954 priv->correct_scroll_idle = 0;
956 if (priv->scroll_drag_timeout_id > 0) {
957 g_source_remove (priv->scroll_drag_timeout_id);
958 priv->scroll_drag_timeout_id = 0;
960 if (priv->clipboard_owner_idle > 0) {
961 g_source_remove (priv->clipboard_owner_idle);
962 priv->clipboard_owner_idle = 0;
964 if (priv->original_account_name)
965 g_free (priv->original_account_name);
966 g_free (priv->msg_uid);
967 g_free (priv->last_search);
968 g_slist_free (priv->font_items_group);
969 g_slist_free (priv->size_items_group);
970 g_object_unref (priv->attachments);
971 g_object_unref (priv->images);
973 /* This had to stay alive for as long as the picker that used it: */
974 modest_pair_list_free (priv->from_field_protos);
976 G_OBJECT_CLASS(parent_class)->finalize (obj);
980 pixbuf_from_stream (TnyStream *stream, const gchar *mime_type, guint64 *stream_size)
982 GdkPixbufLoader *loader;
988 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
990 if (loader == NULL) {
996 tny_stream_reset (TNY_STREAM (stream));
997 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
998 GError *error = NULL;
999 unsigned char read_buffer[128];
1001 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
1003 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
1005 g_error_free (error);
1010 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1012 g_object_ref (pixbuf);
1013 gdk_pixbuf_loader_close (loader, NULL);
1014 g_object_unref (loader);
1019 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1020 GdkPixbuf *new_pixbuf;
1022 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1023 gdk_pixbuf_get_width (pixbuf);
1024 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1025 g_object_unref (pixbuf);
1026 pixbuf = new_pixbuf;
1030 *stream_size = size;
1036 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1038 ModestMsgEditWindowPrivate *priv;
1041 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1043 for (iter = tny_list_create_iterator (attachments);
1044 !tny_iterator_is_done (iter);
1045 tny_iterator_next (iter)) {
1046 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1047 const gchar *cid = tny_mime_part_get_content_id (part);
1048 const gchar *mime_type = tny_mime_part_get_content_type (part);
1049 if ((cid != NULL)&&(mime_type != NULL)) {
1050 guint64 stream_size;
1051 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1052 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
1055 g_object_unref (stream);
1057 if (pixbuf != NULL) {
1058 priv->images_count ++;
1059 priv->images_size += stream_size;
1060 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1061 g_object_unref (pixbuf);
1064 g_object_unref (part);
1066 g_object_unref (iter);
1070 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1072 TnyMimePart *parent = NULL;
1073 const gchar *content_type = NULL;
1074 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1076 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1078 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1079 parent = g_object_ref (msg);
1080 } else if (content_type && !g_strcasecmp (content_type, "multipart/mixed")) {
1081 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1084 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1085 iter = tny_list_create_iterator (parts);
1086 while (!tny_iterator_is_done (iter)) {
1088 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1089 content_type = tny_mime_part_get_content_type (part);
1090 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1094 g_object_unref (part);
1096 tny_iterator_next (iter);
1098 g_object_unref (iter);
1099 g_object_unref (parts);
1102 if (parent != NULL) {
1103 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1106 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1107 iter = tny_list_create_iterator (parts);
1108 while (!tny_iterator_is_done (iter)) {
1110 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1111 content_type = tny_mime_part_get_content_type (part);
1112 if (content_type && g_str_has_prefix (content_type, "image/")) {
1113 tny_list_prepend (priv->images, (GObject *) part);
1115 g_object_unref (part);
1116 tny_iterator_next (iter);
1118 g_object_unref (iter);
1119 g_object_unref (parts);
1120 g_object_unref (parent);
1125 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1128 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1130 for (iter = tny_list_create_iterator (attachments) ;
1131 !tny_iterator_is_done (iter);
1132 tny_iterator_next (iter)) {
1133 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1134 const gchar *cid = tny_mime_part_get_content_id (part);
1136 char *invalid = NULL;
1137 gint int_cid = strtol (cid, &invalid, 10);
1138 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1139 priv->next_cid = int_cid + 1;
1142 g_object_unref (part);
1144 g_object_unref (iter);
1148 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1151 gchar *to, *cc, *bcc, *subject;
1153 ModestMsgEditWindowPrivate *priv;
1154 ModestWindowPrivate *parent_priv;
1156 TnyHeaderFlags priority_flags;
1157 TnyFolder *msg_folder;
1158 gboolean is_html = FALSE;
1159 gboolean field_view_set;
1161 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1162 g_return_if_fail (TNY_IS_MSG (msg));
1164 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1165 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1167 header = tny_msg_get_header (msg);
1168 to = tny_header_dup_to (header);
1169 cc = tny_header_dup_cc (header);
1170 bcc = tny_header_dup_bcc (header);
1171 subject = tny_header_dup_subject (header);
1172 priority_flags = tny_header_get_priority (header);
1175 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
1177 field_view_set = TRUE;
1179 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
1180 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1181 gtk_widget_show (priv->cc_caption);
1182 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1183 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1184 gtk_widget_hide (priv->cc_caption);
1185 field_view_set = FALSE;
1187 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button), field_view_set);
1189 field_view_set = TRUE;
1191 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
1192 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1193 gtk_widget_show (priv->bcc_caption);
1194 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1195 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1196 gtk_widget_hide (priv->bcc_caption);
1197 field_view_set = FALSE;
1199 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button), field_view_set);
1203 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1204 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1207 update_window_title (self);
1209 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1210 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1212 if ((body == NULL)||(body[0] == '\0')) {
1214 body = modest_text_utils_convert_to_html ("");
1217 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1218 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1221 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1224 /* Add attachments to the view */
1225 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1226 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1227 if (tny_list_get_length (priv->attachments) == 0) {
1228 gtk_widget_hide (priv->attachments_caption);
1230 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1231 gtk_widget_show_all (priv->attachments_caption);
1233 get_related_images (self, msg);
1234 update_next_cid (self, priv->attachments);
1235 update_next_cid (self, priv->images);
1236 replace_with_images (self, priv->images);
1238 if (preserve_is_rich && !is_html) {
1239 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1240 /* Get the default format required from configuration */
1241 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1242 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1245 /* Set the default focus depending on having already a To: field or not */
1246 if ((!to)||(*to == '\0')) {
1247 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1249 gtk_widget_grab_focus (priv->msg_body);
1252 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1254 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1255 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1257 modest_msg_edit_window_set_modified (self, FALSE);
1259 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1260 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1261 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1262 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1264 if (priv->msg_uid) {
1265 g_free (priv->msg_uid);
1266 priv->msg_uid = NULL;
1269 /* we should set a reference to the incoming message if it is a draft */
1270 msg_folder = tny_msg_get_folder (msg);
1272 if (modest_tny_folder_is_local_folder (msg_folder)) {
1273 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1274 if (type == TNY_FOLDER_TYPE_INVALID)
1275 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1277 if (type == TNY_FOLDER_TYPE_DRAFTS)
1278 priv->draft_msg = g_object_ref(msg);
1279 if (type == TNY_FOLDER_TYPE_OUTBOX)
1280 priv->outbox_msg = g_object_ref(msg);
1281 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1283 g_object_unref (msg_folder);
1293 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
1296 GList *item_children, *node;
1297 GtkWidget *bin_child;
1299 bin_child = gtk_bin_get_child (GTK_BIN(item));
1301 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
1303 for (node = item_children; node != NULL; node = g_list_next (node)) {
1304 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
1305 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
1308 g_list_free (item_children);
1312 menu_tool_button_dont_expand (GtkMenuToolButton *item)
1315 GList *item_children, *node;
1317 box = gtk_bin_get_child (GTK_BIN (item));
1318 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
1319 item_children = gtk_container_get_children (GTK_CONTAINER (box));
1321 for (node = item_children; node != NULL; node = g_list_next (node)) {
1322 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
1323 if (GTK_IS_TOGGLE_BUTTON (node->data))
1324 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
1325 else if (GTK_IS_BUTTON (node->data))
1326 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
1328 g_list_free (item_children);
1333 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1335 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1336 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1337 GtkWidget *placeholder;
1338 GtkWidget *tool_item;
1343 GtkWidget *sizes_menu;
1344 GtkWidget *fonts_menu;
1345 GSList *radio_group = NULL;
1346 GSList *node = NULL;
1350 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1351 gtk_toolbar_set_show_arrow (GTK_TOOLBAR (parent_priv->toolbar), FALSE);
1352 gtk_toolbar_set_icon_size (GTK_TOOLBAR (parent_priv->toolbar), HILDON_ICON_SIZE_FINGER);
1353 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1355 /* Font color placeholder */
1356 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1357 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1360 priv->font_color_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1361 priv->font_color_button = hildon_color_button_new ();
1362 gtk_widget_set_size_request (priv->font_color_button, -1, 48);
1363 GTK_WIDGET_UNSET_FLAGS (priv->font_color_toolitem, GTK_CAN_FOCUS);
1364 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1365 gtk_container_add (GTK_CONTAINER (priv->font_color_toolitem), priv->font_color_button);
1366 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1367 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1368 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->font_color_toolitem), insert_index);
1369 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1371 G_CALLBACK (modest_msg_edit_window_color_button_change),
1374 /* Font size and face placeholder */
1375 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1376 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1378 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1379 priv->size_tool_button_label = gtk_label_new (NULL);
1380 hildon_helper_set_logical_color (GTK_WIDGET (priv->size_tool_button_label), GTK_RC_TEXT,
1381 GTK_STATE_INSENSITIVE, "SecondaryTextColor");
1382 hildon_helper_set_logical_color (GTK_WIDGET (priv->size_tool_button_label), GTK_RC_FG,
1383 GTK_STATE_INSENSITIVE, "SecondaryTextColor");
1384 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1385 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1386 size_text,"</span>", NULL);
1387 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1389 hildon_helper_set_logical_font (priv->size_tool_button_label, "LargeSystemFont");
1390 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
1391 sizes_menu = gtk_menu_new ();
1392 priv->size_items_group = NULL;
1394 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1395 GtkWidget *size_menu_item;
1397 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1398 size_menu_item = gtk_radio_menu_item_new_with_label (radio_group, size_text);
1399 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (size_menu_item));
1400 gtk_menu_shell_append (GTK_MENU_SHELL (sizes_menu), size_menu_item);
1401 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (size_menu_item), (wp_font_size[size_index] == 12));
1402 gtk_widget_show (size_menu_item);
1404 priv->size_items_group = g_slist_prepend (priv->size_items_group, size_menu_item);
1408 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1409 GtkWidget *item = (GtkWidget *) node->data;
1410 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_size_change),
1414 priv->size_items_group = g_slist_reverse (priv->size_items_group);
1415 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), sizes_menu);
1416 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1417 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1418 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), FALSE);
1419 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), FALSE);
1420 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1421 priv->font_size_toolitem = tool_item;
1424 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1425 priv->font_tool_button_label = gtk_label_new (NULL);
1426 hildon_helper_set_logical_color (GTK_WIDGET (priv->font_tool_button_label), GTK_RC_TEXT,
1427 GTK_STATE_INSENSITIVE, "SecondaryTextColor");
1428 hildon_helper_set_logical_color (GTK_WIDGET (priv->font_tool_button_label), GTK_RC_FG,
1429 GTK_STATE_INSENSITIVE, "SecondaryTextColor");
1430 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1431 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1433 hildon_helper_set_logical_font (priv->font_tool_button_label, "LargeSystemFont");
1434 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
1435 fonts_menu = gtk_menu_new ();
1436 priv->font_items_group = NULL;
1438 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1439 GtkWidget *font_menu_item;
1440 GtkWidget *child_label;
1442 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
1443 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
1444 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
1445 wp_get_font_name (font_index), "</span>", NULL);
1446 gtk_label_set_markup (GTK_LABEL (child_label), markup);
1449 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
1450 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
1451 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
1452 gtk_widget_show (font_menu_item);
1454 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
1457 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1458 GtkWidget *item = (GtkWidget *) node->data;
1459 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
1462 priv->font_items_group = g_slist_reverse (priv->font_items_group);
1463 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
1464 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1465 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1466 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), FALSE);
1467 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), FALSE);
1468 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1469 priv->font_face_toolitem = tool_item;
1471 /* Set expand and homogeneous for remaining items */
1472 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
1473 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1474 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1475 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1476 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1477 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1478 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1479 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1480 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1482 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1483 will not show the tool items added to the placeholders) */
1484 gtk_widget_show_all (parent_priv->toolbar);
1486 /* Set the no show all *after* showing all items. We do not
1487 want the toolbar to be shown with a show all because it
1488 could go agains the gconf setting regarding showing or not
1489 the toolbar of the editor window */
1490 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1496 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, gboolean preserve_is_rich)
1499 ModestWindowPrivate *parent_priv;
1500 ModestMsgEditWindowPrivate *priv;
1501 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1502 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1503 ModestWindowMgr *mgr = NULL;
1505 g_return_val_if_fail (msg, NULL);
1506 g_return_val_if_fail (account_name, NULL);
1508 mgr = modest_runtime_get_window_mgr ();
1510 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1512 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1513 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1515 /* Menubar. Update the state of some toggles */
1516 priv->from_field_protos = get_transports ();
1517 modest_selector_picker_set_pair_list (MODEST_SELECTOR_PICKER (priv->from_field), priv->from_field_protos);
1518 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1519 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1520 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1522 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1523 hildon_touch_selector_get_current_text
1524 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1525 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1526 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1529 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1531 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1533 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1535 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1537 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1538 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1539 /* Add common dimming rules */
1540 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1541 modest_msg_edit_window_toolbar_dimming_entries,
1542 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1543 MODEST_WINDOW (obj));
1544 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_toolitem,
1545 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1546 MODEST_WINDOW (obj));
1547 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1548 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1549 MODEST_WINDOW (obj));
1550 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1551 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1552 MODEST_WINDOW (obj));
1553 /* Insert dimming rules group for this window */
1554 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1555 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1557 /* Setup app menu */
1558 setup_menu (MODEST_MSG_EDIT_WINDOW (obj));
1560 /* Checks the dimming rules */
1561 g_object_unref (toolbar_rules_group);
1562 g_object_unref (clipboard_rules_group);
1563 gtk_widget_hide (priv->priority_icon);
1564 gtk_widget_queue_resize (priv->subject_box);
1565 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1567 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1569 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1570 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1571 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1572 priv->update_caption_visibility = TRUE;
1574 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1576 /* Track account-removed signal, this window should be closed
1577 in the case we're creating a mail associated to the account
1579 priv->account_removed_handler_id =
1580 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1582 G_CALLBACK(on_account_removed),
1585 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1587 return (ModestWindow*) obj;
1591 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1593 GString **string_buffer = (GString **) user_data;
1595 *string_buffer = g_string_append (*string_buffer, buffer);
1601 * @result: A new string which should be freed with g_free().
1604 get_formatted_data (ModestMsgEditWindow *edit_window)
1606 ModestMsgEditWindowPrivate *priv;
1607 GString *string_buffer = g_string_new ("");
1609 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1611 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1613 modest_text_utils_hyperlinkify (string_buffer);
1615 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1617 return g_string_free (string_buffer, FALSE);
1622 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1625 const gchar *account_name;
1626 ModestMsgEditWindowPrivate *priv;
1627 TnyIterator *att_iter;
1629 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1631 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1633 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1634 g_return_val_if_fail (account_name, NULL);
1637 /* don't free these (except from) */
1638 data = g_slice_new0 (MsgData);
1639 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1641 data->account_name = g_strdup (account_name);
1642 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1643 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1644 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1645 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1646 if (priv->draft_msg) {
1647 data->draft_msg = g_object_ref (priv->draft_msg);
1648 } else if (priv->outbox_msg) {
1649 data->draft_msg = g_object_ref (priv->outbox_msg);
1651 data->draft_msg = NULL;
1654 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1656 gtk_text_buffer_get_bounds (buf, &b, &e);
1657 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1659 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1660 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1662 data->html_body = NULL;
1664 /* deep-copy the data */
1665 att_iter = tny_list_create_iterator (priv->attachments);
1666 data->attachments = NULL;
1667 while (!tny_iterator_is_done (att_iter)) {
1668 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1669 if (!(TNY_IS_MIME_PART(part))) {
1670 g_warning ("strange data in attachment list");
1671 g_object_unref (part);
1672 tny_iterator_next (att_iter);
1675 data->attachments = g_list_append (data->attachments,
1677 tny_iterator_next (att_iter);
1679 g_object_unref (att_iter);
1681 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1682 att_iter = tny_list_create_iterator (priv->images);
1683 data->images = NULL;
1684 while (!tny_iterator_is_done (att_iter)) {
1685 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1687 if (!(TNY_IS_MIME_PART(part))) {
1688 g_warning ("strange data in attachment list");
1689 g_object_unref (part);
1690 tny_iterator_next (att_iter);
1693 cid = tny_mime_part_get_content_id (part);
1695 gchar *image_tag_id;
1696 GtkTextTag *image_tag;
1698 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1699 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1700 g_free (image_tag_id);
1702 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1704 ((gtk_text_iter_has_tag (&iter, image_tag))||
1705 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1706 data->images = g_list_append (data->images,
1707 g_object_ref (part));
1709 g_object_unref (part);
1710 tny_iterator_next (att_iter);
1712 g_object_unref (att_iter);
1714 data->priority_flags = priv->priority_flags;
1721 unref_gobject (GObject *obj, gpointer data)
1723 if (!G_IS_OBJECT(obj))
1725 g_object_unref (obj);
1729 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1732 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1740 g_free (data->from);
1741 g_free (data->subject);
1742 g_free (data->plain_body);
1743 g_free (data->html_body);
1744 g_free (data->account_name);
1746 if (data->draft_msg != NULL) {
1747 g_object_unref (data->draft_msg);
1748 data->draft_msg = NULL;
1751 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1752 g_list_free (data->attachments);
1753 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1754 g_list_free (data->images);
1756 g_slice_free (MsgData, data);
1760 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1762 guint64 *parts_size)
1764 ModestMsgEditWindowPrivate *priv;
1766 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1768 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1770 /* TODO: add images */
1771 *parts_size += priv->images_size;
1772 *parts_count += priv->images_count;
1777 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1780 ModestMsgEditWindowPrivate *priv = NULL;
1781 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1783 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1785 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1787 return MODEST_MSG_EDIT_FORMAT_HTML;
1789 return MODEST_MSG_EDIT_FORMAT_TEXT;
1793 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1794 ModestMsgEditFormat format)
1796 ModestMsgEditWindowPrivate *priv;
1798 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1799 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1802 case MODEST_MSG_EDIT_FORMAT_HTML:
1803 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1805 case MODEST_MSG_EDIT_FORMAT_TEXT:
1806 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1809 g_return_if_reached ();
1813 ModestMsgEditFormatState *
1814 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1816 ModestMsgEditFormatState *format_state = NULL;
1817 ModestMsgEditWindowPrivate *priv;
1818 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1820 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1821 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1823 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1825 format_state = g_new0 (ModestMsgEditFormatState, 1);
1826 format_state->bold = buffer_format->bold&0x1;
1827 format_state->italics = buffer_format->italic&0x1;
1828 format_state->bullet = buffer_format->bullet&0x1;
1829 format_state->color = buffer_format->color;
1830 format_state->font_size = buffer_format->font_size;
1831 format_state->font_family = wp_get_font_name (buffer_format->font);
1832 format_state->justification = buffer_format->justification;
1833 g_free (buffer_format);
1835 return format_state;
1840 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1841 const ModestMsgEditFormatState *format_state)
1843 ModestMsgEditWindowPrivate *priv;
1844 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1845 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1846 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1847 g_return_if_fail (format_state != NULL);
1849 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1850 gtk_widget_grab_focus (priv->msg_body);
1851 buffer_format->bold = (format_state->bold != FALSE);
1852 buffer_format->italic = (format_state->italics != FALSE);
1853 buffer_format->color = format_state->color;
1854 buffer_format->font_size = format_state->font_size;
1855 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1856 buffer_format->justification = format_state->justification;
1857 buffer_format->bullet = format_state->bullet;
1859 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1861 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1862 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1863 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1864 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1865 buffer_format->cs.font = (buffer_format->font != current_format->font);
1866 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1867 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1869 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1870 if (buffer_format->cs.bold) {
1871 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
1872 GINT_TO_POINTER (buffer_format->bold&0x1));
1874 if (buffer_format->cs.italic) {
1875 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
1876 GINT_TO_POINTER (buffer_format->italic&0x1));
1878 if (buffer_format->cs.color) {
1879 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1880 GINT_TO_POINTER (&(buffer_format->color)));
1882 if (buffer_format->cs.font_size) {
1883 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1884 GINT_TO_POINTER (buffer_format->font_size));
1886 if (buffer_format->cs.justification) {
1887 switch (buffer_format->justification) {
1888 case GTK_JUSTIFY_LEFT:
1889 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
1890 GINT_TO_POINTER(TRUE));
1892 case GTK_JUSTIFY_CENTER:
1893 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
1894 GINT_TO_POINTER(TRUE));
1896 case GTK_JUSTIFY_RIGHT:
1897 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
1898 GINT_TO_POINTER(TRUE));
1905 if (buffer_format->cs.font) {
1906 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1907 GINT_TO_POINTER (buffer_format->font));
1909 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1910 if (buffer_format->cs.bullet) {
1911 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
1912 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
1914 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1916 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
1918 g_free (buffer_format);
1919 g_free (current_format);
1921 /* Check dimming rules */
1922 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1923 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1927 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1929 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1931 ModestWindowPrivate *parent_priv;
1932 ModestMsgEditWindowPrivate *priv;
1933 GtkWidget *new_size_menuitem;
1934 GtkWidget *new_font_menuitem;
1936 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1937 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1939 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1940 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu");
1941 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1942 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1944 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatPlainTextMenu");
1945 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1946 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1949 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1951 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1952 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1954 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1955 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1957 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
1958 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
1961 switch (buffer_format->justification)
1963 case GTK_JUSTIFY_LEFT:
1964 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
1966 case GTK_JUSTIFY_CENTER:
1967 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
1969 case GTK_JUSTIFY_RIGHT:
1970 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
1977 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
1979 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1980 G_CALLBACK (modest_msg_edit_window_color_button_change),
1982 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1983 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1984 G_CALLBACK (modest_msg_edit_window_color_button_change),
1987 new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group,
1988 buffer_format->font_size))->data);
1989 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1993 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1994 markup = g_strconcat ("<span font_family='Sans'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1995 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1997 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1998 G_CALLBACK (modest_msg_edit_window_size_change),
2000 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
2001 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
2002 G_CALLBACK (modest_msg_edit_window_size_change),
2006 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
2007 buffer_format->font))->data);
2008 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
2012 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
2013 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2014 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2016 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
2017 G_CALLBACK (modest_msg_edit_window_font_change),
2019 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
2020 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
2021 G_CALLBACK (modest_msg_edit_window_font_change),
2025 g_free (buffer_format);
2029 #ifdef MODEST_HILDON_VERSION_0
2031 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2034 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2035 ModestMsgEditWindowPrivate *priv;
2036 GtkWidget *dialog = NULL;
2038 GdkColor *new_color = NULL;
2040 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2041 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2043 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2044 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
2045 g_free (buffer_format);
2047 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2048 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2049 if (new_color != NULL) {
2050 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2051 (gpointer) new_color);
2054 gtk_widget_destroy (dialog);
2059 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2062 ModestMsgEditWindowPrivate *priv;
2063 GtkWidget *dialog = NULL;
2065 GdkColor *old_color = NULL;
2066 const GdkColor *new_color = NULL;
2068 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2069 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2071 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2072 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2074 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2075 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2076 if (new_color != NULL)
2077 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2079 gtk_widget_destroy (dialog);
2085 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2088 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2089 ModestMsgEditWindowPrivate *priv;
2090 GtkWidget *dialog = NULL;
2092 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2093 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2095 dialog = hildon_color_chooser_new ();
2096 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2097 g_free (buffer_format);
2099 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2101 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2102 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2105 gtk_widget_destroy (dialog);
2110 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2113 ModestMsgEditWindowPrivate *priv;
2114 GtkWidget *dialog = NULL;
2115 GdkColor *old_color = NULL;
2117 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2118 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2120 dialog = hildon_color_chooser_new ();
2121 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2123 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2125 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2126 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2128 gtk_widget_destroy (dialog);
2131 #endif /*!MODEST_HILDON_VERSION_0*/
2136 create_stream_for_uri (const gchar* uri)
2141 TnyStream *result = NULL;
2143 GnomeVFSHandle *handle = NULL;
2144 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2145 if (test == GNOME_VFS_OK) {
2146 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2147 /* Streams over OBEX (Bluetooth) are not seekable but
2148 * we expect them to be (we might need to read them
2149 * several times). So if this is a Bluetooth URI just
2150 * read the whole file into memory (this is not a fast
2151 * protocol so we can assume that these files are not
2152 * going to be very big) */
2153 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2154 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2155 TnyStream *memstream = tny_camel_mem_stream_new ();
2156 tny_stream_write_to_stream (vfssstream, memstream);
2157 g_object_unref (vfssstream);
2160 result = vfssstream;
2168 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2171 ModestMsgEditWindowPrivate *priv;
2172 GtkWidget *dialog = NULL;
2174 GSList *uris = NULL;
2175 GSList *uri_node = NULL;
2177 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2179 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2180 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2181 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2183 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2185 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2186 GTK_WINDOW (dialog), GTK_WINDOW (window));
2188 response = gtk_dialog_run (GTK_DIALOG (dialog));
2190 case GTK_RESPONSE_OK:
2191 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2196 gtk_widget_destroy (dialog);
2198 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2200 GnomeVFSHandle *handle = NULL;
2201 GnomeVFSResult result;
2202 GtkTextIter position;
2203 GtkTextMark *insert_mark;
2205 uri = (const gchar *) uri_node->data;
2206 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2207 if (result == GNOME_VFS_OK) {
2209 GnomeVFSFileInfo *info;
2210 gchar *filename, *basename, *escaped_filename;
2211 TnyMimePart *mime_part;
2213 const gchar *mime_type = NULL;
2214 GnomeVFSURI *vfs_uri;
2215 guint64 stream_size;
2217 gnome_vfs_close (handle);
2218 vfs_uri = gnome_vfs_uri_new (uri);
2220 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2221 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2222 g_free (escaped_filename);
2223 gnome_vfs_uri_unref (vfs_uri);
2224 info = gnome_vfs_file_info_new ();
2226 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2227 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2229 mime_type = gnome_vfs_file_info_get_mime_type (info);
2231 mime_part = tny_platform_factory_new_mime_part
2232 (modest_runtime_get_platform_factory ());
2234 TnyStream *stream = create_stream_for_uri (uri);
2236 if (stream == NULL) {
2238 modest_platform_information_banner (NULL, NULL,
2239 _FM("sfil_ib_opening_not_allowed"));
2241 g_object_unref (mime_part);
2242 gnome_vfs_file_info_unref (info);
2246 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2248 content_id = g_strdup_printf ("%d", priv->next_cid);
2249 tny_mime_part_set_content_id (mime_part, content_id);
2250 g_free (content_id);
2253 basename = g_path_get_basename (filename);
2254 tny_mime_part_set_filename (mime_part, basename);
2257 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
2259 if (pixbuf != NULL) {
2260 priv->images_size += stream_size;
2261 priv->images_count ++;
2262 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2263 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2264 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
2265 g_object_unref (pixbuf);
2268 tny_list_prepend (priv->images, (GObject *) mime_part);
2269 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2271 g_object_unref (mime_part);
2272 gnome_vfs_file_info_unref (info);
2281 on_attach_file_response (GtkDialog *dialog,
2285 GSList *uris = NULL;
2287 GnomeVFSFileSize total_size, allowed_size;
2288 ModestMsgEditWindow *window;
2289 ModestMsgEditWindowPrivate *priv;
2294 case GTK_RESPONSE_OK:
2295 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2301 window = MODEST_MSG_EDIT_WINDOW (user_data);
2302 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2304 /* allowed size is the maximum size - what's already there */
2305 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2306 &att_num, &att_size);
2307 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2310 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2312 const gchar *uri = (const gchar *) uri_node->data;
2315 modest_msg_edit_window_attach_file_one (window, uri, allowed_size);
2317 if (total_size > allowed_size) {
2318 g_warning ("%s: total size: %u",
2319 __FUNCTION__, (unsigned int)total_size);
2322 allowed_size -= total_size;
2324 g_slist_foreach (uris, (GFunc) g_free, NULL);
2325 g_slist_free (uris);
2327 gtk_widget_destroy (GTK_WIDGET (dialog));
2331 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2333 GtkWidget *dialog = NULL;
2334 ModestMsgEditWindowPrivate *priv;
2336 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2338 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2340 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2343 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window),
2344 GTK_FILE_CHOOSER_ACTION_OPEN);
2345 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2346 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2347 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2348 GTK_WINDOW (dialog), GTK_WINDOW (window));
2350 /* Connect to response & show */
2351 g_signal_connect (dialog, "response",
2352 G_CALLBACK (on_attach_file_response), window);
2353 gtk_widget_show (dialog);
2358 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2360 GnomeVFSFileSize allowed_size)
2363 GnomeVFSHandle *handle = NULL;
2364 ModestMsgEditWindowPrivate *priv;
2365 GnomeVFSResult result;
2366 GnomeVFSFileSize size = 0;
2367 g_return_val_if_fail (window, 0);
2368 g_return_val_if_fail (uri, 0);
2370 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2372 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2373 if (result == GNOME_VFS_OK) {
2374 TnyMimePart *mime_part;
2376 const gchar *mime_type = NULL;
2378 gchar *escaped_filename;
2381 GnomeVFSFileInfo *info;
2382 GnomeVFSURI *vfs_uri;
2384 gnome_vfs_close (handle);
2385 vfs_uri = gnome_vfs_uri_new (uri);
2388 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2389 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2390 g_free (escaped_filename);
2391 gnome_vfs_uri_unref (vfs_uri);
2393 info = gnome_vfs_file_info_new ();
2395 if (gnome_vfs_get_file_info (uri,
2397 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2399 mime_type = gnome_vfs_file_info_get_mime_type (info);
2400 mime_part = tny_platform_factory_new_mime_part
2401 (modest_runtime_get_platform_factory ());
2403 /* try to get the attachment's size; this may fail for weird
2404 * file systems, like obex, upnp... */
2405 if (allowed_size != 0 &&
2406 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2408 if (size > allowed_size) {
2409 modest_platform_information_banner (NULL, NULL,
2410 _FM("sfil_ib_opening_not_allowed"));
2414 g_warning ("%s: could not get attachment size", __FUNCTION__);
2416 stream = create_stream_for_uri (uri);
2418 if (stream == NULL) {
2420 modest_platform_information_banner (NULL, NULL, _FM("sfil_ib_opening_not_allowed"));
2422 g_object_unref (mime_part);
2423 gnome_vfs_file_info_unref (info);
2427 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2428 g_object_unref (stream);
2430 content_id = g_strdup_printf ("%d", priv->next_cid);
2431 tny_mime_part_set_content_id (mime_part, content_id);
2432 g_free (content_id);
2435 basename = g_path_get_basename (filename);
2436 tny_mime_part_set_filename (mime_part, basename);
2439 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2440 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2442 info->size == 0, info->size);
2443 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2444 gtk_widget_show_all (priv->attachments_caption);
2445 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2447 g_object_unref (mime_part);
2448 gnome_vfs_file_info_unref (info);
2455 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2458 ModestMsgEditWindowPrivate *priv;
2461 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2462 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2464 if (att_list == NULL) {
2465 att_list = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2466 if (!modest_maemo_utils_select_attachments (GTK_WINDOW (window), att_list, TRUE)) {
2467 g_object_unref (att_list);
2472 g_object_ref (att_list);
2475 if (tny_list_get_length (att_list) == 0) {
2476 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2478 gboolean dialog_response;
2479 gchar *message = NULL;
2480 gchar *filename = NULL;
2482 if (tny_list_get_length (att_list) == 1) {
2484 iter = tny_list_create_iterator (att_list);
2485 part = (TnyMimePart *) tny_iterator_get_current (iter);
2486 g_object_unref (iter);
2487 if (TNY_IS_MSG (part)) {
2488 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2490 filename = tny_header_dup_subject (header);
2491 g_object_unref (header);
2493 if (filename == NULL) {
2494 filename = g_strdup (_("mail_va_no_subject"));
2497 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2499 g_object_unref (part);
2501 filename = g_strdup ("");
2503 message = g_strdup_printf (ngettext("emev_nc_delete_attachment",
2504 "emev_nc_delete_attachments",
2505 tny_list_get_length (att_list)), filename);
2508 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
2512 if (dialog_response != GTK_RESPONSE_OK) {
2513 g_object_unref (att_list);
2517 for (iter = tny_list_create_iterator (att_list);
2518 !tny_iterator_is_done (iter);
2519 tny_iterator_next (iter)) {
2520 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2521 const gchar *att_id;
2522 tny_list_remove (priv->attachments, (GObject *) mime_part);
2524 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2526 if (tny_list_get_length (priv->attachments) == 0)
2527 gtk_widget_hide (priv->attachments_caption);
2528 att_id = tny_mime_part_get_content_id (mime_part);
2530 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2532 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2533 g_object_unref (mime_part);
2535 g_object_unref (iter);
2538 g_object_unref (att_list);
2540 /* if the last attachment has been removed, focus the Subject: field */
2541 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2542 gtk_widget_grab_focus (priv->subject_field);
2546 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2549 ModestMsgEditWindowPrivate *priv;
2550 GdkColor *new_color;
2551 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2553 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2554 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2557 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2559 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2561 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2563 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2568 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
2571 ModestMsgEditWindowPrivate *priv;
2572 gint new_size_index;
2573 ModestMsgEditWindow *window;
2576 window = MODEST_MSG_EDIT_WINDOW (userdata);
2577 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2578 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2580 if (gtk_check_menu_item_get_active (menu_item)) {
2582 WPTextBufferFormat format;
2584 memset (&format, 0, sizeof (format));
2585 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2587 label = gtk_bin_get_child (GTK_BIN (menu_item));
2589 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
2590 format.cs.font_size = TRUE;
2591 format.cs.text_position = TRUE;
2592 format.cs.font = TRUE;
2593 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
2594 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2596 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2597 GINT_TO_POINTER (wp_get_font_size_index (new_size_index, 12))))
2598 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2600 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2601 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
2602 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2608 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
2611 ModestMsgEditWindowPrivate *priv;
2612 gint new_font_index;
2613 ModestMsgEditWindow *window;
2616 window = MODEST_MSG_EDIT_WINDOW (userdata);
2617 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2618 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2620 if (gtk_check_menu_item_get_active (menu_item)) {
2623 label = gtk_bin_get_child (GTK_BIN (menu_item));
2625 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
2627 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2628 GINT_TO_POINTER(new_font_index)))
2629 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2631 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2632 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2633 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2639 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2642 ModestMsgEditWindowPrivate *priv = NULL;
2643 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2645 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2646 if (!priv->update_caption_visibility)
2649 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2651 gtk_widget_show (priv->cc_caption);
2653 gtk_widget_hide (priv->cc_caption);
2655 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2659 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2662 ModestMsgEditWindowPrivate *priv = NULL;
2663 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2665 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2666 if (!priv->update_caption_visibility)
2669 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2671 gtk_widget_show (priv->bcc_caption);
2673 gtk_widget_hide (priv->bcc_caption);
2675 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2679 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2680 ModestRecptEditor *editor)
2682 ModestMsgEditWindowPrivate *priv;
2684 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2685 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2687 /* we check for low-mem; in that case, show a warning, and don't allow
2688 * for the addressbook
2690 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2693 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2695 if (editor == NULL) {
2696 GtkWidget *view_focus;
2697 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2699 /* This code should be kept in sync with ModestRecptEditor. The
2700 textview inside the recpt editor is the one that really gets the
2701 focus. As it's inside a scrolled window, and this one inside the
2702 hbox recpt editor inherits from, we'll need to go up in the
2703 hierarchy to know if the text view is part of the recpt editor
2704 or if it's a different text entry */
2706 if (gtk_widget_get_parent (view_focus)) {
2707 GtkWidget *first_parent;
2709 first_parent = gtk_widget_get_parent (view_focus);
2710 if (gtk_widget_get_parent (first_parent) &&
2711 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2712 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2717 editor = MODEST_RECPT_EDITOR (priv->to_field);
2721 modest_address_book_select_addresses (editor);
2726 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2728 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2730 modest_msg_edit_window_open_addressbook (window, NULL);
2734 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2735 gboolean show_toolbar)
2737 ModestWindowPrivate *parent_priv;
2739 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2740 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2742 /* We can not just use the code of
2743 modest_msg_edit_window_setup_toolbar because it has a
2744 mixture of both initialization and creation code. */
2746 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2748 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2752 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2753 TnyHeaderFlags priority_flags)
2755 ModestMsgEditWindowPrivate *priv;
2756 ModestWindowPrivate *parent_priv;
2758 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2760 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2761 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2763 if (priv->priority_flags != priority_flags) {
2764 GtkAction *priority_action = NULL;
2766 priv->priority_flags = priority_flags;
2768 switch (priority_flags) {
2769 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2770 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2771 MODEST_HEADER_ICON_HIGH,
2772 HILDON_ICON_SIZE_SMALL);
2773 gtk_widget_show (priv->priority_icon);
2774 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2775 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2777 case TNY_HEADER_FLAG_LOW_PRIORITY:
2778 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2779 MODEST_HEADER_ICON_LOW,
2780 HILDON_ICON_SIZE_SMALL);
2781 gtk_widget_show (priv->priority_icon);
2782 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2783 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2786 gtk_widget_hide (priv->priority_icon);
2787 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2788 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2791 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2792 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2794 gtk_widget_queue_resize (priv->subject_box);
2798 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2801 ModestMsgEditWindowPrivate *priv;
2802 ModestWindowPrivate *parent_priv;
2803 gint current_format;
2805 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2807 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2808 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2810 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2811 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2813 if (current_format != file_format) {
2814 switch (file_format) {
2815 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2816 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2817 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
2819 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2823 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2824 response = gtk_dialog_run (GTK_DIALOG (dialog));
2825 gtk_widget_destroy (dialog);
2826 if (response == GTK_RESPONSE_OK) {
2827 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2829 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
2830 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
2835 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2836 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2837 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2842 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2845 ModestMsgEditWindowPrivate *priv;
2846 WPTextBufferFormat oldfmt, fmt;
2847 gint old_position = 0;
2851 GdkColor *color = NULL;
2852 gboolean bold, bold_set, italic, italic_set;
2853 gboolean underline, underline_set;
2854 gboolean strikethrough, strikethrough_set;
2855 gboolean position_set;
2856 gboolean font_size_set, font_set, color_set;
2859 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2860 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2862 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2863 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
2864 GTK_WINDOW(dialog), GTK_WINDOW (window));
2866 /* First we get the currently selected font information */
2867 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2869 switch (oldfmt.text_position) {
2870 case TEXT_POSITION_NORMAL:
2873 case TEXT_POSITION_SUPERSCRIPT:
2881 g_object_set (G_OBJECT (dialog),
2882 "bold", oldfmt.bold != FALSE,
2883 "bold-set", !oldfmt.cs.bold,
2884 "underline", oldfmt.underline != FALSE,
2885 "underline-set", !oldfmt.cs.underline,
2886 "italic", oldfmt.italic != FALSE,
2887 "italic-set", !oldfmt.cs.italic,
2888 "strikethrough", oldfmt.strikethrough != FALSE,
2889 "strikethrough-set", !oldfmt.cs.strikethrough,
2890 "color", &oldfmt.color,
2891 "color-set", !oldfmt.cs.color,
2892 "size", wp_font_size[oldfmt.font_size],
2893 "size-set", !oldfmt.cs.font_size,
2894 "position", old_position,
2895 "position-set", !oldfmt.cs.text_position,
2896 "family", wp_get_font_name (oldfmt.font),
2897 "family-set", !oldfmt.cs.font,
2900 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2901 GTK_WINDOW (dialog), GTK_WINDOW (window));
2902 gtk_widget_show_all (dialog);
2903 priv->font_dialog = dialog;
2904 response = gtk_dialog_run (GTK_DIALOG (dialog));
2905 priv->font_dialog = NULL;
2906 if (response == GTK_RESPONSE_OK) {
2908 g_object_get( dialog,
2910 "bold-set", &bold_set,
2911 "underline", &underline,
2912 "underline-set", &underline_set,
2914 "italic-set", &italic_set,
2915 "strikethrough", &strikethrough,
2916 "strikethrough-set", &strikethrough_set,
2918 "color-set", &color_set,
2920 "size-set", &font_size_set,
2921 "family", &font_name,
2922 "family-set", &font_set,
2923 "position", &position,
2924 "position-set", &position_set,
2929 if (response == GTK_RESPONSE_OK) {
2930 memset(&fmt, 0, sizeof(fmt));
2936 fmt.italic = italic;
2937 fmt.cs.italic = TRUE;
2939 if (underline_set) {
2940 fmt.underline = underline;
2941 fmt.cs.underline = TRUE;
2943 if (strikethrough_set) {
2944 fmt.strikethrough = strikethrough;
2945 fmt.cs.strikethrough = TRUE;
2950 ? TEXT_POSITION_NORMAL
2951 : ( ( position == 1 )
2952 ? TEXT_POSITION_SUPERSCRIPT
2953 : TEXT_POSITION_SUBSCRIPT );
2954 fmt.cs.text_position = TRUE;
2955 fmt.font_size = oldfmt.font_size;
2959 fmt.cs.color = TRUE;
2962 fmt.font = wp_get_font_index(font_name,
2967 if (font_size_set) {
2968 fmt.cs.font_size = TRUE;
2969 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
2971 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2972 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2974 gtk_widget_destroy (dialog);
2976 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2980 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2982 ModestMsgEditWindowPrivate *priv;
2984 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2985 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2987 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2989 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2990 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2994 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
2996 ModestMsgEditWindowPrivate *priv;
2998 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2999 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3001 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
3003 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3004 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3009 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
3011 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3013 priv->can_undo = can_undo;
3017 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
3019 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3021 priv->can_redo = can_redo;
3025 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3027 ModestMsgEditWindowPrivate *priv;
3028 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3029 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3031 return priv->can_undo;
3035 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3037 ModestMsgEditWindowPrivate *priv;
3038 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3039 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3041 return priv->can_redo;
3046 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3049 GtkTextIter match_start, match_end;
3051 if (image_id == NULL)
3054 gtk_text_buffer_get_start_iter (buffer, &iter);
3056 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3057 GSList *tags = gtk_text_iter_get_tags (&match_start);
3059 for (node = tags; node != NULL; node = g_slist_next (node)) {
3060 GtkTextTag *tag = (GtkTextTag *) node->data;
3061 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3062 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3063 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3065 offset = gtk_text_iter_get_offset (&match_start);
3066 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3067 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3071 gtk_text_iter_forward_char (&iter);
3076 message_is_empty (ModestMsgEditWindow *window)
3078 ModestMsgEditWindowPrivate *priv = NULL;
3080 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3081 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3083 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3084 * so we can ignore markup.
3086 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3089 count = gtk_text_buffer_get_char_count (buf);
3095 msg_body_focus (GtkWidget *focus,
3096 GdkEventFocus *event,
3100 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3101 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3102 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3107 recpt_field_changed (GtkTextBuffer *buffer,
3108 ModestMsgEditWindow *editor)
3110 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3111 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3115 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3117 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3118 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3122 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3125 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3126 GtkTextBuffer *buffer;
3128 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3129 gtk_text_buffer_set_modified (buffer, modified);
3130 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3131 gtk_text_buffer_set_modified (buffer, modified);
3132 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3133 gtk_text_buffer_set_modified (buffer, modified);
3134 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3138 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3140 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3141 const char *account_name;
3142 GtkTextBuffer *buffer;
3144 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3145 if (gtk_text_buffer_get_modified (buffer))
3147 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3148 if (gtk_text_buffer_get_modified (buffer))
3150 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3151 if (gtk_text_buffer_get_modified (buffer))
3153 if (gtk_text_buffer_get_modified (priv->text_buffer))
3155 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3156 if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3167 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3169 ModestMsgEditWindowPrivate *priv = NULL;
3171 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3172 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3174 /* check if there's no recipient added */
3175 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3176 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3177 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3178 /* no recipient contents, then select contacts */
3179 modest_msg_edit_window_open_addressbook (window, NULL);
3183 g_object_ref (window);
3184 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3185 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3186 g_object_unref (window);
3189 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3190 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3191 g_object_unref (window);
3194 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3195 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3196 g_object_unref (window);
3200 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3201 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3202 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3203 g_object_unref (window);
3210 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3211 ModestMsgEditWindow *window)
3213 modest_msg_edit_window_offer_attach_file (window);
3217 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3219 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3221 return priv->clipboard_text;
3225 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3227 ModestMsgEditWindow *window)
3229 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3230 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3232 if (!GTK_WIDGET_VISIBLE (window))
3235 g_object_ref (window);
3236 text = gtk_clipboard_wait_for_text (selection_clipboard);
3238 if (priv->clipboard_text != NULL) {
3239 g_free (priv->clipboard_text);
3241 priv->clipboard_text = text;
3243 if (GTK_WIDGET_VISIBLE (window)) {
3244 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3246 g_object_unref (window);
3249 static gboolean clipboard_owner_change_idle (gpointer userdata)
3251 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3252 ModestMsgEditWindowPrivate *priv;
3254 gdk_threads_enter ();
3255 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3256 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3258 priv->clipboard_owner_idle = 0;
3259 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3260 gdk_threads_leave ();
3266 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3268 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3269 if (priv->clipboard_owner_idle == 0) {
3270 priv->clipboard_owner_idle = g_idle_add (clipboard_owner_change_idle, window);
3275 subject_field_move_cursor (GtkEntry *entry,
3276 GtkMovementStep step,
3281 if (!GTK_WIDGET_VISIBLE (window))
3284 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3288 update_window_title (ModestMsgEditWindow *window)
3290 ModestMsgEditWindowPrivate *priv = NULL;
3291 const gchar *subject;
3293 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3294 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3295 if (subject == NULL || subject[0] == '\0')
3296 subject = _("mail_va_new_email");
3298 gtk_window_set_title (GTK_WINDOW (window), subject);
3303 subject_field_changed (GtkEditable *editable,
3304 ModestMsgEditWindow *window)
3306 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3307 update_window_title (window);
3308 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3309 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3310 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3314 subject_field_insert_text (GtkEditable *editable,
3316 gint new_text_length,
3318 ModestMsgEditWindow *window)
3320 GString *result = g_string_new ("");
3322 gint result_len = 0;
3323 const gchar *entry_text = NULL;
3326 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3327 old_length = g_utf8_strlen (entry_text, -1);
3329 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3330 gunichar c = g_utf8_get_char_validated (current, 8);
3331 /* Invalid unichar, stop */
3337 result = g_string_append_unichar (result, c);
3341 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3342 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3345 /* Prevent endless recursion */
3346 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3347 g_signal_emit_by_name (editable, "insert-text",
3348 (gpointer) result->str, (gpointer) result->len,
3349 (gpointer) position, (gpointer) window);
3350 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3354 if (result_len + old_length > 1000) {
3355 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3356 _CS("ckdg_ib_maximum_characters_reached"));
3358 g_string_free (result, TRUE);
3362 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3365 ModestMsgEditWindowPrivate *priv = NULL;
3367 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3368 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3370 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3373 gtk_widget_show_all (priv->find_toolbar);
3374 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3376 gtk_widget_hide_all (priv->find_toolbar);
3377 gtk_widget_grab_focus (priv->msg_body);
3382 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3384 GtkTextIter *match_start,
3385 GtkTextIter *match_end)
3387 GtkTextIter end_iter;
3388 gchar *str_casefold;
3391 gchar *range_casefold;
3394 gboolean result = FALSE;
3401 gtk_text_iter_forward_to_end (&end_iter);
3403 str_casefold = g_utf8_casefold (str, -1);
3404 str_chars_n = strlen (str);
3406 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3407 range_casefold = g_utf8_casefold (range_text, -1);
3408 range_chars_n = strlen (range_casefold);
3410 if (range_chars_n < str_chars_n) {
3411 g_free (str_casefold);
3412 g_free (range_text);
3413 g_free (range_casefold);
3417 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3418 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3419 if (!g_utf8_collate (range_subtext, str_casefold)) {
3420 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3422 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3423 match_start, match_end, NULL);
3424 g_free (found_text);
3426 g_free (range_subtext);
3430 g_free (str_casefold);
3431 g_free (range_text);
3432 g_free (range_casefold);
3439 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3440 ModestMsgEditWindow *window)
3442 gchar *current_search = NULL;
3443 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3445 GtkTextIter selection_start, selection_end;
3446 GtkTextIter match_start, match_end;
3447 gboolean continue_search = FALSE;
3449 if (message_is_empty (window)) {
3450 g_free (priv->last_search);
3451 priv->last_search = NULL;
3452 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3456 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3457 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3458 g_free (current_search);
3459 g_free (priv->last_search);
3460 priv->last_search = NULL;
3461 /* Information banner about empty search */
3462 hildon_banner_show_information (NULL, NULL, _CS("ecdg_ib_find_rep_enter_text"));
3466 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3467 continue_search = TRUE;
3469 g_free (priv->last_search);
3470 priv->last_search = g_strdup (current_search);
3473 if (continue_search) {
3474 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3475 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3476 &match_start, &match_end);
3478 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_search_complete"));
3480 GtkTextIter buffer_start;
3481 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3482 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3483 &match_start, &match_end);
3485 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_no_matches"));
3488 /* Mark as selected the string found in search */
3490 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3491 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3492 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3494 g_free (priv->last_search);
3495 priv->last_search = NULL;
3497 g_free (current_search);
3501 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3503 ModestMsgEditWindowPrivate *priv;
3505 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3510 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3513 ModestMsgEditWindowPrivate *priv;
3515 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3520 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3521 ModestMsgEditWindow *window)
3523 modest_msg_edit_window_toggle_find_toolbar (window, FALSE);
3527 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3530 ModestMsgEditWindowPrivate *priv;
3531 TnyHeader *header = NULL;
3533 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3534 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3536 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3537 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3539 if (priv->draft_msg != NULL) {
3540 g_object_unref (priv->draft_msg);
3543 if (draft != NULL) {
3544 g_object_ref (draft);
3545 header = tny_msg_get_header (draft);
3546 if (priv->msg_uid) {
3547 g_free (priv->msg_uid);
3548 priv->msg_uid = NULL;
3550 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3551 if (GTK_WIDGET_REALIZED (window)) {
3552 if (!modest_window_mgr_register_window (mgr, MODEST_WINDOW (window), NULL)) {
3553 gtk_widget_destroy (GTK_WIDGET (window));
3559 priv->draft_msg = draft;
3563 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3564 GtkTextIter *start, GtkTextIter *end,
3567 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3568 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3571 if (tag == NULL) return;
3572 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3573 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3574 replace_with_images (window, priv->images);
3579 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3582 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3584 g_return_if_fail (TNY_IS_MIME_PART (part));
3585 tny_list_prepend (priv->attachments, (GObject *) part);
3586 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3587 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3588 gtk_widget_show_all (priv->attachments_caption);
3589 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3593 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3595 ModestMsgEditWindowPrivate *priv;
3597 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3598 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3600 return priv->msg_uid;
3604 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3605 ModestMsgEditWindowWidgetType widget_type)
3607 ModestMsgEditWindowPrivate *priv;
3609 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3610 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3612 switch (widget_type) {
3613 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3614 return priv->msg_body;
3616 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3617 return priv->to_field;
3619 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3620 return priv->cc_field;
3622 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3623 return priv->bcc_field;
3625 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3626 return priv->subject_field;
3628 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3629 return priv->attachments_view;
3637 remove_tags (WPTextBuffer *buffer)
3639 GtkTextIter start, end;
3641 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3642 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3644 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3648 on_account_removed (TnyAccountStore *account_store,
3649 TnyAccount *account,
3652 /* Do nothing if it's a store account, because we use the
3653 transport to send the messages */
3654 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3655 const gchar *parent_acc = NULL;
3656 const gchar *our_acc = NULL;
3658 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3659 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3660 /* Close this window if I'm showing a message of the removed account */
3661 if (strcmp (parent_acc, our_acc) == 0)
3662 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3667 from_field_changed (HildonPickerButton *button,
3668 ModestMsgEditWindow *self)
3670 ModestMsgEditWindowPrivate *priv;
3671 gboolean has_old_signature, has_new_signature;
3673 GtkTextIter match_start, match_end;
3674 ModestAccountMgr *mgr;
3676 gchar *full_signature;
3678 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3680 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
3681 mgr = modest_runtime_get_account_mgr ();
3682 signature = modest_account_mgr_get_signature (mgr, priv->last_from_account, &has_old_signature);
3683 if (has_old_signature) {
3684 full_signature = g_strconcat ("\n--\n", signature, NULL);
3685 if (gtk_text_iter_forward_search (&iter, full_signature, 0, &match_start, &match_end, NULL)) {
3686 gtk_text_buffer_delete (priv->text_buffer, &match_start, &match_end);
3688 } else if (gtk_text_iter_forward_search (&iter, _("mcen_ia_editor_original_message"), 0,
3689 &match_start, &match_end, NULL)) {
3692 g_free (full_signature);
3696 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3697 signature = modest_account_mgr_get_signature (mgr, priv->last_from_account, &has_new_signature);
3698 if (has_new_signature) {
3699 full_signature = g_strconcat ("\n--\n", signature, NULL);
3700 gtk_text_buffer_insert (priv->text_buffer, &iter, full_signature, -1);
3701 g_free (full_signature);
3706 typedef struct _MessageSettingsHelper {
3707 ModestMsgEditWindow *window;
3708 GSList *priority_group;
3709 GSList *format_group;
3710 GtkToggleButton *current_priority;
3711 GtkToggleButton *current_format;
3712 } MessageSettingsHelper;
3715 on_priority_toggle (GtkToggleButton *button,
3716 MessageSettingsHelper *helper)
3719 ModestMsgEditWindowPrivate *priv;
3721 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3722 if (gtk_toggle_button_get_active (button)) {
3724 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3725 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3726 if ((node_button != button) &&
3727 gtk_toggle_button_get_active (node_button)) {
3728 gtk_toggle_button_set_active (node_button, FALSE);
3731 helper->current_priority = button;
3733 gboolean found = FALSE;
3734 /* If no one is active, activate it again */
3735 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3736 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3737 if (gtk_toggle_button_get_active (node_button)) {
3743 gtk_toggle_button_set_active (button, TRUE);
3749 on_format_toggle (GtkToggleButton *button,
3750 MessageSettingsHelper *helper)
3753 ModestMsgEditWindowPrivate *priv;
3755 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3756 if (gtk_toggle_button_get_active (button)) {
3758 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
3759 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3760 if ((node_button != button) &&
3761 gtk_toggle_button_get_active (node_button)) {
3762 gtk_toggle_button_set_active (node_button, FALSE);
3765 helper->current_format = button;
3767 gboolean found = FALSE;
3768 /* If no one is active, activate it again */
3769 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
3770 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3771 if (gtk_toggle_button_get_active (node_button)) {
3777 gtk_toggle_button_set_active (button, TRUE);
3784 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
3789 GtkWidget *priority_hbox;
3790 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
3791 GtkWidget *captioned;
3792 GtkSizeGroup *title_sizegroup, *value_sizegroup;
3793 GtkWidget *format_hbox;
3794 GtkWidget *html_toggle, *text_toggle;
3795 ModestMsgEditWindowPrivate *priv;
3796 MessageSettingsHelper helper = {0,};
3798 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3799 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3800 helper.window = window;
3801 helper.priority_group = NULL;
3802 helper.format_group = NULL;
3804 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3805 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3807 dialog = gtk_dialog_new_with_buttons (_("mcen_me_message_settings"), NULL,
3808 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
3809 _HL("wdgt_bd_done"), GTK_RESPONSE_ACCEPT, NULL);
3810 vbox = gtk_vbox_new (FALSE, 0);
3811 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
3812 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DOUBLE, 0);
3813 gtk_container_add (GTK_CONTAINER (align), vbox);
3814 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), align);
3815 gtk_widget_show (align);
3816 gtk_widget_show (vbox);
3818 /* Priority toggles */
3819 priority_hbox = gtk_hbox_new (TRUE, 0);
3820 high_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3821 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
3822 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
3823 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
3824 medium_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3825 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
3826 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
3827 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
3828 low_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3829 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
3830 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
3831 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
3832 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, TRUE, TRUE, 0);
3833 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, TRUE, TRUE, 0);
3834 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, TRUE, TRUE, 0);
3835 gtk_widget_show_all (priority_hbox);
3836 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
3837 _("mcen_me_editor_message_priority"), FALSE, priority_hbox);
3838 gtk_widget_show (captioned);
3839 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
3841 /* format toggles */
3842 format_hbox = gtk_hbox_new (TRUE, 0);
3843 html_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3844 gtk_button_set_label (GTK_BUTTON (html_toggle), _("mcen_me_editor_formatted_text"));
3845 helper.format_group = g_slist_prepend (helper.format_group, html_toggle);
3846 g_object_set_data (G_OBJECT (html_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_HTML));
3847 g_object_set_data (G_OBJECT (html_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_FORMATTED_TEXT));
3848 text_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3849 gtk_button_set_label (GTK_BUTTON (text_toggle), _("mcen_me_editor_plain_text"));
3850 helper.format_group = g_slist_prepend (helper.format_group, text_toggle);
3851 g_object_set_data (G_OBJECT (text_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_TEXT));
3852 g_object_set_data (G_OBJECT (text_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_PLAIN_TEXT));
3853 gtk_box_pack_start (GTK_BOX (format_hbox), html_toggle, TRUE, TRUE, 0);
3854 gtk_box_pack_start (GTK_BOX (format_hbox), text_toggle, TRUE, TRUE, 0);
3855 gtk_widget_show_all (format_hbox);
3856 gtk_widget_show (format_hbox);
3857 gtk_box_pack_start (GTK_BOX (vbox), format_hbox, FALSE, FALSE, 0);
3860 g_object_unref (title_sizegroup);
3861 g_object_unref (value_sizegroup);
3863 /* Set current values */
3864 switch (priv->priority_flags) {
3865 case TNY_HEADER_FLAG_HIGH_PRIORITY:
3866 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (high_toggle), TRUE);
3867 helper.current_priority = GTK_TOGGLE_BUTTON (high_toggle);
3869 case TNY_HEADER_FLAG_LOW_PRIORITY:
3870 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (low_toggle), TRUE);
3871 helper.current_priority = GTK_TOGGLE_BUTTON (low_toggle);
3874 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (medium_toggle), TRUE);
3875 helper.current_priority = GTK_TOGGLE_BUTTON (medium_toggle);
3879 switch (modest_msg_edit_window_get_format (window)) {
3880 case MODEST_MSG_EDIT_FORMAT_TEXT:
3881 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_toggle), TRUE);
3882 helper.current_format = GTK_TOGGLE_BUTTON (text_toggle);
3884 case MODEST_MSG_EDIT_FORMAT_HTML:
3886 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (html_toggle), TRUE);
3887 helper.current_format = GTK_TOGGLE_BUTTON (html_toggle);
3891 /* Signal connects */
3892 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3893 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3894 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3895 g_signal_connect (G_OBJECT (html_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
3896 g_signal_connect (G_OBJECT (text_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
3898 /* Save settings if the user clicked on done */
3899 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
3900 TnyHeaderFlags flags;
3901 ModestMsgEditFormat old_format, new_format;
3903 /* Set priority flags */
3904 flags = (TnyHeaderFlags) g_object_get_data (G_OBJECT (helper.current_priority), "priority");
3905 if (priv->priority_flags != flags)
3906 modest_msg_edit_window_set_priority_flags (window, flags);
3908 /* Set edit format */
3909 old_format = modest_msg_edit_window_get_format (window);
3910 new_format = (ModestMsgEditFormat) g_object_get_data (G_OBJECT (helper.current_format), "format");
3911 if (old_format != new_format) {
3912 gint file_format = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (helper.current_format), "file-format"));
3913 modest_msg_edit_window_set_file_format (window, file_format);
3917 gtk_widget_destroy (dialog);
3918 g_slist_free (helper.priority_group);
3922 on_message_settings (GtkAction *action,
3923 ModestMsgEditWindow *window)
3925 modest_msg_edit_window_show_msg_settings_dialog (window);
3929 on_cc_button_toggled (HildonCheckButton *button,
3930 ModestMsgEditWindow *window)
3932 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
3934 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
3935 hildon_check_button_get_active (button));
3939 on_bcc_button_toggled (HildonCheckButton *button,
3940 ModestMsgEditWindow *window)
3942 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
3944 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
3945 hildon_check_button_get_active (button));
3949 setup_menu (ModestMsgEditWindow *self)
3951 ModestMsgEditWindowPrivate *priv = NULL;
3953 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
3955 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3957 /* Settings menu buttons */
3958 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_checknames"), NULL,
3959 APP_MENU_CALLBACK (modest_ui_actions_on_check_names),
3961 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_undo"), "<Ctrl>z",
3962 APP_MENU_CALLBACK (modest_ui_actions_on_undo),
3963 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_undo));
3965 priv->cc_button = hildon_check_button_new (0);
3966 gtk_button_set_label (GTK_BUTTON (priv->cc_button), _("mcen_me_editor_showcc"));
3967 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button),
3969 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->cc_button),
3971 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
3972 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
3973 priv->bcc_button = hildon_check_button_new (0);
3974 gtk_button_set_label (GTK_BUTTON (priv->bcc_button), _("mcen_me_editor_showbcc"));
3975 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button),
3977 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->bcc_button),
3979 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
3980 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
3982 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_attach_inlineimage"), NULL,
3983 APP_MENU_CALLBACK (modest_ui_actions_on_insert_image),
3984 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_set_style));
3985 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_remove_attachments"), NULL,
3986 APP_MENU_CALLBACK (modest_ui_actions_on_remove_attachments),
3987 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
3988 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_message_settings"), NULL,
3989 APP_MENU_CALLBACK (on_message_settings),
3991 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_viewer_find"), "<Ctrl>f",
3992 APP_MENU_CALLBACK (modest_ui_actions_on_toggle_find_in_page),