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 <widgets/modest-combo-box.h>
47 #include <widgets/modest-recpt-editor.h>
48 #include <widgets/modest-attachments-view.h>
50 #include <modest-runtime.h>
52 #include "modest-platform.h"
53 #include "modest-icon-names.h"
54 #include "modest-widget-memory.h"
55 #include "modest-window-priv.h"
56 #include "modest-mail-operation.h"
57 #include "modest-tny-platform-factory.h"
58 #include "modest-tny-msg.h"
59 #include "modest-tny-folder.h"
60 #include "modest-tny-account.h"
61 #include "modest-address-book.h"
62 #include "modest-text-utils.h"
63 #include <tny-simple-list.h>
64 #include <wptextview.h>
65 #include <wptextbuffer.h>
66 #include "modest-scroll-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"
83 #define DEFAULT_FONT_SIZE 3
84 #define DEFAULT_FONT 2
85 #define DEFAULT_SIZE_BUTTON_FONT_FAMILY "Sans"
86 #define DEFAULT_SIZE_COMBOBOX_WIDTH 80
87 #define DEFAULT_MAIN_VBOX_SPACING 6
88 #define SUBJECT_MAX_LENGTH 1000
89 #define IMAGE_MAX_WIDTH 560
90 #define DEFAULT_FONT_SCALE 1.5
92 static gboolean is_wp_text_buffer_started = FALSE;
94 static void modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass);
95 static void modest_msg_edit_window_init (ModestMsgEditWindow *obj);
96 static void modest_msg_edit_window_finalize (GObject *obj);
98 static gboolean msg_body_focus (GtkWidget *focus, GdkEventFocus *event, gpointer userdata);
99 static void body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
100 static void recpt_field_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
102 static void text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window);
103 static void text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window);
104 static void text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window);
105 static void text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
106 GtkTextIter *start, GtkTextIter *end,
108 static void text_buffer_insert_text (GtkTextBuffer *buffer,
109 GtkTextIter *location,
112 ModestMsgEditWindow *window);
113 static void text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id);
114 static void subject_field_changed (GtkEditable *editable, ModestMsgEditWindow *window);
115 static void subject_field_insert_text (GtkEditable *editable,
117 gint new_text_length,
119 ModestMsgEditWindow *window);
120 static void modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
122 static void modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
124 static void modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
126 static void modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
127 static gboolean modest_msg_edit_window_window_state_event (GtkWidget *widget,
128 GdkEventWindowState *event,
130 static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
131 ModestRecptEditor *editor);
132 static void modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
133 ModestMsgEditWindow *window);
135 /* ModestWindow methods implementation */
136 static void modest_msg_edit_window_disconnect_signals (ModestWindow *window);
137 static void modest_msg_edit_window_show_toolbar (ModestWindow *window,
138 gboolean show_toolbar);
139 static void modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
141 ModestMsgEditWindow *window);
142 static void modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window);
143 static void subject_field_move_cursor (GtkEntry *entry,
144 GtkMovementStep step,
148 static void update_window_title (ModestMsgEditWindow *window);
151 static void modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
152 ModestMsgEditWindow *window);
153 static void modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
154 ModestMsgEditWindow *window);
155 static gboolean gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
157 GtkTextIter *match_start,
158 GtkTextIter *match_end);
160 static void remove_tags (WPTextBuffer *buffer);
162 static void on_account_removed (TnyAccountStore *account_store,
166 static gboolean on_zoom_minus_plus_not_implemented (ModestWindow *window);
167 static void set_zoom_do_nothing (ModestWindow *window, gdouble zoom);
168 static gdouble get_zoom_do_nothing (ModestWindow *window);
170 static void init_window (ModestMsgEditWindow *obj);
172 gboolean scroll_drag_timeout (gpointer userdata);
173 static void correct_scroll (ModestMsgEditWindow *w);
174 static void correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused);
175 static void text_buffer_end_user_action (GtkTextBuffer *buffer,
176 ModestMsgEditWindow *userdata);
177 static void text_buffer_mark_set (GtkTextBuffer *buffer,
180 ModestMsgEditWindow *userdata);
181 void vadj_changed (GtkAdjustment *adj,
182 ModestMsgEditWindow *window);
184 static void DEBUG_BUFFER (WPTextBuffer *buffer)
188 g_message ("BEGIN BUFFER OF SIZE %d", gtk_text_buffer_get_char_count (GTK_TEXT_BUFFER (buffer)));
190 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &iter);
191 while (!gtk_text_iter_is_end (&iter)) {
192 GString *output = g_string_new ("");
193 GSList *toggled_tags;
196 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
197 g_string_append_printf (output, "%d: CLOSED [ ", gtk_text_iter_get_offset (&iter));
198 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
199 GtkTextTag *tag = (GtkTextTag *) node->data;
201 g_object_get (G_OBJECT (tag), "name", &name, NULL);
202 output = g_string_append (output, name);
203 g_string_append (output, " ");
205 output = g_string_append (output, "] OPENED [ ");
206 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
207 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
208 GtkTextTag *tag = (GtkTextTag *) node->data;
210 g_object_get (G_OBJECT (tag), "name", &name, NULL);
211 output = g_string_append (output, name);
212 g_string_append (output, " ");
214 output = g_string_append (output, "]\n");
215 g_message ("%s", output->str);
216 g_string_free (output, TRUE);
217 gtk_text_iter_forward_to_tag_toggle (&iter, NULL);
219 g_message ("END BUFFER");
224 /* static gboolean */
225 /* on_key_pressed (GtkWidget *self, */
226 /* GdkEventKey *event, */
227 /* gpointer user_data); */
229 /* list my signals */
236 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
237 struct _ModestMsgEditWindowPrivate {
240 GtkWidget *header_box;
242 ModestPairList *from_field_protos;
243 GtkWidget *from_field;
244 gchar *original_account_name;
248 GtkWidget *bcc_field;
249 GtkWidget *subject_field;
250 GtkWidget *attachments_view;
251 GtkWidget *priority_icon;
252 GtkWidget *add_attachment_button;
254 GtkWidget *cc_caption;
255 GtkWidget *bcc_caption;
256 gboolean update_caption_visibility;
257 GtkWidget *attachments_caption;
259 GtkTextBuffer *text_buffer;
261 GtkWidget *font_size_toolitem;
262 GtkWidget *font_face_toolitem;
263 GtkWidget *font_color_button;
264 GSList *font_items_group;
265 GtkWidget *font_tool_button_label;
266 GSList *size_items_group;
267 GtkWidget *size_tool_button_label;
269 GtkWidget *find_toolbar;
272 GtkWidget *font_dialog;
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 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
301 MODEST_TYPE_MSG_EDIT_WINDOW, \
302 ModestMsgEditWindowPrivate))
304 static GtkWindowClass *parent_class = NULL;
306 /* uncomment the following if you have defined any signals */
307 /* static guint signals[LAST_SIGNAL] = {0}; */
310 modest_msg_edit_window_get_type (void)
312 static GType my_type = 0;
314 static const GTypeInfo my_info = {
315 sizeof(ModestMsgEditWindowClass),
316 NULL, /* base init */
317 NULL, /* base finalize */
318 (GClassInitFunc) modest_msg_edit_window_class_init,
319 NULL, /* class finalize */
320 NULL, /* class data */
321 sizeof(ModestMsgEditWindow),
323 (GInstanceInitFunc) modest_msg_edit_window_init,
326 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
327 "ModestMsgEditWindow",
335 save_state (ModestWindow *self)
337 modest_widget_memory_save (modest_runtime_get_conf(),
338 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
343 restore_settings (ModestMsgEditWindow *self)
345 ModestConf *conf = NULL;
347 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
349 conf = modest_runtime_get_conf ();
350 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
351 "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarNormalScreenMenu");
352 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
353 modest_conf_get_bool (conf, MODEST_CONF_EDIT_WINDOW_SHOW_TOOLBAR, NULL));
354 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
355 "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarFullScreenMenu");
356 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
357 modest_conf_get_bool (conf, MODEST_CONF_EDIT_WINDOW_SHOW_TOOLBAR_FULLSCREEN, NULL));
359 /* set initial state of cc and bcc */
360 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewCcFieldMenu");
361 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
362 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, NULL));
363 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewBccFieldMenu");
364 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
365 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, NULL));
367 /* Dim at start clipboard actions */
368 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
369 gtk_action_set_sensitive (action, FALSE);
370 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
371 gtk_action_set_sensitive (action, FALSE);
372 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
373 gtk_action_set_sensitive (action, FALSE);
375 modest_widget_memory_restore (conf,
376 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
381 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
383 GObjectClass *gobject_class;
384 ModestWindowClass *modest_window_class;
385 gobject_class = (GObjectClass*) klass;
386 modest_window_class = (ModestWindowClass*) klass;
388 parent_class = g_type_class_peek_parent (klass);
389 gobject_class->finalize = modest_msg_edit_window_finalize;
391 modest_window_class->set_zoom_func = set_zoom_do_nothing;
392 modest_window_class->get_zoom_func = get_zoom_do_nothing;
393 modest_window_class->zoom_plus_func = on_zoom_minus_plus_not_implemented;
394 modest_window_class->zoom_minus_func = on_zoom_minus_plus_not_implemented;
395 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
396 modest_window_class->save_state_func = save_state;
397 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
399 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
403 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
405 ModestMsgEditWindowPrivate *priv;
406 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
408 priv->msg_body = NULL;
410 priv->from_field = NULL;
411 priv->to_field = NULL;
412 priv->cc_field = NULL;
413 priv->bcc_field = NULL;
414 priv->subject_field = NULL;
415 priv->attachments = TNY_LIST (tny_simple_list_new ());
416 priv->images = TNY_LIST (tny_simple_list_new ());
417 priv->images_size = 0;
418 priv->images_count = 0;
421 priv->cc_caption = NULL;
422 priv->bcc_caption = NULL;
423 priv->update_caption_visibility = FALSE;
425 priv->priority_flags = 0;
427 priv->find_toolbar = NULL;
428 priv->last_search = NULL;
430 priv->draft_msg = NULL;
431 priv->outbox_msg = NULL;
432 priv->msg_uid = NULL;
434 priv->can_undo = FALSE;
435 priv->can_redo = FALSE;
436 priv->clipboard_change_handler_id = 0;
437 priv->default_clipboard_change_handler_id = 0;
438 priv->account_removed_handler_id = 0;
439 priv->clipboard_owner_idle = 0;
440 priv->clipboard_text = NULL;
443 priv->scroll_drag_timeout_id = 0;
444 priv->last_upper = 0.0;
446 priv->font_dialog = NULL;
448 modest_window_mgr_register_help_id (modest_runtime_get_window_mgr(),
449 GTK_WINDOW(obj),"applications_email_editor");
451 if (!is_wp_text_buffer_started) {
452 is_wp_text_buffer_started = TRUE;
453 wp_text_buffer_library_init ();
458 hildon_program_add_window (hildon_program_get_instance(),
463 /* FIXME: this is a dup from the one in gtk/ */
466 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
468 static ModestPairList*
469 get_transports (void)
471 GSList *transports = NULL;
473 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
474 GSList *accounts = modest_account_mgr_account_names (account_mgr,
475 TRUE /* only enabled accounts. */);
477 GSList *cursor = accounts;
479 gchar *account_name = cursor->data;
480 gchar *from_string = NULL;
482 from_string = modest_account_mgr_get_from_string (account_mgr,
486 if (from_string && account_name) {
487 gchar *name = account_name;
488 ModestPair *pair = modest_pair_new ((gpointer) name,
489 (gpointer) from_string , TRUE);
490 transports = g_slist_prepend (transports, pair);
493 cursor = cursor->next;
495 g_slist_free (accounts); /* only free the accounts, not the elements,
496 * because they are used in the pairlist */
500 static void window_focus (GtkWindow *window,
504 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
508 scroll_drag_timeout (gpointer userdata)
510 ModestMsgEditWindow *win = (ModestMsgEditWindow *) userdata;
511 ModestMsgEditWindowPrivate *priv;
513 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(win);
515 correct_scroll_without_drag_check (win, TRUE);
517 priv->scroll_drag_timeout_id = 0;
523 correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused)
525 ModestMsgEditWindowPrivate *priv;
528 GdkRectangle rectangle;
534 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
536 if (only_if_focused && !gtk_widget_is_focus (priv->msg_body))
539 insert = gtk_text_buffer_get_insert (priv->text_buffer);
540 gtk_text_buffer_get_iter_at_mark (priv->text_buffer, &iter, insert);
542 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &iter, &rectangle);
543 vadj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll));
544 offset = priv->msg_body->allocation.y;
546 new_value = vadj->value;
548 if ((offset + rectangle.y + rectangle.height) >
549 ((gint) (vadj->value +vadj->page_size))) {
550 new_value = (offset + rectangle.y) - vadj->page_size * 0.25;
551 if (new_value > vadj->upper - vadj->page_size)
552 new_value = vadj->upper - vadj->page_size;
553 } else if ((offset + rectangle.y) < ((gint) vadj->value)) {
554 new_value = (offset + rectangle.y - vadj->page_size * 0.75);
555 if (((gint) (new_value + vadj->page_size)) < (offset + rectangle.y + rectangle.height))
556 new_value = offset + rectangle.y + rectangle.height - (gint) vadj->page_size;
559 if (new_value > vadj->value)
560 new_value = vadj->value;
563 if (vadj->value != new_value) {
564 g_signal_emit_by_name (GTK_TEXT_VIEW(priv->msg_body)->layout,
566 vadj->value = new_value;
567 gtk_adjustment_value_changed (vadj);
568 /* invalidate body */
569 window = gtk_widget_get_parent_window (priv->msg_body);
571 gdk_window_invalidate_rect (window, NULL, TRUE);
577 correct_scroll (ModestMsgEditWindow *w)
579 ModestMsgEditWindowPrivate *priv;
581 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
582 if (gtk_grab_get_current () == priv->msg_body) {
583 if (priv->scroll_drag_timeout_id == 0) {
584 priv->scroll_drag_timeout_id = g_timeout_add (500, (GSourceFunc) scroll_drag_timeout,
590 correct_scroll_without_drag_check (w, TRUE);
594 text_buffer_end_user_action (GtkTextBuffer *buffer,
595 ModestMsgEditWindow *userdata)
598 correct_scroll (userdata);
602 text_buffer_mark_set (GtkTextBuffer *buffer,
605 ModestMsgEditWindow *userdata)
607 gtk_text_buffer_begin_user_action (buffer);
608 gtk_text_buffer_end_user_action (buffer);
612 cut_clipboard_check (GtkTextView *text_view,
615 GtkTextBuffer *buffer;
617 buffer = gtk_text_view_get_buffer (text_view);
618 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
619 g_signal_stop_emission_by_name ((gpointer )text_view, "cut-clipboard");
624 copy_clipboard_check (GtkTextView *text_view,
627 GtkTextBuffer *buffer;
629 buffer = gtk_text_view_get_buffer (text_view);
630 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
631 g_signal_stop_emission_by_name ((gpointer )text_view, "copy-clipboard");
635 void vadj_changed (GtkAdjustment *adj,
636 ModestMsgEditWindow *window)
638 ModestMsgEditWindowPrivate *priv;
640 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
642 if (priv->last_upper != adj->upper) {
643 priv->last_upper = adj->upper;
644 correct_scroll (window);
649 connect_signals (ModestMsgEditWindow *obj)
651 ModestMsgEditWindowPrivate *priv;
653 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
655 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
656 G_CALLBACK (text_buffer_refresh_attributes), obj);
657 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
658 G_CALLBACK (text_buffer_can_undo), obj);
659 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
660 G_CALLBACK (text_buffer_can_redo), obj);
661 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
662 G_CALLBACK (body_changed), obj);
663 g_signal_connect (G_OBJECT (priv->text_buffer), "modified-changed",
664 G_CALLBACK (body_changed), obj);
665 g_signal_connect (G_OBJECT (priv->text_buffer), "insert-text",
666 G_CALLBACK (text_buffer_insert_text), obj);
667 g_signal_connect (G_OBJECT (obj), "window-state-event",
668 G_CALLBACK (modest_msg_edit_window_window_state_event),
670 g_signal_connect (G_OBJECT (priv->text_buffer), "end-user-action",
671 G_CALLBACK (text_buffer_end_user_action), obj);
672 g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
673 G_CALLBACK (text_buffer_mark_set), obj);
674 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
675 G_CALLBACK (text_buffer_apply_tag), obj);
676 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
677 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
678 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
679 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
680 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
681 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
683 g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
684 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
686 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
687 G_CALLBACK (msg_body_focus), obj);
688 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
689 G_CALLBACK (msg_body_focus), obj);
690 g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
691 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
692 "changed", G_CALLBACK (recpt_field_changed), obj);
693 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
694 "changed", G_CALLBACK (recpt_field_changed), obj);
695 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
696 "changed", G_CALLBACK (recpt_field_changed), obj);
697 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
698 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
699 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
701 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
702 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
704 g_signal_connect (G_OBJECT (gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll))),
706 G_CALLBACK (vadj_changed),
709 priv->clipboard_change_handler_id =
710 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
711 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
712 priv->default_clipboard_change_handler_id =
713 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
714 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
716 g_signal_connect (G_OBJECT (priv->msg_body), "cut-clipboard", G_CALLBACK (cut_clipboard_check), NULL);
717 g_signal_connect (G_OBJECT (priv->msg_body), "copy-clipboard", G_CALLBACK (copy_clipboard_check), NULL);
722 init_window (ModestMsgEditWindow *obj)
724 GtkWidget *from_caption, *to_caption, *subject_caption;
725 GtkWidget *main_vbox;
726 ModestMsgEditWindowPrivate *priv;
727 GtkActionGroup *action_group;
728 ModestWindowPrivate *parent_priv;
729 GdkPixbuf *window_icon = NULL;
730 GError *error = NULL;
732 GtkSizeGroup *size_group;
733 GtkWidget *subject_box;
734 GtkWidget *attachment_icon;
735 GtkWidget *window_box;
736 #if (GTK_MINOR_VERSION >= 10)
737 GdkAtom deserialize_type;
739 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
740 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
742 parent_priv->ui_manager = gtk_ui_manager_new();
743 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
744 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
746 /* Add common actions */
747 gtk_action_group_add_actions (action_group,
748 modest_msg_edit_action_entries,
749 G_N_ELEMENTS (modest_msg_edit_action_entries),
751 gtk_action_group_add_toggle_actions (action_group,
752 modest_msg_edit_toggle_action_entries,
753 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
755 gtk_action_group_add_radio_actions (action_group,
756 modest_msg_edit_alignment_radio_action_entries,
757 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
759 G_CALLBACK (modest_ui_actions_on_change_justify),
761 gtk_action_group_add_radio_actions (action_group,
762 modest_msg_edit_priority_action_entries,
763 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
765 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
767 gtk_action_group_add_radio_actions (action_group,
768 modest_msg_edit_file_format_action_entries,
769 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
770 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
771 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
773 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
774 g_object_unref (action_group);
776 /* Load the UI definition */
777 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
780 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
781 g_clear_error (&error);
784 /* Add accelerators */
785 gtk_window_add_accel_group (GTK_WINDOW (obj),
786 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
788 parent_priv->menubar = NULL;
790 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
792 /* Note: This ModestPairList* must exist for as long as the combo
793 * that uses it, because the ModestComboBox uses the ID opaquely,
794 * so it can't know how to manage its memory. */
795 priv->from_field = modest_combo_box_new (NULL, g_str_equal);
797 priv->to_field = modest_recpt_editor_new ();
798 priv->cc_field = modest_recpt_editor_new ();
799 priv->bcc_field = modest_recpt_editor_new ();
800 subject_box = gtk_hbox_new (FALSE, 0);
801 priv->priority_icon = gtk_image_new ();
802 gtk_box_pack_start (GTK_BOX (subject_box), priv->priority_icon, FALSE, FALSE, 0);
803 priv->subject_field = gtk_entry_new_with_max_length (SUBJECT_MAX_LENGTH);
804 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
805 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
806 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
807 gtk_box_pack_start (GTK_BOX (subject_box), priv->subject_field, TRUE, TRUE, 0);
808 priv->add_attachment_button = gtk_button_new ();
809 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
810 gtk_button_set_relief (GTK_BUTTON (priv->add_attachment_button), GTK_RELIEF_NONE);
811 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
812 gtk_button_set_alignment (GTK_BUTTON (priv->add_attachment_button), 1.0, 1.0);
813 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, GTK_ICON_SIZE_BUTTON);
814 gtk_container_add (GTK_CONTAINER (priv->add_attachment_button), attachment_icon);
815 gtk_box_pack_start (GTK_BOX (subject_box), priv->add_attachment_button, FALSE, FALSE, 0);
816 priv->attachments_view = modest_attachments_view_new (NULL);
818 priv->header_box = gtk_vbox_new (FALSE, 0);
820 from_caption = hildon_caption_new (size_group, _("mail_va_from"), priv->from_field, NULL, 0);
821 to_caption = hildon_caption_new (size_group, _("mail_va_to"), priv->to_field, NULL, 0);
822 priv->cc_caption = hildon_caption_new (size_group, _("mail_va_cc"), priv->cc_field, NULL, 0);
823 priv->bcc_caption = hildon_caption_new (size_group, _("mail_va_hotfix1"), priv->bcc_field, NULL, 0);
824 subject_caption = hildon_caption_new (size_group, _("mail_va_subject"), subject_box, NULL, 0);
825 priv->attachments_caption = hildon_caption_new (size_group, _("mail_va_attachment"), priv->attachments_view, NULL, 0);
826 g_object_unref (size_group);
828 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
829 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), size_group);
830 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), size_group);
831 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), size_group);
832 gtk_size_group_add_widget (size_group, priv->subject_field);
833 gtk_size_group_add_widget (size_group, priv->attachments_view);
834 g_object_unref (size_group);
836 gtk_box_pack_start (GTK_BOX (priv->header_box), from_caption, FALSE, FALSE, 0);
837 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
838 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
839 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
840 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
841 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
842 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
845 priv->msg_body = wp_text_view_new ();
846 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
847 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
848 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
849 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
850 #if (GTK_MINOR_VERSION >= 10)
851 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), "wp-text-buffer");
852 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
854 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
855 deserialize_type, TRUE);
857 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
859 priv->find_toolbar = hildon_find_toolbar_new (NULL);
860 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
862 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
864 priv->scroll = gtk_scrolled_window_new (NULL, NULL);
865 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
866 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (priv->scroll), GTK_SHADOW_NONE);
867 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->scroll), TRUE);
869 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
871 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
872 priv->frame = gtk_frame_new (NULL);
873 gtk_box_pack_start (GTK_BOX(main_vbox), priv->frame, TRUE, TRUE, 0);
875 gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (priv->scroll), main_vbox);
876 gtk_container_set_focus_vadjustment (GTK_CONTAINER (main_vbox), gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll)));
877 gtk_widget_show_all (GTK_WIDGET(priv->scroll));
879 window_box = gtk_vbox_new (FALSE, 0);
880 gtk_container_add (GTK_CONTAINER(obj), window_box);
882 gtk_box_pack_start (GTK_BOX (window_box), priv->scroll, TRUE, TRUE, 0);
884 gtk_container_add (GTK_CONTAINER (priv->frame), priv->msg_body);
886 /* Set window icon */
887 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
889 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
890 g_object_unref (window_icon);
895 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
897 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
899 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
900 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
901 priv->clipboard_change_handler_id))
902 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
903 priv->clipboard_change_handler_id);
904 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
905 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
906 priv->default_clipboard_change_handler_id))
907 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
908 priv->default_clipboard_change_handler_id);
910 if (priv->account_removed_handler_id &&
911 g_signal_handler_is_connected (modest_runtime_get_account_store (),
912 priv->account_removed_handler_id))
913 g_signal_handler_disconnect(modest_runtime_get_account_store (),
914 priv->account_removed_handler_id);
918 modest_msg_edit_window_finalize (GObject *obj)
920 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
922 /* Sanity check: shouldn't be needed, the window mgr should
923 call this function before */
924 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
926 if (priv->font_dialog != NULL) {
927 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
930 if (priv->clipboard_text != NULL) {
931 g_free (priv->clipboard_text);
932 priv->clipboard_text = NULL;
935 if (priv->draft_msg != NULL) {
936 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
937 if (TNY_IS_HEADER (header)) {
938 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
939 modest_window_mgr_unregister_header (mgr, header);
941 g_object_unref (priv->draft_msg);
942 priv->draft_msg = NULL;
944 if (priv->outbox_msg != NULL) {
945 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
946 if (TNY_IS_HEADER (header)) {
947 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
948 modest_window_mgr_unregister_header (mgr, header);
950 g_object_unref (priv->outbox_msg);
951 priv->outbox_msg = NULL;
953 if (priv->scroll_drag_timeout_id > 0) {
954 g_source_remove (priv->scroll_drag_timeout_id);
955 priv->scroll_drag_timeout_id = 0;
957 if (priv->clipboard_owner_idle > 0) {
958 g_source_remove (priv->clipboard_owner_idle);
959 priv->clipboard_owner_idle = 0;
961 if (priv->original_account_name)
962 g_free (priv->original_account_name);
963 g_free (priv->msg_uid);
964 g_free (priv->last_search);
965 g_slist_free (priv->font_items_group);
966 g_slist_free (priv->size_items_group);
967 g_object_unref (priv->attachments);
968 g_object_unref (priv->images);
970 /* This had to stay alive for as long as the combobox that used it: */
971 modest_pair_list_free (priv->from_field_protos);
973 G_OBJECT_CLASS(parent_class)->finalize (obj);
977 pixbuf_from_stream (TnyStream *stream, const gchar *mime_type, guint64 *stream_size)
979 GdkPixbufLoader *loader;
985 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
987 if (loader == NULL) {
993 tny_stream_reset (TNY_STREAM (stream));
994 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
995 GError *error = NULL;
996 unsigned char read_buffer[128];
998 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
1000 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
1005 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1007 g_object_ref (pixbuf);
1008 gdk_pixbuf_loader_close (loader, NULL);
1009 g_object_unref (loader);
1014 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1015 GdkPixbuf *new_pixbuf;
1017 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1018 gdk_pixbuf_get_width (pixbuf);
1019 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1020 g_object_unref (pixbuf);
1021 pixbuf = new_pixbuf;
1025 *stream_size = size;
1031 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1033 ModestMsgEditWindowPrivate *priv;
1036 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1038 for (iter = tny_list_create_iterator (attachments);
1039 !tny_iterator_is_done (iter);
1040 tny_iterator_next (iter)) {
1041 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1042 const gchar *cid = tny_mime_part_get_content_id (part);
1043 const gchar *mime_type = tny_mime_part_get_content_type (part);
1044 if ((cid != NULL)&&(mime_type != NULL)) {
1045 guint64 stream_size;
1046 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1047 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
1050 g_object_unref (stream);
1052 if (pixbuf != NULL) {
1053 priv->images_count ++;
1054 priv->images_size += stream_size;
1055 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1056 g_object_unref (pixbuf);
1059 g_object_unref (part);
1061 g_object_unref (iter);
1065 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1067 TnyMimePart *parent = NULL;
1068 const gchar *content_type = NULL;
1069 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1071 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1073 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1074 parent = g_object_ref (msg);
1075 } else if (content_type && !g_strcasecmp (content_type, "multipart/mixed")) {
1076 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1079 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1080 iter = tny_list_create_iterator (parts);
1081 while (!tny_iterator_is_done (iter)) {
1083 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1084 content_type = tny_mime_part_get_content_type (part);
1085 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1089 g_object_unref (part);
1091 tny_iterator_next (iter);
1093 g_object_unref (iter);
1094 g_object_unref (parts);
1097 if (parent != NULL) {
1098 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1101 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1102 iter = tny_list_create_iterator (parts);
1103 while (!tny_iterator_is_done (iter)) {
1105 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1106 content_type = tny_mime_part_get_content_type (part);
1107 if (content_type && g_str_has_prefix (content_type, "image/")) {
1108 tny_list_prepend (priv->images, (GObject *) part);
1110 g_object_unref (part);
1111 tny_iterator_next (iter);
1113 g_object_unref (iter);
1114 g_object_unref (parts);
1115 g_object_unref (parent);
1120 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1123 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1125 for (iter = tny_list_create_iterator (attachments) ;
1126 !tny_iterator_is_done (iter);
1127 tny_iterator_next (iter)) {
1128 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1129 const gchar *cid = tny_mime_part_get_content_id (part);
1131 char *invalid = NULL;
1132 gint int_cid = strtol (cid, &invalid, 10);
1133 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1134 priv->next_cid = int_cid + 1;
1137 g_object_unref (part);
1139 g_object_unref (iter);
1143 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1146 gchar *to, *cc, *bcc, *subject;
1148 ModestMsgEditWindowPrivate *priv;
1150 TnyHeaderFlags priority_flags;
1151 TnyFolder *msg_folder;
1152 gboolean is_html = FALSE;
1154 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1155 g_return_if_fail (TNY_IS_MSG (msg));
1157 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1159 header = tny_msg_get_header (msg);
1160 to = tny_header_dup_to (header);
1161 cc = tny_header_dup_cc (header);
1162 bcc = tny_header_dup_bcc (header);
1163 subject = tny_header_dup_subject (header);
1164 priority_flags = tny_header_get_priority (header);
1167 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
1169 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
1170 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1171 gtk_widget_show (priv->cc_caption);
1172 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1173 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1174 gtk_widget_hide (priv->cc_caption);
1177 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
1178 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1179 gtk_widget_show (priv->bcc_caption);
1180 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1181 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1182 gtk_widget_hide (priv->bcc_caption);
1185 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1186 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1189 update_window_title (self);
1191 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1192 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1194 if ((body == NULL)||(body[0] == '\0')) {
1196 body = modest_text_utils_convert_to_html ("");
1199 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1200 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1203 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1206 /* Add attachments to the view */
1207 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1208 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1209 if (tny_list_get_length (priv->attachments) == 0) {
1210 gtk_widget_hide (priv->attachments_caption);
1212 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1213 gtk_widget_show_all (priv->attachments_caption);
1215 get_related_images (self, msg);
1216 update_next_cid (self, priv->attachments);
1217 update_next_cid (self, priv->images);
1218 replace_with_images (self, priv->images);
1220 if (preserve_is_rich && !is_html) {
1221 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1222 /* Get the default format required from configuration */
1223 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1224 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1227 /* Set the default focus depending on having already a To: field or not */
1228 if ((!to)||(*to == '\0')) {
1229 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1231 gtk_widget_grab_focus (priv->msg_body);
1234 /* TODO: lower priority, select in the From: combo to the
1235 value that comes from msg <- not sure, should it be
1238 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1240 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1241 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1243 modest_msg_edit_window_set_modified (self, FALSE);
1245 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1246 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1247 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1248 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1250 if (priv->msg_uid) {
1251 g_free (priv->msg_uid);
1252 priv->msg_uid = NULL;
1255 /* we should set a reference to the incoming message if it is a draft */
1256 msg_folder = tny_msg_get_folder (msg);
1258 if (modest_tny_folder_is_local_folder (msg_folder)) {
1259 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1260 if (type == TNY_FOLDER_TYPE_INVALID)
1261 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1263 if (type == TNY_FOLDER_TYPE_DRAFTS)
1264 priv->draft_msg = g_object_ref(msg);
1265 if (type == TNY_FOLDER_TYPE_OUTBOX)
1266 priv->outbox_msg = g_object_ref(msg);
1267 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1269 g_object_unref (msg_folder);
1279 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
1282 GList *item_children, *node;
1283 GtkWidget *bin_child;
1285 bin_child = gtk_bin_get_child (GTK_BIN(item));
1287 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
1289 for (node = item_children; node != NULL; node = g_list_next (node)) {
1290 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
1291 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
1294 g_list_free (item_children);
1298 menu_tool_button_dont_expand (GtkMenuToolButton *item)
1301 GList *item_children, *node;
1303 box = gtk_bin_get_child (GTK_BIN (item));
1304 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
1305 item_children = gtk_container_get_children (GTK_CONTAINER (box));
1307 for (node = item_children; node != NULL; node = g_list_next (node)) {
1308 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
1309 if (GTK_IS_TOGGLE_BUTTON (node->data))
1310 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
1311 else if (GTK_IS_BUTTON (node->data))
1312 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
1314 g_list_free (item_children);
1319 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1321 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1322 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1323 GtkWidget *placeholder;
1324 GtkWidget *tool_item;
1329 GtkWidget *sizes_menu;
1330 GtkWidget *fonts_menu;
1331 GSList *radio_group = NULL;
1332 GSList *node = NULL;
1336 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1337 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1339 /* Font color placeholder */
1340 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1341 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1344 tool_item = GTK_WIDGET (gtk_tool_item_new ());
1345 priv->font_color_button = hildon_color_button_new ();
1346 GTK_WIDGET_UNSET_FLAGS (tool_item, GTK_CAN_FOCUS);
1347 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1348 gtk_container_add (GTK_CONTAINER (tool_item), priv->font_color_button);
1349 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1350 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1351 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1352 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1354 G_CALLBACK (modest_msg_edit_window_color_button_change),
1357 /* Font size and face placeholder */
1358 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1359 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1361 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1362 priv->size_tool_button_label = gtk_label_new (NULL);
1363 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1364 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1365 size_text,"</span>", NULL);
1366 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1368 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
1369 sizes_menu = gtk_menu_new ();
1370 priv->size_items_group = NULL;
1372 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1373 GtkWidget *size_menu_item;
1375 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1376 size_menu_item = gtk_radio_menu_item_new_with_label (radio_group, size_text);
1377 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (size_menu_item));
1378 gtk_menu_shell_append (GTK_MENU_SHELL (sizes_menu), size_menu_item);
1379 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (size_menu_item), (wp_font_size[size_index] == 12));
1380 gtk_widget_show (size_menu_item);
1382 priv->size_items_group = g_slist_prepend (priv->size_items_group, size_menu_item);
1386 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1387 GtkWidget *item = (GtkWidget *) node->data;
1388 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_size_change),
1392 priv->size_items_group = g_slist_reverse (priv->size_items_group);
1393 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), sizes_menu);
1394 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1395 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1396 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1397 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1398 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1399 priv->font_size_toolitem = tool_item;
1402 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1403 priv->font_tool_button_label = gtk_label_new (NULL);
1404 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1405 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1407 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
1408 fonts_menu = gtk_menu_new ();
1409 priv->font_items_group = NULL;
1411 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1412 GtkWidget *font_menu_item;
1413 GtkWidget *child_label;
1415 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
1416 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
1417 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
1418 wp_get_font_name (font_index), "</span>", NULL);
1419 gtk_label_set_markup (GTK_LABEL (child_label), markup);
1422 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
1423 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
1424 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
1425 gtk_widget_show (font_menu_item);
1427 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
1430 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1431 GtkWidget *item = (GtkWidget *) node->data;
1432 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
1435 priv->font_items_group = g_slist_reverse (priv->font_items_group);
1436 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
1437 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1438 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1439 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1440 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1441 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1442 priv->font_face_toolitem = tool_item;
1444 /* Set expand and homogeneous for remaining items */
1445 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
1446 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1447 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1448 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1449 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1450 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1451 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1452 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1453 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1455 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1456 will not show the tool items added to the placeholders) */
1457 gtk_widget_show_all (parent_priv->toolbar);
1459 /* Set the no show all *after* showing all items. We do not
1460 want the toolbar to be shown with a show all because it
1461 could go agains the gconf setting regarding showing or not
1462 the toolbar of the editor window */
1463 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1469 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, gboolean preserve_is_rich)
1472 ModestWindowPrivate *parent_priv;
1473 ModestMsgEditWindowPrivate *priv;
1474 ModestDimmingRulesGroup *menu_rules_group = NULL;
1475 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1476 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1477 ModestWindowMgr *mgr = NULL;
1479 g_return_val_if_fail (msg, NULL);
1480 g_return_val_if_fail (account_name, NULL);
1482 mgr = modest_runtime_get_window_mgr ();
1484 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1486 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1487 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1489 /* Menubar. Update the state of some toggles */
1490 parent_priv->menubar = modest_maemo_utils_get_manager_menubar_as_menu (parent_priv->ui_manager, "/MenuBar");
1491 hildon_window_set_menu (HILDON_WINDOW (obj), GTK_MENU (parent_priv->menubar));
1492 priv->from_field_protos = get_transports ();
1493 modest_combo_box_set_pair_list (MODEST_COMBO_BOX (priv->from_field), priv->from_field_protos);
1494 modest_combo_box_set_active_id (MODEST_COMBO_BOX (priv->from_field), (gpointer) account_name);
1495 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1496 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1499 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1501 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1503 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1505 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1507 parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new ();
1508 menu_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_MENU, FALSE);
1509 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1510 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1511 /* Add common dimming rules */
1512 modest_dimming_rules_group_add_rules (menu_rules_group,
1513 modest_msg_edit_window_menu_dimming_entries,
1514 G_N_ELEMENTS (modest_msg_edit_window_menu_dimming_entries),
1515 MODEST_WINDOW (obj));
1516 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1517 modest_msg_edit_window_toolbar_dimming_entries,
1518 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1519 MODEST_WINDOW (obj));
1520 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_button,
1521 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1522 MODEST_WINDOW (obj));
1523 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1524 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1525 MODEST_WINDOW (obj));
1526 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1527 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1528 MODEST_WINDOW (obj));
1529 modest_dimming_rules_group_add_rules (clipboard_rules_group,
1530 modest_msg_edit_window_clipboard_dimming_entries,
1531 G_N_ELEMENTS (modest_msg_edit_window_clipboard_dimming_entries),
1532 MODEST_WINDOW (obj));
1533 /* Insert dimming rules group for this window */
1534 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
1535 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1536 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1537 /* Checks the dimming rules */
1538 g_object_unref (menu_rules_group);
1539 g_object_unref (toolbar_rules_group);
1540 g_object_unref (clipboard_rules_group);
1541 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1543 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1545 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1546 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1547 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1548 priv->update_caption_visibility = TRUE;
1550 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1552 /* Track account-removed signal, this window should be closed
1553 in the case we're creating a mail associated to the account
1555 priv->account_removed_handler_id =
1556 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1558 G_CALLBACK(on_account_removed),
1561 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1563 return (ModestWindow*) obj;
1567 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1569 GString **string_buffer = (GString **) user_data;
1571 *string_buffer = g_string_append (*string_buffer, buffer);
1577 * @result: A new string which should be freed with g_free().
1580 get_formatted_data (ModestMsgEditWindow *edit_window)
1582 ModestMsgEditWindowPrivate *priv;
1583 GString *string_buffer = g_string_new ("");
1585 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1587 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1589 modest_text_utils_hyperlinkify (string_buffer);
1591 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1593 return g_string_free (string_buffer, FALSE);
1598 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1601 const gchar *account_name;
1602 ModestMsgEditWindowPrivate *priv;
1603 TnyIterator *att_iter;
1605 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1607 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1609 account_name = modest_combo_box_get_active_id (MODEST_COMBO_BOX (priv->from_field));
1610 g_return_val_if_fail (account_name, NULL);
1613 /* don't free these (except from) */
1614 data = g_slice_new0 (MsgData);
1615 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1617 data->account_name = g_strdup (account_name);
1618 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1619 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1620 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1621 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1622 if (priv->draft_msg) {
1623 data->draft_msg = g_object_ref (priv->draft_msg);
1624 } else if (priv->outbox_msg) {
1625 data->draft_msg = g_object_ref (priv->outbox_msg);
1627 data->draft_msg = NULL;
1630 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1632 gtk_text_buffer_get_bounds (buf, &b, &e);
1633 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1635 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1636 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1638 data->html_body = NULL;
1640 /* deep-copy the data */
1641 att_iter = tny_list_create_iterator (priv->attachments);
1642 data->attachments = NULL;
1643 while (!tny_iterator_is_done (att_iter)) {
1644 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1645 if (!(TNY_IS_MIME_PART(part))) {
1646 g_warning ("strange data in attachment list");
1647 g_object_unref (part);
1648 tny_iterator_next (att_iter);
1651 data->attachments = g_list_append (data->attachments,
1653 tny_iterator_next (att_iter);
1655 g_object_unref (att_iter);
1657 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1658 att_iter = tny_list_create_iterator (priv->images);
1659 data->images = NULL;
1660 while (!tny_iterator_is_done (att_iter)) {
1661 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1663 if (!(TNY_IS_MIME_PART(part))) {
1664 g_warning ("strange data in attachment list");
1665 g_object_unref (part);
1666 tny_iterator_next (att_iter);
1669 cid = tny_mime_part_get_content_id (part);
1671 gchar *image_tag_id;
1672 GtkTextTag *image_tag;
1674 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1675 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1676 g_free (image_tag_id);
1678 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1680 ((gtk_text_iter_has_tag (&iter, image_tag))||
1681 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1682 data->images = g_list_append (data->images,
1683 g_object_ref (part));
1685 g_object_unref (part);
1686 tny_iterator_next (att_iter);
1688 g_object_unref (att_iter);
1690 data->priority_flags = priv->priority_flags;
1697 unref_gobject (GObject *obj, gpointer data)
1699 if (!G_IS_OBJECT(obj))
1701 g_object_unref (obj);
1705 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1708 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1716 g_free (data->from);
1717 g_free (data->subject);
1718 g_free (data->plain_body);
1719 g_free (data->html_body);
1720 g_free (data->account_name);
1722 if (data->draft_msg != NULL) {
1723 g_object_unref (data->draft_msg);
1724 data->draft_msg = NULL;
1727 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1728 g_list_free (data->attachments);
1729 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1730 g_list_free (data->images);
1732 g_slice_free (MsgData, data);
1736 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1738 guint64 *parts_size)
1740 ModestMsgEditWindowPrivate *priv;
1742 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1744 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1746 /* TODO: add images */
1747 *parts_size += priv->images_size;
1748 *parts_count += priv->images_count;
1753 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1756 ModestMsgEditWindowPrivate *priv = NULL;
1757 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1759 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1761 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1763 return MODEST_MSG_EDIT_FORMAT_HTML;
1765 return MODEST_MSG_EDIT_FORMAT_TEXT;
1769 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1770 ModestMsgEditFormat format)
1772 ModestMsgEditWindowPrivate *priv;
1774 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1775 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1778 case MODEST_MSG_EDIT_FORMAT_HTML:
1779 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1781 case MODEST_MSG_EDIT_FORMAT_TEXT:
1782 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1785 g_return_if_reached ();
1789 ModestMsgEditFormatState *
1790 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1792 ModestMsgEditFormatState *format_state = NULL;
1793 ModestMsgEditWindowPrivate *priv;
1794 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1796 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1797 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1799 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1801 format_state = g_new0 (ModestMsgEditFormatState, 1);
1802 format_state->bold = buffer_format->bold&0x1;
1803 format_state->italics = buffer_format->italic&0x1;
1804 format_state->bullet = buffer_format->bullet&0x1;
1805 format_state->color = buffer_format->color;
1806 format_state->font_size = buffer_format->font_size;
1807 format_state->font_family = wp_get_font_name (buffer_format->font);
1808 format_state->justification = buffer_format->justification;
1809 g_free (buffer_format);
1811 return format_state;
1816 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1817 const ModestMsgEditFormatState *format_state)
1819 ModestMsgEditWindowPrivate *priv;
1820 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1821 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1822 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1823 g_return_if_fail (format_state != NULL);
1825 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1826 gtk_widget_grab_focus (priv->msg_body);
1827 buffer_format->bold = (format_state->bold != FALSE);
1828 buffer_format->italic = (format_state->italics != FALSE);
1829 buffer_format->color = format_state->color;
1830 buffer_format->font_size = format_state->font_size;
1831 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1832 buffer_format->justification = format_state->justification;
1833 buffer_format->bullet = format_state->bullet;
1835 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1837 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1838 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1839 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1840 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1841 buffer_format->cs.font = (buffer_format->font != current_format->font);
1842 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1843 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1845 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1846 if (buffer_format->cs.bold) {
1847 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
1848 GINT_TO_POINTER (buffer_format->bold&0x1));
1850 if (buffer_format->cs.italic) {
1851 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
1852 GINT_TO_POINTER (buffer_format->italic&0x1));
1854 if (buffer_format->cs.color) {
1855 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1856 GINT_TO_POINTER (&(buffer_format->color)));
1858 if (buffer_format->cs.font_size) {
1859 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1860 GINT_TO_POINTER (buffer_format->font_size));
1862 if (buffer_format->cs.justification) {
1863 switch (buffer_format->justification) {
1864 case GTK_JUSTIFY_LEFT:
1865 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
1866 GINT_TO_POINTER(TRUE));
1868 case GTK_JUSTIFY_CENTER:
1869 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
1870 GINT_TO_POINTER(TRUE));
1872 case GTK_JUSTIFY_RIGHT:
1873 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
1874 GINT_TO_POINTER(TRUE));
1881 if (buffer_format->cs.font) {
1882 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1883 GINT_TO_POINTER (buffer_format->font));
1885 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1886 if (buffer_format->cs.bullet) {
1887 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
1888 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
1890 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1892 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
1894 g_free (current_format);
1899 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1901 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1903 ModestWindowPrivate *parent_priv;
1904 ModestMsgEditWindowPrivate *priv;
1905 GtkWidget *new_size_menuitem;
1906 GtkWidget *new_font_menuitem;
1908 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1909 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1911 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1912 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu");
1913 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1914 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1916 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatPlainTextMenu");
1917 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1918 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1921 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1923 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1924 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1926 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1927 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1929 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
1930 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
1933 switch (buffer_format->justification)
1935 case GTK_JUSTIFY_LEFT:
1936 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
1938 case GTK_JUSTIFY_CENTER:
1939 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
1941 case GTK_JUSTIFY_RIGHT:
1942 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
1949 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
1951 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1952 G_CALLBACK (modest_msg_edit_window_color_button_change),
1954 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1955 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1956 G_CALLBACK (modest_msg_edit_window_color_button_change),
1959 new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group,
1960 buffer_format->font_size))->data);
1961 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1965 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1966 markup = g_strconcat ("<span font_family='Sans'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1967 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1969 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1970 G_CALLBACK (modest_msg_edit_window_size_change),
1972 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
1973 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
1974 G_CALLBACK (modest_msg_edit_window_size_change),
1978 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
1979 buffer_format->font))->data);
1980 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
1984 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
1985 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1986 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1988 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
1989 G_CALLBACK (modest_msg_edit_window_font_change),
1991 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
1992 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
1993 G_CALLBACK (modest_msg_edit_window_font_change),
1997 g_free (buffer_format);
2001 #ifdef MODEST_HILDON_VERSION_0
2003 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2006 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2007 ModestMsgEditWindowPrivate *priv;
2008 GtkWidget *dialog = NULL;
2010 GdkColor *new_color = NULL;
2012 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2013 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2015 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2016 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
2017 g_free (buffer_format);
2019 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2020 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2021 if (new_color != NULL) {
2022 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2023 (gpointer) new_color);
2026 gtk_widget_destroy (dialog);
2031 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2034 ModestMsgEditWindowPrivate *priv;
2035 GtkWidget *dialog = NULL;
2037 GdkColor *old_color = NULL;
2038 const GdkColor *new_color = NULL;
2040 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2041 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2043 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2044 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2046 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2047 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2048 if (new_color != NULL)
2049 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2051 gtk_widget_destroy (dialog);
2057 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2060 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2061 ModestMsgEditWindowPrivate *priv;
2062 GtkWidget *dialog = NULL;
2064 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2065 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2067 dialog = hildon_color_chooser_new ();
2068 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2069 g_free (buffer_format);
2071 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2073 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2074 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2077 gtk_widget_destroy (dialog);
2082 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2085 ModestMsgEditWindowPrivate *priv;
2086 GtkWidget *dialog = NULL;
2087 GdkColor *old_color = NULL;
2089 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2090 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2092 dialog = hildon_color_chooser_new ();
2093 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2095 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2097 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2098 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2100 gtk_widget_destroy (dialog);
2103 #endif /*!MODEST_HILDON_VERSION_0*/
2108 create_stream_for_uri (const gchar* uri)
2113 TnyStream *result = NULL;
2115 GnomeVFSHandle *handle = NULL;
2116 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2117 if (test == GNOME_VFS_OK) {
2118 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2119 /* Streams over OBEX (Bluetooth) are not seekable but
2120 * we expect them to be (we might need to read them
2121 * several times). So if this is a Bluetooth URI just
2122 * read the whole file into memory (this is not a fast
2123 * protocol so we can assume that these files are not
2124 * going to be very big) */
2125 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2126 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2127 TnyStream *memstream = tny_camel_mem_stream_new ();
2128 tny_stream_write_to_stream (vfssstream, memstream);
2129 g_object_unref (vfssstream);
2132 result = vfssstream;
2140 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2143 ModestMsgEditWindowPrivate *priv;
2144 GtkWidget *dialog = NULL;
2146 GSList *uris = NULL;
2147 GSList *uri_node = NULL;
2149 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2151 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2152 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2153 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2155 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2157 response = gtk_dialog_run (GTK_DIALOG (dialog));
2159 case GTK_RESPONSE_OK:
2160 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2165 gtk_widget_destroy (dialog);
2167 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2169 GnomeVFSHandle *handle = NULL;
2170 GnomeVFSResult result;
2171 GtkTextIter position;
2172 GtkTextMark *insert_mark;
2174 uri = (const gchar *) uri_node->data;
2175 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2176 if (result == GNOME_VFS_OK) {
2178 GnomeVFSFileInfo *info;
2179 gchar *filename, *basename, *escaped_filename;
2180 TnyMimePart *mime_part;
2182 const gchar *mime_type = NULL;
2183 GnomeVFSURI *vfs_uri;
2184 guint64 stream_size;
2186 gnome_vfs_close (handle);
2187 vfs_uri = gnome_vfs_uri_new (uri);
2189 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2190 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2191 g_free (escaped_filename);
2192 gnome_vfs_uri_unref (vfs_uri);
2193 info = gnome_vfs_file_info_new ();
2195 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2196 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2198 mime_type = gnome_vfs_file_info_get_mime_type (info);
2200 mime_part = tny_platform_factory_new_mime_part
2201 (modest_runtime_get_platform_factory ());
2203 TnyStream *stream = create_stream_for_uri (uri);
2205 if (stream == NULL) {
2207 modest_platform_information_banner (NULL, NULL, dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2209 g_object_unref (mime_part);
2210 gnome_vfs_file_info_unref (info);
2214 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2216 content_id = g_strdup_printf ("%d", priv->next_cid);
2217 tny_mime_part_set_content_id (mime_part, content_id);
2218 g_free (content_id);
2221 basename = g_path_get_basename (filename);
2222 tny_mime_part_set_filename (mime_part, basename);
2225 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
2227 if (pixbuf != NULL) {
2228 priv->images_size += stream_size;
2229 priv->images_count ++;
2230 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2231 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2232 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
2235 tny_list_prepend (priv->images, (GObject *) mime_part);
2236 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2238 g_object_unref (mime_part);
2239 gnome_vfs_file_info_unref (info);
2248 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2250 GtkWidget *dialog = NULL;
2252 GSList *uris = NULL;
2254 GnomeVFSFileSize total_size, allowed_size;
2255 ModestMsgEditWindowPrivate *priv;
2259 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2261 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2263 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2266 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2267 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2268 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2269 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), GTK_WINDOW (dialog));
2271 response = gtk_dialog_run (GTK_DIALOG (dialog));
2273 case GTK_RESPONSE_OK:
2274 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2279 gtk_widget_destroy (dialog);
2281 /* allowed size is the maximum size - what's already there */
2282 modest_attachments_view_get_sizes (
2283 MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2284 &att_num, &att_size);
2285 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2288 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2290 const gchar *uri = (const gchar *) uri_node->data;
2292 total_size += modest_msg_edit_window_attach_file_one
2293 (window, uri, allowed_size);
2295 if (total_size > allowed_size) {
2296 g_warning ("%s: total size: %u",
2297 __FUNCTION__, (unsigned int)total_size);
2301 allowed_size -= total_size;
2305 g_slist_foreach (uris, (GFunc) g_free, NULL);
2306 g_slist_free (uris);
2311 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2313 GnomeVFSFileSize allowed_size)
2316 GnomeVFSHandle *handle = NULL;
2317 ModestMsgEditWindowPrivate *priv;
2318 GnomeVFSResult result;
2319 GnomeVFSFileSize size = 0;
2321 g_return_val_if_fail (window, 0);
2322 g_return_val_if_fail (uri, 0);
2324 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2326 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2327 if (result == GNOME_VFS_OK) {
2328 TnyMimePart *mime_part;
2330 const gchar *mime_type = NULL;
2332 gchar *escaped_filename;
2335 GnomeVFSFileInfo *info;
2336 GnomeVFSURI *vfs_uri;
2338 gnome_vfs_close (handle);
2339 vfs_uri = gnome_vfs_uri_new (uri);
2342 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2343 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2344 g_free (escaped_filename);
2345 gnome_vfs_uri_unref (vfs_uri);
2347 info = gnome_vfs_file_info_new ();
2349 if (gnome_vfs_get_file_info (uri,
2351 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2353 mime_type = gnome_vfs_file_info_get_mime_type (info);
2354 mime_part = tny_platform_factory_new_mime_part
2355 (modest_runtime_get_platform_factory ());
2357 /* try to get the attachment's size; this may fail for weird
2358 * file systems, like obex, upnp... */
2359 if (allowed_size != 0 &&
2360 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2362 if (size > allowed_size) {
2363 g_warning ("%s: attachment too big", __FUNCTION__);
2364 modest_platform_information_banner (NULL, NULL, dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2368 g_warning ("%s: could not get attachment size", __FUNCTION__);
2370 stream = create_stream_for_uri (uri);
2372 if (stream == NULL) {
2374 modest_platform_information_banner (NULL, NULL, dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2376 g_object_unref (mime_part);
2377 gnome_vfs_file_info_unref (info);
2381 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2382 g_object_unref (stream);
2384 content_id = g_strdup_printf ("%d", priv->next_cid);
2385 tny_mime_part_set_content_id (mime_part, content_id);
2386 g_free (content_id);
2389 basename = g_path_get_basename (filename);
2390 tny_mime_part_set_filename (mime_part, basename);
2393 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2394 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2396 info->size == 0, info->size);
2397 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2398 gtk_widget_show_all (priv->attachments_caption);
2399 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2401 g_object_unref (mime_part);
2402 gnome_vfs_file_info_unref (info);
2409 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2412 ModestMsgEditWindowPrivate *priv;
2415 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2416 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2418 if (att_list == NULL) {
2419 att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2421 g_object_ref (att_list);
2424 if (tny_list_get_length (att_list) == 0) {
2425 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2427 GtkWidget *confirmation_dialog = NULL;
2428 gboolean dialog_response;
2429 gchar *message = NULL;
2430 gchar *filename = NULL;
2432 if (tny_list_get_length (att_list) == 1) {
2434 iter = tny_list_create_iterator (att_list);
2435 part = (TnyMimePart *) tny_iterator_get_current (iter);
2436 g_object_unref (iter);
2437 if (TNY_IS_MSG (part)) {
2438 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2440 filename = tny_header_dup_subject (header);
2441 g_object_unref (header);
2443 if (filename == NULL) {
2444 filename = g_strdup (_("mail_va_no_subject"));
2447 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2449 g_object_unref (part);
2451 filename = g_strdup ("");
2453 message = g_strdup_printf (ngettext("emev_nc_delete_attachment", "emev_nc_delete_attachments",
2454 tny_list_get_length (att_list)), filename);
2456 confirmation_dialog = hildon_note_new_confirmation (GTK_WINDOW (window), message);
2458 dialog_response = (gtk_dialog_run (GTK_DIALOG (confirmation_dialog))==GTK_RESPONSE_OK);
2459 gtk_widget_destroy (confirmation_dialog);
2460 if (!dialog_response) {
2461 g_object_unref (att_list);
2464 hildon_banner_show_information (NULL, NULL, _("mcen_ib_removing_attachment"));
2466 for (iter = tny_list_create_iterator (att_list);
2467 !tny_iterator_is_done (iter);
2468 tny_iterator_next (iter)) {
2469 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2470 const gchar *att_id;
2471 tny_list_remove (priv->attachments, (GObject *) mime_part);
2473 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2475 if (tny_list_get_length (priv->attachments) == 0)
2476 gtk_widget_hide (priv->attachments_caption);
2477 att_id = tny_mime_part_get_content_id (mime_part);
2479 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2481 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2482 g_object_unref (mime_part);
2484 g_object_unref (iter);
2487 g_object_unref (att_list);
2489 /* if the last attachment has been removed, focus the Subject: field */
2490 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2491 gtk_widget_grab_focus (priv->subject_field);
2495 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2498 ModestMsgEditWindowPrivate *priv;
2499 GdkColor *new_color;
2500 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2502 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2503 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2506 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2508 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2510 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2512 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2517 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
2520 ModestMsgEditWindowPrivate *priv;
2521 gint new_size_index;
2522 ModestMsgEditWindow *window;
2525 window = MODEST_MSG_EDIT_WINDOW (userdata);
2526 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2527 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2529 if (gtk_check_menu_item_get_active (menu_item)) {
2531 WPTextBufferFormat format;
2533 memset (&format, 0, sizeof (format));
2534 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2536 label = gtk_bin_get_child (GTK_BIN (menu_item));
2538 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
2539 format.cs.font_size = TRUE;
2540 format.cs.text_position = TRUE;
2541 format.cs.font = TRUE;
2542 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
2543 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2545 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2546 GINT_TO_POINTER (wp_get_font_size_index (new_size_index, 12))))
2547 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2549 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2550 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
2551 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2557 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
2560 ModestMsgEditWindowPrivate *priv;
2561 gint new_font_index;
2562 ModestMsgEditWindow *window;
2565 window = MODEST_MSG_EDIT_WINDOW (userdata);
2566 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2567 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2569 if (gtk_check_menu_item_get_active (menu_item)) {
2572 label = gtk_bin_get_child (GTK_BIN (menu_item));
2574 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
2576 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2577 GINT_TO_POINTER(new_font_index)))
2578 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2580 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2581 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2582 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2588 modest_msg_edit_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
2590 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
2591 ModestWindowPrivate *parent_priv;
2592 ModestWindowMgr *mgr;
2593 gboolean is_fullscreen;
2594 GtkAction *fs_toggle_action;
2597 mgr = modest_runtime_get_window_mgr ();
2598 is_fullscreen = (modest_window_mgr_get_fullscreen_mode (mgr))?1:0;
2600 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
2602 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
2603 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
2604 if (is_fullscreen != active)
2605 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
2613 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2616 ModestMsgEditWindowPrivate *priv = NULL;
2617 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2619 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2620 if (!priv->update_caption_visibility)
2623 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2625 gtk_widget_show (priv->cc_caption);
2627 gtk_widget_hide (priv->cc_caption);
2629 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2633 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2636 ModestMsgEditWindowPrivate *priv = NULL;
2637 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2639 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2640 if (!priv->update_caption_visibility)
2643 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2645 gtk_widget_show (priv->bcc_caption);
2647 gtk_widget_hide (priv->bcc_caption);
2649 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2653 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2654 ModestRecptEditor *editor)
2656 ModestMsgEditWindowPrivate *priv;
2658 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2659 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2661 /* we check for low-mem; in that case, show a warning, and don't allow
2662 * for the addressbook
2664 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2667 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2669 if (editor == NULL) {
2670 GtkWidget *view_focus;
2671 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2673 /* This code should be kept in sync with ModestRecptEditor. The
2674 textview inside the recpt editor is the one that really gets the
2675 focus. As it's inside a scrolled window, and this one inside the
2676 hbox recpt editor inherits from, we'll need to go up in the
2677 hierarchy to know if the text view is part of the recpt editor
2678 or if it's a different text entry */
2680 if (gtk_widget_get_parent (view_focus)) {
2681 GtkWidget *first_parent;
2683 first_parent = gtk_widget_get_parent (view_focus);
2684 if (gtk_widget_get_parent (first_parent) &&
2685 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2686 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2691 editor = MODEST_RECPT_EDITOR (priv->to_field);
2695 modest_address_book_select_addresses (editor);
2700 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2702 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2704 modest_msg_edit_window_open_addressbook (window, NULL);
2708 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2709 gboolean show_toolbar)
2711 ModestWindowPrivate *parent_priv;
2712 const gchar *action_name;
2715 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2716 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2718 /* We can not just use the code of
2719 modest_msg_edit_window_setup_toolbar because it has a
2720 mixture of both initialization and creation code. */
2722 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2724 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2726 /* Update also the actions (to update the toggles in the
2727 menus), we have to do it manually because some other window
2728 of the same time could have changed it (remember that the
2729 toolbar fullscreen mode is shared by all the windows of the
2731 if (modest_window_mgr_get_fullscreen_mode (modest_runtime_get_window_mgr ()))
2732 action_name = "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarFullScreenMenu";
2734 action_name = "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarNormalScreenMenu";
2736 action = gtk_ui_manager_get_action (parent_priv->ui_manager, action_name);
2737 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
2743 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2744 TnyHeaderFlags priority_flags)
2746 ModestMsgEditWindowPrivate *priv;
2747 ModestWindowPrivate *parent_priv;
2749 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2751 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2752 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2754 if (priv->priority_flags != priority_flags) {
2755 GtkAction *priority_action = NULL;
2757 priv->priority_flags = priority_flags;
2759 switch (priority_flags) {
2760 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2761 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_high", GTK_ICON_SIZE_MENU);
2762 gtk_widget_show (priv->priority_icon);
2763 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2764 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2766 case TNY_HEADER_FLAG_LOW_PRIORITY:
2767 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_low", GTK_ICON_SIZE_MENU);
2768 gtk_widget_show (priv->priority_icon);
2769 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2770 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2773 gtk_widget_hide (priv->priority_icon);
2774 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2775 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2778 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2779 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2784 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2787 ModestMsgEditWindowPrivate *priv;
2788 ModestWindowPrivate *parent_priv;
2789 gint current_format;
2791 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2793 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2794 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2796 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2797 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2799 if (current_format != file_format) {
2800 switch (file_format) {
2801 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2802 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2803 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
2805 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2809 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2810 response = gtk_dialog_run (GTK_DIALOG (dialog));
2811 gtk_widget_destroy (dialog);
2812 if (response == GTK_RESPONSE_OK) {
2813 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2815 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu"));
2816 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
2821 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2822 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2827 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2830 ModestMsgEditWindowPrivate *priv;
2831 WPTextBufferFormat oldfmt, fmt;
2832 gint old_position = 0;
2836 GdkColor *color = NULL;
2837 gboolean bold, bold_set, italic, italic_set;
2838 gboolean underline, underline_set;
2839 gboolean strikethrough, strikethrough_set;
2840 gboolean position_set;
2841 gboolean font_size_set, font_set, color_set;
2844 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2845 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2847 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2848 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
2849 GTK_WINDOW(dialog));
2851 /* First we get the currently selected font information */
2852 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2854 switch (oldfmt.text_position) {
2855 case TEXT_POSITION_NORMAL:
2858 case TEXT_POSITION_SUPERSCRIPT:
2866 g_object_set (G_OBJECT (dialog),
2867 "bold", oldfmt.bold != FALSE,
2868 "bold-set", !oldfmt.cs.bold,
2869 "underline", oldfmt.underline != FALSE,
2870 "underline-set", !oldfmt.cs.underline,
2871 "italic", oldfmt.italic != FALSE,
2872 "italic-set", !oldfmt.cs.italic,
2873 "strikethrough", oldfmt.strikethrough != FALSE,
2874 "strikethrough-set", !oldfmt.cs.strikethrough,
2875 "color", &oldfmt.color,
2876 "color-set", !oldfmt.cs.color,
2877 "size", wp_font_size[oldfmt.font_size],
2878 "size-set", !oldfmt.cs.font_size,
2879 "position", old_position,
2880 "position-set", !oldfmt.cs.text_position,
2881 "family", wp_get_font_name (oldfmt.font),
2882 "family-set", !oldfmt.cs.font,
2885 gtk_widget_show_all (dialog);
2886 priv->font_dialog = dialog;
2887 response = gtk_dialog_run (GTK_DIALOG (dialog));
2888 priv->font_dialog = NULL;
2889 if (response == GTK_RESPONSE_OK) {
2891 g_object_get( dialog,
2893 "bold-set", &bold_set,
2894 "underline", &underline,
2895 "underline-set", &underline_set,
2897 "italic-set", &italic_set,
2898 "strikethrough", &strikethrough,
2899 "strikethrough-set", &strikethrough_set,
2901 "color-set", &color_set,
2903 "size-set", &font_size_set,
2904 "family", &font_name,
2905 "family-set", &font_set,
2906 "position", &position,
2907 "position-set", &position_set,
2912 if (response == GTK_RESPONSE_OK) {
2913 memset(&fmt, 0, sizeof(fmt));
2919 fmt.italic = italic;
2920 fmt.cs.italic = TRUE;
2922 if (underline_set) {
2923 fmt.underline = underline;
2924 fmt.cs.underline = TRUE;
2926 if (strikethrough_set) {
2927 fmt.strikethrough = strikethrough;
2928 fmt.cs.strikethrough = TRUE;
2933 ? TEXT_POSITION_NORMAL
2934 : ( ( position == 1 )
2935 ? TEXT_POSITION_SUPERSCRIPT
2936 : TEXT_POSITION_SUBSCRIPT );
2937 fmt.cs.text_position = TRUE;
2938 fmt.font_size = oldfmt.font_size;
2942 fmt.cs.color = TRUE;
2945 fmt.font = wp_get_font_index(font_name,
2950 if (font_size_set) {
2951 fmt.cs.font_size = TRUE;
2952 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
2954 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2955 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2957 gtk_widget_destroy (dialog);
2959 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2963 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2965 ModestMsgEditWindowPrivate *priv;
2967 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2968 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2970 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2972 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2973 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2978 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
2980 ModestMsgEditWindowPrivate *priv;
2982 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2983 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2985 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
2987 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2988 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2993 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
2995 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2997 priv->can_undo = can_undo;
3001 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
3003 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3005 priv->can_redo = can_redo;
3009 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3011 ModestMsgEditWindowPrivate *priv;
3012 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3013 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3015 return priv->can_undo;
3019 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3021 ModestMsgEditWindowPrivate *priv;
3022 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3023 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3025 return priv->can_redo;
3030 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3033 GtkTextIter match_start, match_end;
3035 if (image_id == NULL)
3038 gtk_text_buffer_get_start_iter (buffer, &iter);
3040 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3041 GSList *tags = gtk_text_iter_get_tags (&match_start);
3043 for (node = tags; node != NULL; node = g_slist_next (node)) {
3044 GtkTextTag *tag = (GtkTextTag *) node->data;
3045 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3046 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3047 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3049 offset = gtk_text_iter_get_offset (&match_start);
3050 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3051 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3055 gtk_text_iter_forward_char (&iter);
3060 message_is_empty (ModestMsgEditWindow *window)
3062 ModestMsgEditWindowPrivate *priv = NULL;
3064 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3065 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3067 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3068 * so we can ignore markup.
3070 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3073 count = gtk_text_buffer_get_char_count (buf);
3079 msg_body_focus (GtkWidget *focus,
3080 GdkEventFocus *event,
3084 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3085 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3086 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3091 recpt_field_changed (GtkTextBuffer *buffer,
3092 ModestMsgEditWindow *editor)
3094 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3095 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3099 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3101 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3102 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3106 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3109 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3110 GtkTextBuffer *buffer;
3112 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3113 gtk_text_buffer_set_modified (buffer, modified);
3114 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3115 gtk_text_buffer_set_modified (buffer, modified);
3116 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3117 gtk_text_buffer_set_modified (buffer, modified);
3118 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3122 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3124 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3125 const char *account_name;
3126 GtkTextBuffer *buffer;
3128 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3129 if (gtk_text_buffer_get_modified (buffer))
3131 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3132 if (gtk_text_buffer_get_modified (buffer))
3134 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3135 if (gtk_text_buffer_get_modified (buffer))
3137 if (gtk_text_buffer_get_modified (priv->text_buffer))
3139 account_name = modest_combo_box_get_active_id (MODEST_COMBO_BOX (priv->from_field));
3140 if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3151 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3153 ModestMsgEditWindowPrivate *priv = NULL;
3155 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3156 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3158 /* check if there's no recipient added */
3159 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3160 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3161 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3162 /* no recipient contents, then select contacts */
3163 modest_msg_edit_window_open_addressbook (window, NULL);
3167 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3168 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3171 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3172 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3175 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3176 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3180 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3181 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3182 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3189 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3190 ModestMsgEditWindow *window)
3192 modest_msg_edit_window_offer_attach_file (window);
3196 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3198 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3200 return priv->clipboard_text;
3204 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3206 ModestMsgEditWindow *window)
3208 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3209 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3211 if (!GTK_WIDGET_VISIBLE (window))
3214 g_object_ref (window);
3215 text = gtk_clipboard_wait_for_text (selection_clipboard);
3217 if (priv->clipboard_text != NULL) {
3218 g_free (priv->clipboard_text);
3220 priv->clipboard_text = text;
3222 if (GTK_WIDGET_VISIBLE (window)) {
3223 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3225 g_object_unref (window);
3228 static gboolean clipboard_owner_change_idle (gpointer userdata)
3230 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3231 ModestMsgEditWindowPrivate *priv;
3233 gdk_threads_enter ();
3234 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3235 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3237 priv->clipboard_owner_idle = 0;
3238 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3239 gdk_threads_leave ();
3245 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3247 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3248 if (priv->clipboard_owner_idle == 0) {
3249 priv->clipboard_owner_idle = g_idle_add (clipboard_owner_change_idle, window);
3254 subject_field_move_cursor (GtkEntry *entry,
3255 GtkMovementStep step,
3260 if (!GTK_WIDGET_VISIBLE (window))
3263 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3267 update_window_title (ModestMsgEditWindow *window)
3269 ModestMsgEditWindowPrivate *priv = NULL;
3270 const gchar *subject;
3272 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3273 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3274 if (subject == NULL || subject[0] == '\0')
3275 subject = _("mail_va_new_email");
3277 gtk_window_set_title (GTK_WINDOW (window), subject);
3282 subject_field_changed (GtkEditable *editable,
3283 ModestMsgEditWindow *window)
3285 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3286 update_window_title (window);
3287 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3288 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3289 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3293 subject_field_insert_text (GtkEditable *editable,
3295 gint new_text_length,
3297 ModestMsgEditWindow *window)
3299 GString *result = g_string_new ("");
3301 gint result_len = 0;
3302 const gchar *entry_text = NULL;
3305 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3306 old_length = g_utf8_strlen (entry_text, -1);
3308 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3309 gunichar c = g_utf8_get_char_validated (current, 8);
3310 /* Invalid unichar, stop */
3316 result = g_string_append_unichar (result, c);
3320 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3321 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3324 /* Prevent endless recursion */
3325 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3326 g_signal_emit_by_name (editable, "insert-text",
3327 (gpointer) result->str, (gpointer) result->len,
3328 (gpointer) position, (gpointer) window);
3329 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3333 if (result_len + old_length > 1000) {
3334 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3335 dgettext("hildon-common-strings",
3336 "ckdg_ib_maximum_characters_reached"));
3339 g_string_free (result, TRUE);
3343 text_buffer_insert_text (GtkTextBuffer *buffer,
3346 gint new_text_length,
3347 ModestMsgEditWindow *window)
3349 GString *result = g_string_new ("");
3351 gint result_len = 0;
3352 gboolean changed = FALSE;
3354 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3355 gunichar c = g_utf8_get_char_validated (current, 8);
3356 /* Invalid unichar, stop */
3362 result = g_string_append_c (result, ' ');
3366 result = g_string_append_unichar (result, c);
3372 g_signal_stop_emission_by_name (G_OBJECT (buffer), "insert-text");
3373 g_signal_handlers_block_by_func(G_OBJECT(buffer), G_CALLBACK(text_buffer_insert_text), window);
3374 g_signal_emit_by_name (buffer, "insert-text",
3376 (gpointer) result->str, (gpointer) result->len,
3378 g_signal_handlers_unblock_by_func(G_OBJECT(buffer), G_CALLBACK(text_buffer_insert_text), window);
3381 g_string_free (result, TRUE);
3385 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3388 ModestMsgEditWindowPrivate *priv = NULL;
3390 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3391 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3393 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3396 gtk_widget_show_all (priv->find_toolbar);
3397 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3399 gtk_widget_hide_all (priv->find_toolbar);
3400 gtk_widget_grab_focus (priv->msg_body);
3406 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3408 GtkTextIter *match_start,
3409 GtkTextIter *match_end)
3411 GtkTextIter end_iter;
3412 gchar *str_casefold;
3415 gchar *range_casefold;
3418 gboolean result = FALSE;
3425 gtk_text_iter_forward_to_end (&end_iter);
3427 str_casefold = g_utf8_casefold (str, -1);
3428 str_chars_n = strlen (str);
3430 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3431 range_casefold = g_utf8_casefold (range_text, -1);
3432 range_chars_n = strlen (range_casefold);
3434 if (range_chars_n < str_chars_n) {
3435 g_free (str_casefold);
3436 g_free (range_text);
3437 g_free (range_casefold);
3441 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3442 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3443 if (!g_utf8_collate (range_subtext, str_casefold)) {
3444 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3446 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3447 match_start, match_end, NULL);
3448 g_free (found_text);
3450 g_free (range_subtext);
3454 g_free (str_casefold);
3455 g_free (range_text);
3456 g_free (range_casefold);
3463 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3464 ModestMsgEditWindow *window)
3466 gchar *current_search = NULL;
3467 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3469 GtkTextIter selection_start, selection_end;
3470 GtkTextIter match_start, match_end;
3471 gboolean continue_search = FALSE;
3473 if (message_is_empty (window)) {
3474 g_free (priv->last_search);
3475 priv->last_search = NULL;
3476 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3480 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3481 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3482 g_free (current_search);
3483 g_free (priv->last_search);
3484 priv->last_search = NULL;
3485 /* Information banner about empty search */
3486 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-common-strings", "ecdg_ib_find_rep_enter_text"));
3490 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3491 continue_search = TRUE;
3493 g_free (priv->last_search);
3494 priv->last_search = g_strdup (current_search);
3497 if (continue_search) {
3498 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3499 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3500 &match_start, &match_end);
3502 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_search_complete"));
3504 GtkTextIter buffer_start;
3505 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3506 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3507 &match_start, &match_end);
3509 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_no_matches"));
3512 /* Mark as selected the string found in search */
3514 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3515 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3516 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3518 g_free (priv->last_search);
3519 priv->last_search = NULL;
3521 g_free (current_search);
3525 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3526 ModestMsgEditWindow *window)
3528 GtkToggleAction *toggle;
3529 ModestWindowPrivate *parent_priv;
3530 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3532 toggle = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ToolsMenu/FindInMessageMenu"));
3533 gtk_toggle_action_set_active (toggle, FALSE);
3537 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3539 ModestMsgEditWindowPrivate *priv;
3541 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3546 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3549 ModestMsgEditWindowPrivate *priv;
3551 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3557 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3560 ModestMsgEditWindowPrivate *priv;
3561 TnyHeader *header = NULL;
3563 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3564 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3566 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3567 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3569 if (priv->draft_msg != NULL) {
3570 g_object_unref (priv->draft_msg);
3573 if (draft != NULL) {
3574 g_object_ref (draft);
3575 header = tny_msg_get_header (draft);
3576 if (priv->msg_uid) {
3577 g_free (priv->msg_uid);
3578 priv->msg_uid = NULL;
3580 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3581 if (GTK_WIDGET_REALIZED (window))
3582 modest_window_mgr_register_window (mgr, MODEST_WINDOW (window));
3585 priv->draft_msg = draft;
3589 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3590 GtkTextIter *start, GtkTextIter *end,
3593 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3594 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3597 if (tag == NULL+13) return;
3598 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3599 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3600 replace_with_images (window, priv->images);
3605 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3608 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3610 g_return_if_fail (TNY_IS_MIME_PART (part));
3611 tny_list_prepend (priv->attachments, (GObject *) part);
3612 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3613 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3614 gtk_widget_show_all (priv->attachments_caption);
3615 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3619 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3621 ModestMsgEditWindowPrivate *priv;
3623 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3624 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3626 return priv->msg_uid;
3630 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3631 ModestMsgEditWindowWidgetType widget_type)
3633 ModestMsgEditWindowPrivate *priv;
3635 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3636 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3638 switch (widget_type) {
3639 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3640 return priv->msg_body;
3642 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3643 return priv->to_field;
3645 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3646 return priv->cc_field;
3648 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3649 return priv->bcc_field;
3651 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3652 return priv->subject_field;
3654 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3655 return priv->attachments_view;
3663 remove_tags (WPTextBuffer *buffer)
3665 GtkTextIter start, end;
3667 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3668 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3670 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3674 on_account_removed (TnyAccountStore *account_store,
3675 TnyAccount *account,
3678 /* Do nothing if it's a store account, because we use the
3679 transport to send the messages */
3680 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3681 const gchar *parent_acc = NULL;
3682 const gchar *our_acc = NULL;
3684 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3685 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3686 /* Close this window if I'm showing a message of the removed account */
3687 if (strcmp (parent_acc, our_acc) == 0)
3688 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3693 on_zoom_minus_plus_not_implemented (ModestWindow *window)
3695 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3697 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
3703 set_zoom_do_nothing (ModestWindow *window,
3709 get_zoom_do_nothing (ModestWindow *window)