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;
273 guint scroll_drag_timeout_id;
277 TnyList *attachments;
282 TnyHeaderFlags priority_flags;
284 gboolean can_undo, can_redo;
285 gulong clipboard_change_handler_id;
286 gulong default_clipboard_change_handler_id;
287 gulong account_removed_handler_id;
288 guint clipboard_owner_idle;
289 gchar *clipboard_text;
298 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
299 MODEST_TYPE_MSG_EDIT_WINDOW, \
300 ModestMsgEditWindowPrivate))
302 static GtkWindowClass *parent_class = NULL;
304 /* uncomment the following if you have defined any signals */
305 /* static guint signals[LAST_SIGNAL] = {0}; */
308 modest_msg_edit_window_get_type (void)
310 static GType my_type = 0;
312 static const GTypeInfo my_info = {
313 sizeof(ModestMsgEditWindowClass),
314 NULL, /* base init */
315 NULL, /* base finalize */
316 (GClassInitFunc) modest_msg_edit_window_class_init,
317 NULL, /* class finalize */
318 NULL, /* class data */
319 sizeof(ModestMsgEditWindow),
321 (GInstanceInitFunc) modest_msg_edit_window_init,
324 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
325 "ModestMsgEditWindow",
333 save_state (ModestWindow *self)
335 modest_widget_memory_save (modest_runtime_get_conf(),
336 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
341 restore_settings (ModestMsgEditWindow *self)
343 ModestConf *conf = NULL;
345 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
347 conf = modest_runtime_get_conf ();
348 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
349 "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarNormalScreenMenu");
350 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
351 modest_conf_get_bool (conf, MODEST_CONF_EDIT_WINDOW_SHOW_TOOLBAR, NULL));
352 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
353 "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarFullScreenMenu");
354 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
355 modest_conf_get_bool (conf, MODEST_CONF_EDIT_WINDOW_SHOW_TOOLBAR_FULLSCREEN, NULL));
357 /* set initial state of cc and bcc */
358 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewCcFieldMenu");
359 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
360 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, NULL));
361 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewBccFieldMenu");
362 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
363 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, NULL));
365 /* Dim at start clipboard actions */
366 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
367 gtk_action_set_sensitive (action, FALSE);
368 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
369 gtk_action_set_sensitive (action, FALSE);
370 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
371 gtk_action_set_sensitive (action, FALSE);
373 modest_widget_memory_restore (conf,
374 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
379 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
381 GObjectClass *gobject_class;
382 ModestWindowClass *modest_window_class;
383 gobject_class = (GObjectClass*) klass;
384 modest_window_class = (ModestWindowClass*) klass;
386 parent_class = g_type_class_peek_parent (klass);
387 gobject_class->finalize = modest_msg_edit_window_finalize;
389 modest_window_class->set_zoom_func = set_zoom_do_nothing;
390 modest_window_class->get_zoom_func = get_zoom_do_nothing;
391 modest_window_class->zoom_plus_func = on_zoom_minus_plus_not_implemented;
392 modest_window_class->zoom_minus_func = on_zoom_minus_plus_not_implemented;
393 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
394 modest_window_class->save_state_func = save_state;
395 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
397 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
401 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
403 ModestMsgEditWindowPrivate *priv;
404 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
406 priv->msg_body = NULL;
408 priv->from_field = NULL;
409 priv->to_field = NULL;
410 priv->cc_field = NULL;
411 priv->bcc_field = NULL;
412 priv->subject_field = NULL;
413 priv->attachments = TNY_LIST (tny_simple_list_new ());
414 priv->images = TNY_LIST (tny_simple_list_new ());
415 priv->images_size = 0;
416 priv->images_count = 0;
419 priv->cc_caption = NULL;
420 priv->bcc_caption = NULL;
421 priv->update_caption_visibility = FALSE;
423 priv->priority_flags = 0;
425 priv->find_toolbar = NULL;
426 priv->last_search = NULL;
428 priv->draft_msg = NULL;
429 priv->outbox_msg = NULL;
430 priv->msg_uid = NULL;
432 priv->can_undo = FALSE;
433 priv->can_redo = FALSE;
434 priv->clipboard_change_handler_id = 0;
435 priv->default_clipboard_change_handler_id = 0;
436 priv->account_removed_handler_id = 0;
437 priv->clipboard_owner_idle = 0;
438 priv->clipboard_text = NULL;
441 priv->scroll_drag_timeout_id = 0;
442 priv->last_upper = 0.0;
444 modest_window_mgr_register_help_id (modest_runtime_get_window_mgr(),
445 GTK_WINDOW(obj),"applications_email_editor");
447 if (!is_wp_text_buffer_started) {
448 is_wp_text_buffer_started = TRUE;
449 wp_text_buffer_library_init ();
454 hildon_program_add_window (hildon_program_get_instance(),
459 /* FIXME: this is a dup from the one in gtk/ */
462 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
464 static ModestPairList*
465 get_transports (void)
467 GSList *transports = NULL;
469 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
470 GSList *accounts = modest_account_mgr_account_names (account_mgr,
471 TRUE /* only enabled accounts. */);
473 GSList *cursor = accounts;
475 gchar *account_name = cursor->data;
476 gchar *from_string = NULL;
478 from_string = modest_account_mgr_get_from_string (account_mgr,
482 if (from_string && account_name) {
483 gchar *name = account_name;
484 ModestPair *pair = modest_pair_new ((gpointer) name,
485 (gpointer) from_string , TRUE);
486 transports = g_slist_prepend (transports, pair);
489 cursor = cursor->next;
491 g_slist_free (accounts); /* only free the accounts, not the elements,
492 * because they are used in the pairlist */
496 static void window_focus (GtkWindow *window,
500 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
504 scroll_drag_timeout (gpointer userdata)
506 ModestMsgEditWindow *win = (ModestMsgEditWindow *) userdata;
507 ModestMsgEditWindowPrivate *priv;
509 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(win);
511 correct_scroll_without_drag_check (win, TRUE);
513 priv->scroll_drag_timeout_id = 0;
519 correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused)
521 ModestMsgEditWindowPrivate *priv;
524 GdkRectangle rectangle;
530 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
532 if (only_if_focused && !gtk_widget_is_focus (priv->msg_body))
535 insert = gtk_text_buffer_get_insert (priv->text_buffer);
536 gtk_text_buffer_get_iter_at_mark (priv->text_buffer, &iter, insert);
538 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &iter, &rectangle);
539 vadj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll));
540 offset = priv->msg_body->allocation.y;
542 new_value = vadj->value;
544 if ((offset + rectangle.y + rectangle.height) >
545 ((gint) (vadj->value +vadj->page_size))) {
546 new_value = (offset + rectangle.y) - vadj->page_size * 0.25;
547 if (new_value > vadj->upper - vadj->page_size)
548 new_value = vadj->upper - vadj->page_size;
549 } else if ((offset + rectangle.y) < ((gint) vadj->value)) {
550 new_value = (offset + rectangle.y - vadj->page_size * 0.75);
551 if (((gint) (new_value + vadj->page_size)) < (offset + rectangle.y + rectangle.height))
552 new_value = offset + rectangle.y + rectangle.height - (gint) vadj->page_size;
555 if (new_value > vadj->value)
556 new_value = vadj->value;
559 if (vadj->value != new_value) {
560 g_signal_emit_by_name (GTK_TEXT_VIEW(priv->msg_body)->layout,
562 vadj->value = new_value;
563 gtk_adjustment_value_changed (vadj);
564 /* invalidate body */
565 window = gtk_widget_get_parent_window (priv->msg_body);
567 gdk_window_invalidate_rect (window, NULL, TRUE);
573 correct_scroll (ModestMsgEditWindow *w)
575 ModestMsgEditWindowPrivate *priv;
577 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
578 if (gtk_grab_get_current () == priv->msg_body) {
579 if (priv->scroll_drag_timeout_id == 0) {
580 priv->scroll_drag_timeout_id = g_timeout_add (500, (GSourceFunc) scroll_drag_timeout,
586 correct_scroll_without_drag_check (w, TRUE);
590 text_buffer_end_user_action (GtkTextBuffer *buffer,
591 ModestMsgEditWindow *userdata)
594 correct_scroll (userdata);
598 text_buffer_mark_set (GtkTextBuffer *buffer,
601 ModestMsgEditWindow *userdata)
603 gtk_text_buffer_begin_user_action (buffer);
604 gtk_text_buffer_end_user_action (buffer);
608 cut_clipboard_check (GtkTextView *text_view,
611 GtkTextBuffer *buffer;
613 buffer = gtk_text_view_get_buffer (text_view);
614 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
615 g_signal_stop_emission_by_name ((gpointer )text_view, "cut-clipboard");
620 copy_clipboard_check (GtkTextView *text_view,
623 GtkTextBuffer *buffer;
625 buffer = gtk_text_view_get_buffer (text_view);
626 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
627 g_signal_stop_emission_by_name ((gpointer )text_view, "copy-clipboard");
631 void vadj_changed (GtkAdjustment *adj,
632 ModestMsgEditWindow *window)
634 ModestMsgEditWindowPrivate *priv;
636 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
638 if (priv->last_upper != adj->upper) {
639 priv->last_upper = adj->upper;
640 correct_scroll (window);
645 connect_signals (ModestMsgEditWindow *obj)
647 ModestMsgEditWindowPrivate *priv;
649 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
651 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
652 G_CALLBACK (text_buffer_refresh_attributes), obj);
653 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
654 G_CALLBACK (text_buffer_can_undo), obj);
655 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
656 G_CALLBACK (text_buffer_can_redo), obj);
657 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
658 G_CALLBACK (body_changed), obj);
659 g_signal_connect (G_OBJECT (priv->text_buffer), "modified-changed",
660 G_CALLBACK (body_changed), obj);
661 g_signal_connect (G_OBJECT (priv->text_buffer), "insert-text",
662 G_CALLBACK (text_buffer_insert_text), obj);
663 g_signal_connect (G_OBJECT (obj), "window-state-event",
664 G_CALLBACK (modest_msg_edit_window_window_state_event),
666 g_signal_connect (G_OBJECT (priv->text_buffer), "end-user-action",
667 G_CALLBACK (text_buffer_end_user_action), obj);
668 g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
669 G_CALLBACK (text_buffer_mark_set), obj);
670 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
671 G_CALLBACK (text_buffer_apply_tag), obj);
672 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
673 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
674 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
675 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
676 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
677 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
679 g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
680 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
682 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
683 G_CALLBACK (msg_body_focus), obj);
684 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
685 G_CALLBACK (msg_body_focus), obj);
686 g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
687 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
688 "changed", G_CALLBACK (recpt_field_changed), obj);
689 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
690 "changed", G_CALLBACK (recpt_field_changed), obj);
691 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
692 "changed", G_CALLBACK (recpt_field_changed), obj);
693 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
694 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
695 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
697 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
698 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
700 g_signal_connect (G_OBJECT (gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll))),
702 G_CALLBACK (vadj_changed),
705 priv->clipboard_change_handler_id =
706 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
707 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
708 priv->default_clipboard_change_handler_id =
709 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
710 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
712 g_signal_connect (G_OBJECT (priv->msg_body), "cut-clipboard", G_CALLBACK (cut_clipboard_check), NULL);
713 g_signal_connect (G_OBJECT (priv->msg_body), "copy-clipboard", G_CALLBACK (copy_clipboard_check), NULL);
718 init_window (ModestMsgEditWindow *obj)
720 GtkWidget *from_caption, *to_caption, *subject_caption;
721 GtkWidget *main_vbox;
722 ModestMsgEditWindowPrivate *priv;
723 GtkActionGroup *action_group;
724 ModestWindowPrivate *parent_priv;
725 GdkPixbuf *window_icon = NULL;
726 GError *error = NULL;
728 GtkSizeGroup *size_group;
729 GtkWidget *subject_box;
730 GtkWidget *attachment_icon;
731 GtkWidget *window_box;
732 #if (GTK_MINOR_VERSION >= 10)
733 GdkAtom deserialize_type;
735 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
736 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
738 parent_priv->ui_manager = gtk_ui_manager_new();
739 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
740 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
742 /* Add common actions */
743 gtk_action_group_add_actions (action_group,
744 modest_msg_edit_action_entries,
745 G_N_ELEMENTS (modest_msg_edit_action_entries),
747 gtk_action_group_add_toggle_actions (action_group,
748 modest_msg_edit_toggle_action_entries,
749 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
751 gtk_action_group_add_radio_actions (action_group,
752 modest_msg_edit_alignment_radio_action_entries,
753 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
755 G_CALLBACK (modest_ui_actions_on_change_justify),
757 gtk_action_group_add_radio_actions (action_group,
758 modest_msg_edit_priority_action_entries,
759 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
761 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
763 gtk_action_group_add_radio_actions (action_group,
764 modest_msg_edit_file_format_action_entries,
765 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
766 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
767 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
769 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
770 g_object_unref (action_group);
772 /* Load the UI definition */
773 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
776 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
777 g_clear_error (&error);
780 /* Add accelerators */
781 gtk_window_add_accel_group (GTK_WINDOW (obj),
782 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
784 parent_priv->menubar = NULL;
786 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
788 /* Note: This ModestPairList* must exist for as long as the combo
789 * that uses it, because the ModestComboBox uses the ID opaquely,
790 * so it can't know how to manage its memory. */
791 priv->from_field = modest_combo_box_new (NULL, g_str_equal);
793 priv->to_field = modest_recpt_editor_new ();
794 priv->cc_field = modest_recpt_editor_new ();
795 priv->bcc_field = modest_recpt_editor_new ();
796 subject_box = gtk_hbox_new (FALSE, 0);
797 priv->priority_icon = gtk_image_new ();
798 gtk_box_pack_start (GTK_BOX (subject_box), priv->priority_icon, FALSE, FALSE, 0);
799 priv->subject_field = gtk_entry_new_with_max_length (SUBJECT_MAX_LENGTH);
800 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
801 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
802 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
803 gtk_box_pack_start (GTK_BOX (subject_box), priv->subject_field, TRUE, TRUE, 0);
804 priv->add_attachment_button = gtk_button_new ();
805 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
806 gtk_button_set_relief (GTK_BUTTON (priv->add_attachment_button), GTK_RELIEF_NONE);
807 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
808 gtk_button_set_alignment (GTK_BUTTON (priv->add_attachment_button), 1.0, 1.0);
809 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, GTK_ICON_SIZE_BUTTON);
810 gtk_container_add (GTK_CONTAINER (priv->add_attachment_button), attachment_icon);
811 gtk_box_pack_start (GTK_BOX (subject_box), priv->add_attachment_button, FALSE, FALSE, 0);
812 priv->attachments_view = modest_attachments_view_new (NULL);
814 priv->header_box = gtk_vbox_new (FALSE, 0);
816 from_caption = hildon_caption_new (size_group, _("mail_va_from"), priv->from_field, NULL, 0);
817 to_caption = hildon_caption_new (size_group, _("mail_va_to"), priv->to_field, NULL, 0);
818 priv->cc_caption = hildon_caption_new (size_group, _("mail_va_cc"), priv->cc_field, NULL, 0);
819 priv->bcc_caption = hildon_caption_new (size_group, _("mail_va_hotfix1"), priv->bcc_field, NULL, 0);
820 subject_caption = hildon_caption_new (size_group, _("mail_va_subject"), subject_box, NULL, 0);
821 priv->attachments_caption = hildon_caption_new (size_group, _("mail_va_attachment"), priv->attachments_view, NULL, 0);
822 g_object_unref (size_group);
824 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
825 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), size_group);
826 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), size_group);
827 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), size_group);
828 gtk_size_group_add_widget (size_group, priv->subject_field);
829 gtk_size_group_add_widget (size_group, priv->attachments_view);
830 g_object_unref (size_group);
832 gtk_box_pack_start (GTK_BOX (priv->header_box), from_caption, FALSE, FALSE, 0);
833 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
834 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
835 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
836 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
837 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
838 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
841 priv->msg_body = wp_text_view_new ();
842 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
843 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
844 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
845 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
846 #if (GTK_MINOR_VERSION >= 10)
847 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), "wp-text-buffer");
848 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
850 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
851 deserialize_type, TRUE);
853 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
855 priv->find_toolbar = hildon_find_toolbar_new (NULL);
856 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
858 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
860 priv->scroll = gtk_scrolled_window_new (NULL, NULL);
861 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
862 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (priv->scroll), GTK_SHADOW_NONE);
863 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->scroll), TRUE);
865 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
867 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
868 priv->frame = gtk_frame_new (NULL);
869 gtk_box_pack_start (GTK_BOX(main_vbox), priv->frame, TRUE, TRUE, 0);
871 gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (priv->scroll), main_vbox);
872 gtk_container_set_focus_vadjustment (GTK_CONTAINER (main_vbox), gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll)));
873 gtk_widget_show_all (GTK_WIDGET(priv->scroll));
875 window_box = gtk_vbox_new (FALSE, 0);
876 gtk_container_add (GTK_CONTAINER(obj), window_box);
878 gtk_box_pack_start (GTK_BOX (window_box), priv->scroll, TRUE, TRUE, 0);
880 gtk_container_add (GTK_CONTAINER (priv->frame), priv->msg_body);
882 /* Set window icon */
883 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
885 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
886 g_object_unref (window_icon);
891 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
893 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
895 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
896 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
897 priv->clipboard_change_handler_id))
898 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
899 priv->clipboard_change_handler_id);
900 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
901 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
902 priv->default_clipboard_change_handler_id))
903 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
904 priv->default_clipboard_change_handler_id);
906 if (priv->account_removed_handler_id &&
907 g_signal_handler_is_connected (modest_runtime_get_account_store (),
908 priv->account_removed_handler_id))
909 g_signal_handler_disconnect(modest_runtime_get_account_store (),
910 priv->account_removed_handler_id);
914 modest_msg_edit_window_finalize (GObject *obj)
916 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
918 /* Sanity check: shouldn't be needed, the window mgr should
919 call this function before */
920 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
922 if (priv->clipboard_text != NULL) {
923 g_free (priv->clipboard_text);
924 priv->clipboard_text = NULL;
927 if (priv->draft_msg != NULL) {
928 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
929 if (TNY_IS_HEADER (header)) {
930 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
931 modest_window_mgr_unregister_header (mgr, header);
933 g_object_unref (priv->draft_msg);
934 priv->draft_msg = NULL;
936 if (priv->outbox_msg != NULL) {
937 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
938 if (TNY_IS_HEADER (header)) {
939 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
940 modest_window_mgr_unregister_header (mgr, header);
942 g_object_unref (priv->outbox_msg);
943 priv->outbox_msg = NULL;
945 if (priv->scroll_drag_timeout_id > 0) {
946 g_source_remove (priv->scroll_drag_timeout_id);
947 priv->scroll_drag_timeout_id = 0;
949 if (priv->clipboard_owner_idle > 0) {
950 g_source_remove (priv->clipboard_owner_idle);
951 priv->clipboard_owner_idle = 0;
953 if (priv->original_account_name)
954 g_free (priv->original_account_name);
955 g_free (priv->msg_uid);
956 g_free (priv->last_search);
957 g_slist_free (priv->font_items_group);
958 g_slist_free (priv->size_items_group);
959 g_object_unref (priv->attachments);
960 g_object_unref (priv->images);
962 /* This had to stay alive for as long as the combobox that used it: */
963 modest_pair_list_free (priv->from_field_protos);
965 G_OBJECT_CLASS(parent_class)->finalize (obj);
969 pixbuf_from_stream (TnyStream *stream, const gchar *mime_type, guint64 *stream_size)
971 GdkPixbufLoader *loader;
977 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
979 if (loader == NULL) {
985 tny_stream_reset (TNY_STREAM (stream));
986 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
987 GError *error = NULL;
988 unsigned char read_buffer[128];
990 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
992 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
997 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
999 g_object_ref (pixbuf);
1000 gdk_pixbuf_loader_close (loader, NULL);
1001 g_object_unref (loader);
1006 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1007 GdkPixbuf *new_pixbuf;
1009 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1010 gdk_pixbuf_get_width (pixbuf);
1011 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1012 g_object_unref (pixbuf);
1013 pixbuf = new_pixbuf;
1017 *stream_size = size;
1023 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1025 ModestMsgEditWindowPrivate *priv;
1028 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1030 for (iter = tny_list_create_iterator (attachments);
1031 !tny_iterator_is_done (iter);
1032 tny_iterator_next (iter)) {
1033 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1034 const gchar *cid = tny_mime_part_get_content_id (part);
1035 const gchar *mime_type = tny_mime_part_get_content_type (part);
1036 if ((cid != NULL)&&(mime_type != NULL)) {
1037 guint64 stream_size;
1038 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1039 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
1042 g_object_unref (stream);
1044 if (pixbuf != NULL) {
1045 priv->images_count ++;
1046 priv->images_size += stream_size;
1047 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1048 g_object_unref (pixbuf);
1051 g_object_unref (part);
1053 g_object_unref (iter);
1057 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1059 TnyMimePart *parent = NULL;
1060 const gchar *content_type = NULL;
1061 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1063 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1065 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1066 parent = g_object_ref (msg);
1067 } else if (content_type && !g_strcasecmp (content_type, "multipart/mixed")) {
1068 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1071 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1072 iter = tny_list_create_iterator (parts);
1073 while (!tny_iterator_is_done (iter)) {
1075 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1076 content_type = tny_mime_part_get_content_type (part);
1077 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1081 g_object_unref (part);
1083 tny_iterator_next (iter);
1085 g_object_unref (iter);
1086 g_object_unref (parts);
1089 if (parent != NULL) {
1090 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1093 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1094 iter = tny_list_create_iterator (parts);
1095 while (!tny_iterator_is_done (iter)) {
1097 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1098 content_type = tny_mime_part_get_content_type (part);
1099 if (content_type && g_str_has_prefix (content_type, "image/")) {
1100 tny_list_prepend (priv->images, (GObject *) part);
1102 g_object_unref (part);
1103 tny_iterator_next (iter);
1105 g_object_unref (iter);
1106 g_object_unref (parts);
1107 g_object_unref (parent);
1112 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1115 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1117 for (iter = tny_list_create_iterator (attachments) ;
1118 !tny_iterator_is_done (iter);
1119 tny_iterator_next (iter)) {
1120 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1121 const gchar *cid = tny_mime_part_get_content_id (part);
1123 char *invalid = NULL;
1124 gint int_cid = strtol (cid, &invalid, 10);
1125 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1126 priv->next_cid = int_cid + 1;
1129 g_object_unref (part);
1131 g_object_unref (iter);
1135 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1138 gchar *to, *cc, *bcc, *subject;
1140 ModestMsgEditWindowPrivate *priv;
1142 TnyHeaderFlags priority_flags;
1143 TnyFolder *msg_folder;
1144 gboolean is_html = FALSE;
1146 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1147 g_return_if_fail (TNY_IS_MSG (msg));
1149 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1151 header = tny_msg_get_header (msg);
1152 to = tny_header_dup_to (header);
1153 cc = tny_header_dup_cc (header);
1154 bcc = tny_header_dup_bcc (header);
1155 subject = tny_header_dup_subject (header);
1156 priority_flags = tny_header_get_priority (header);
1159 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
1161 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
1162 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1163 gtk_widget_show (priv->cc_caption);
1164 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1165 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1166 gtk_widget_hide (priv->cc_caption);
1169 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
1170 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1171 gtk_widget_show (priv->bcc_caption);
1172 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1173 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1174 gtk_widget_hide (priv->bcc_caption);
1177 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1178 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1181 update_window_title (self);
1183 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1184 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1186 if ((body == NULL)||(body[0] == '\0')) {
1188 body = modest_text_utils_convert_to_html ("");
1191 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1192 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1195 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1198 /* Add attachments to the view */
1199 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1200 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1201 if (tny_list_get_length (priv->attachments) == 0) {
1202 gtk_widget_hide (priv->attachments_caption);
1204 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1205 gtk_widget_show_all (priv->attachments_caption);
1207 get_related_images (self, msg);
1208 update_next_cid (self, priv->attachments);
1209 update_next_cid (self, priv->images);
1210 replace_with_images (self, priv->images);
1212 if (preserve_is_rich && !is_html) {
1213 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1214 /* Get the default format required from configuration */
1215 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1216 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1219 /* Set the default focus depending on having already a To: field or not */
1220 if ((!to)||(*to == '\0')) {
1221 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1223 gtk_widget_grab_focus (priv->msg_body);
1226 /* TODO: lower priority, select in the From: combo to the
1227 value that comes from msg <- not sure, should it be
1230 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1232 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1233 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1235 modest_msg_edit_window_set_modified (self, FALSE);
1237 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1238 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1239 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1240 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1242 if (priv->msg_uid) {
1243 g_free (priv->msg_uid);
1244 priv->msg_uid = NULL;
1247 /* we should set a reference to the incoming message if it is a draft */
1248 msg_folder = tny_msg_get_folder (msg);
1250 if (modest_tny_folder_is_local_folder (msg_folder)) {
1251 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1252 if (type == TNY_FOLDER_TYPE_INVALID)
1253 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1255 if (type == TNY_FOLDER_TYPE_DRAFTS)
1256 priv->draft_msg = g_object_ref(msg);
1257 if (type == TNY_FOLDER_TYPE_OUTBOX)
1258 priv->outbox_msg = g_object_ref(msg);
1259 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1261 g_object_unref (msg_folder);
1271 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
1274 GList *item_children, *node;
1275 GtkWidget *bin_child;
1277 bin_child = gtk_bin_get_child (GTK_BIN(item));
1279 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
1281 for (node = item_children; node != NULL; node = g_list_next (node)) {
1282 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
1283 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
1286 g_list_free (item_children);
1290 menu_tool_button_dont_expand (GtkMenuToolButton *item)
1293 GList *item_children, *node;
1295 box = gtk_bin_get_child (GTK_BIN (item));
1296 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
1297 item_children = gtk_container_get_children (GTK_CONTAINER (box));
1299 for (node = item_children; node != NULL; node = g_list_next (node)) {
1300 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
1301 if (GTK_IS_TOGGLE_BUTTON (node->data))
1302 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
1303 else if (GTK_IS_BUTTON (node->data))
1304 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
1306 g_list_free (item_children);
1311 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1313 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1314 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1315 GtkWidget *placeholder;
1316 GtkWidget *tool_item;
1321 GtkWidget *sizes_menu;
1322 GtkWidget *fonts_menu;
1323 GSList *radio_group = NULL;
1324 GSList *node = NULL;
1328 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1329 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1331 /* Font color placeholder */
1332 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1333 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1336 tool_item = GTK_WIDGET (gtk_tool_item_new ());
1337 priv->font_color_button = hildon_color_button_new ();
1338 GTK_WIDGET_UNSET_FLAGS (tool_item, GTK_CAN_FOCUS);
1339 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1340 gtk_container_add (GTK_CONTAINER (tool_item), priv->font_color_button);
1341 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1342 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1343 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1344 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1346 G_CALLBACK (modest_msg_edit_window_color_button_change),
1349 /* Font size and face placeholder */
1350 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1351 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1353 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1354 priv->size_tool_button_label = gtk_label_new (NULL);
1355 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1356 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1357 size_text,"</span>", NULL);
1358 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1360 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
1361 sizes_menu = gtk_menu_new ();
1362 priv->size_items_group = NULL;
1364 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1365 GtkWidget *size_menu_item;
1367 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1368 size_menu_item = gtk_radio_menu_item_new_with_label (radio_group, size_text);
1369 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (size_menu_item));
1370 gtk_menu_shell_append (GTK_MENU_SHELL (sizes_menu), size_menu_item);
1371 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (size_menu_item), (wp_font_size[size_index] == 12));
1372 gtk_widget_show (size_menu_item);
1374 priv->size_items_group = g_slist_prepend (priv->size_items_group, size_menu_item);
1378 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1379 GtkWidget *item = (GtkWidget *) node->data;
1380 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_size_change),
1384 priv->size_items_group = g_slist_reverse (priv->size_items_group);
1385 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), sizes_menu);
1386 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1387 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1388 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1389 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1390 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1391 priv->font_size_toolitem = tool_item;
1394 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1395 priv->font_tool_button_label = gtk_label_new (NULL);
1396 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1397 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1399 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
1400 fonts_menu = gtk_menu_new ();
1401 priv->font_items_group = NULL;
1403 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1404 GtkWidget *font_menu_item;
1405 GtkWidget *child_label;
1407 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
1408 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
1409 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
1410 wp_get_font_name (font_index), "</span>", NULL);
1411 gtk_label_set_markup (GTK_LABEL (child_label), markup);
1414 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
1415 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
1416 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
1417 gtk_widget_show (font_menu_item);
1419 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
1422 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1423 GtkWidget *item = (GtkWidget *) node->data;
1424 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
1427 priv->font_items_group = g_slist_reverse (priv->font_items_group);
1428 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
1429 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1430 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1431 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1432 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1433 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1434 priv->font_face_toolitem = tool_item;
1436 /* Set expand and homogeneous for remaining items */
1437 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
1438 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1439 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1440 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1441 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1442 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1443 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1444 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1445 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1447 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1448 will not show the tool items added to the placeholders) */
1449 gtk_widget_show_all (parent_priv->toolbar);
1451 /* Set the no show all *after* showing all items. We do not
1452 want the toolbar to be shown with a show all because it
1453 could go agains the gconf setting regarding showing or not
1454 the toolbar of the editor window */
1455 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1461 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, gboolean preserve_is_rich)
1464 ModestWindowPrivate *parent_priv;
1465 ModestMsgEditWindowPrivate *priv;
1466 ModestDimmingRulesGroup *menu_rules_group = NULL;
1467 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1468 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1469 ModestWindowMgr *mgr = NULL;
1471 g_return_val_if_fail (msg, NULL);
1472 g_return_val_if_fail (account_name, NULL);
1474 mgr = modest_runtime_get_window_mgr ();
1476 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1478 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1479 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1481 /* Menubar. Update the state of some toggles */
1482 parent_priv->menubar = modest_maemo_utils_get_manager_menubar_as_menu (parent_priv->ui_manager, "/MenuBar");
1483 hildon_window_set_menu (HILDON_WINDOW (obj), GTK_MENU (parent_priv->menubar));
1484 priv->from_field_protos = get_transports ();
1485 modest_combo_box_set_pair_list (MODEST_COMBO_BOX (priv->from_field), priv->from_field_protos);
1486 modest_combo_box_set_active_id (MODEST_COMBO_BOX (priv->from_field), (gpointer) account_name);
1487 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1488 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1491 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1493 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1495 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1497 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1499 parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new ();
1500 menu_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_MENU, FALSE);
1501 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1502 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1503 /* Add common dimming rules */
1504 modest_dimming_rules_group_add_rules (menu_rules_group,
1505 modest_msg_edit_window_menu_dimming_entries,
1506 G_N_ELEMENTS (modest_msg_edit_window_menu_dimming_entries),
1507 MODEST_WINDOW (obj));
1508 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1509 modest_msg_edit_window_toolbar_dimming_entries,
1510 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1511 MODEST_WINDOW (obj));
1512 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_button,
1513 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1514 MODEST_WINDOW (obj));
1515 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1516 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1517 MODEST_WINDOW (obj));
1518 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1519 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1520 MODEST_WINDOW (obj));
1521 modest_dimming_rules_group_add_rules (clipboard_rules_group,
1522 modest_msg_edit_window_clipboard_dimming_entries,
1523 G_N_ELEMENTS (modest_msg_edit_window_clipboard_dimming_entries),
1524 MODEST_WINDOW (obj));
1525 /* Insert dimming rules group for this window */
1526 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
1527 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1528 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1529 /* Checks the dimming rules */
1530 g_object_unref (menu_rules_group);
1531 g_object_unref (toolbar_rules_group);
1532 g_object_unref (clipboard_rules_group);
1533 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1535 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1537 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1538 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1539 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1540 priv->update_caption_visibility = TRUE;
1542 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1544 /* Track account-removed signal, this window should be closed
1545 in the case we're creating a mail associated to the account
1547 priv->account_removed_handler_id =
1548 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1550 G_CALLBACK(on_account_removed),
1553 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1555 return (ModestWindow*) obj;
1559 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1561 GString **string_buffer = (GString **) user_data;
1563 *string_buffer = g_string_append (*string_buffer, buffer);
1569 * @result: A new string which should be freed with g_free().
1572 get_formatted_data (ModestMsgEditWindow *edit_window)
1574 ModestMsgEditWindowPrivate *priv;
1575 GString *string_buffer = g_string_new ("");
1577 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1579 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1581 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1583 return g_string_free (string_buffer, FALSE);
1588 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1591 const gchar *account_name;
1592 ModestMsgEditWindowPrivate *priv;
1593 TnyIterator *att_iter;
1595 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1597 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1599 account_name = modest_combo_box_get_active_id (MODEST_COMBO_BOX (priv->from_field));
1600 g_return_val_if_fail (account_name, NULL);
1603 /* don't free these (except from) */
1604 data = g_slice_new0 (MsgData);
1605 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1607 data->account_name = g_strdup (account_name);
1608 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1609 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1610 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1611 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1612 if (priv->draft_msg) {
1613 data->draft_msg = g_object_ref (priv->draft_msg);
1614 } else if (priv->outbox_msg) {
1615 data->draft_msg = g_object_ref (priv->outbox_msg);
1617 data->draft_msg = NULL;
1620 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1622 gtk_text_buffer_get_bounds (buf, &b, &e);
1623 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1625 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1626 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1628 data->html_body = NULL;
1630 /* deep-copy the data */
1631 att_iter = tny_list_create_iterator (priv->attachments);
1632 data->attachments = NULL;
1633 while (!tny_iterator_is_done (att_iter)) {
1634 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1635 if (!(TNY_IS_MIME_PART(part))) {
1636 g_warning ("strange data in attachment list");
1637 g_object_unref (part);
1638 tny_iterator_next (att_iter);
1641 data->attachments = g_list_append (data->attachments,
1643 tny_iterator_next (att_iter);
1645 g_object_unref (att_iter);
1647 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1648 att_iter = tny_list_create_iterator (priv->images);
1649 data->images = NULL;
1650 while (!tny_iterator_is_done (att_iter)) {
1651 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1653 if (!(TNY_IS_MIME_PART(part))) {
1654 g_warning ("strange data in attachment list");
1655 g_object_unref (part);
1656 tny_iterator_next (att_iter);
1659 cid = tny_mime_part_get_content_id (part);
1661 gchar *image_tag_id;
1662 GtkTextTag *image_tag;
1664 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1665 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1666 g_free (image_tag_id);
1668 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1670 ((gtk_text_iter_has_tag (&iter, image_tag))||
1671 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1672 data->images = g_list_append (data->images,
1673 g_object_ref (part));
1675 g_object_unref (part);
1676 tny_iterator_next (att_iter);
1678 g_object_unref (att_iter);
1680 data->priority_flags = priv->priority_flags;
1687 unref_gobject (GObject *obj, gpointer data)
1689 if (!G_IS_OBJECT(obj))
1691 g_object_unref (obj);
1695 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1698 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1706 g_free (data->from);
1707 g_free (data->subject);
1708 g_free (data->plain_body);
1709 g_free (data->html_body);
1710 g_free (data->account_name);
1712 if (data->draft_msg != NULL) {
1713 g_object_unref (data->draft_msg);
1714 data->draft_msg = NULL;
1717 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1718 g_list_free (data->attachments);
1719 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1720 g_list_free (data->images);
1722 g_slice_free (MsgData, data);
1726 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1728 guint64 *parts_size)
1730 ModestMsgEditWindowPrivate *priv;
1732 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1734 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1736 /* TODO: add images */
1737 *parts_size += priv->images_size;
1738 *parts_count += priv->images_count;
1743 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1746 ModestMsgEditWindowPrivate *priv = NULL;
1747 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1749 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1751 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1753 return MODEST_MSG_EDIT_FORMAT_HTML;
1755 return MODEST_MSG_EDIT_FORMAT_TEXT;
1759 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1760 ModestMsgEditFormat format)
1762 ModestMsgEditWindowPrivate *priv;
1764 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1765 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1768 case MODEST_MSG_EDIT_FORMAT_HTML:
1769 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1771 case MODEST_MSG_EDIT_FORMAT_TEXT:
1772 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1775 g_return_if_reached ();
1779 ModestMsgEditFormatState *
1780 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1782 ModestMsgEditFormatState *format_state = NULL;
1783 ModestMsgEditWindowPrivate *priv;
1784 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1786 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1787 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1789 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1791 format_state = g_new0 (ModestMsgEditFormatState, 1);
1792 format_state->bold = buffer_format->bold&0x1;
1793 format_state->italics = buffer_format->italic&0x1;
1794 format_state->bullet = buffer_format->bullet&0x1;
1795 format_state->color = buffer_format->color;
1796 format_state->font_size = buffer_format->font_size;
1797 format_state->font_family = wp_get_font_name (buffer_format->font);
1798 format_state->justification = buffer_format->justification;
1799 g_free (buffer_format);
1801 return format_state;
1806 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1807 const ModestMsgEditFormatState *format_state)
1809 ModestMsgEditWindowPrivate *priv;
1810 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1811 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1812 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1813 g_return_if_fail (format_state != NULL);
1815 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1816 gtk_widget_grab_focus (priv->msg_body);
1817 buffer_format->bold = (format_state->bold != FALSE);
1818 buffer_format->italic = (format_state->italics != FALSE);
1819 buffer_format->color = format_state->color;
1820 buffer_format->font_size = format_state->font_size;
1821 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1822 buffer_format->justification = format_state->justification;
1823 buffer_format->bullet = format_state->bullet;
1825 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1827 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1828 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1829 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1830 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1831 buffer_format->cs.font = (buffer_format->font != current_format->font);
1832 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1833 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1835 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1836 if (buffer_format->cs.bold) {
1837 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
1838 GINT_TO_POINTER (buffer_format->bold&0x1));
1840 if (buffer_format->cs.italic) {
1841 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
1842 GINT_TO_POINTER (buffer_format->italic&0x1));
1844 if (buffer_format->cs.color) {
1845 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1846 GINT_TO_POINTER (&(buffer_format->color)));
1848 if (buffer_format->cs.font_size) {
1849 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1850 GINT_TO_POINTER (buffer_format->font_size));
1852 if (buffer_format->cs.justification) {
1853 switch (buffer_format->justification) {
1854 case GTK_JUSTIFY_LEFT:
1855 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
1856 GINT_TO_POINTER(TRUE));
1858 case GTK_JUSTIFY_CENTER:
1859 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
1860 GINT_TO_POINTER(TRUE));
1862 case GTK_JUSTIFY_RIGHT:
1863 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
1864 GINT_TO_POINTER(TRUE));
1871 if (buffer_format->cs.font) {
1872 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1873 GINT_TO_POINTER (buffer_format->font));
1875 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1876 if (buffer_format->cs.bullet) {
1877 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
1878 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
1880 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1882 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
1884 g_free (current_format);
1889 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1891 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1893 ModestWindowPrivate *parent_priv;
1894 ModestMsgEditWindowPrivate *priv;
1895 GtkWidget *new_size_menuitem;
1896 GtkWidget *new_font_menuitem;
1898 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1899 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1901 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1902 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu");
1903 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1904 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1906 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatPlainTextMenu");
1907 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1908 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1911 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1913 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1914 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1916 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1917 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1919 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
1920 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
1923 switch (buffer_format->justification)
1925 case GTK_JUSTIFY_LEFT:
1926 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
1928 case GTK_JUSTIFY_CENTER:
1929 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
1931 case GTK_JUSTIFY_RIGHT:
1932 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
1939 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
1941 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1942 G_CALLBACK (modest_msg_edit_window_color_button_change),
1944 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1945 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1946 G_CALLBACK (modest_msg_edit_window_color_button_change),
1949 new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group,
1950 buffer_format->font_size))->data);
1951 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1955 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1956 markup = g_strconcat ("<span font_family='Sans'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1957 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1959 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1960 G_CALLBACK (modest_msg_edit_window_size_change),
1962 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
1963 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
1964 G_CALLBACK (modest_msg_edit_window_size_change),
1968 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
1969 buffer_format->font))->data);
1970 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
1974 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
1975 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1976 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1978 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
1979 G_CALLBACK (modest_msg_edit_window_font_change),
1981 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
1982 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
1983 G_CALLBACK (modest_msg_edit_window_font_change),
1987 g_free (buffer_format);
1991 #ifdef MODEST_HILDON_VERSION_0
1993 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
1996 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1997 ModestMsgEditWindowPrivate *priv;
1998 GtkWidget *dialog = NULL;
2000 GdkColor *new_color = NULL;
2002 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2003 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2005 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2006 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
2007 g_free (buffer_format);
2009 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2010 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2011 if (new_color != NULL) {
2012 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2013 (gpointer) new_color);
2016 gtk_widget_destroy (dialog);
2021 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2024 ModestMsgEditWindowPrivate *priv;
2025 GtkWidget *dialog = NULL;
2027 GdkColor *old_color = NULL;
2028 const GdkColor *new_color = NULL;
2030 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2031 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2033 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2034 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2036 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2037 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2038 if (new_color != NULL)
2039 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2041 gtk_widget_destroy (dialog);
2047 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2050 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2051 ModestMsgEditWindowPrivate *priv;
2052 GtkWidget *dialog = NULL;
2054 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2055 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2057 dialog = hildon_color_chooser_new ();
2058 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2059 g_free (buffer_format);
2061 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2063 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2064 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2067 gtk_widget_destroy (dialog);
2072 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2075 ModestMsgEditWindowPrivate *priv;
2076 GtkWidget *dialog = NULL;
2077 GdkColor *old_color = NULL;
2079 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2080 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2082 dialog = hildon_color_chooser_new ();
2083 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2085 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2087 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2088 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2090 gtk_widget_destroy (dialog);
2093 #endif /*!MODEST_HILDON_VERSION_0*/
2098 create_stream_for_uri (const gchar* uri)
2103 TnyStream *result = NULL;
2105 GnomeVFSHandle *handle = NULL;
2106 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2107 if (test == GNOME_VFS_OK) {
2108 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2109 /* Streams over OBEX (Bluetooth) are not seekable but
2110 * we expect them to be (we might need to read them
2111 * several times). So if this is a Bluetooth URI just
2112 * read the whole file into memory (this is not a fast
2113 * protocol so we can assume that these files are not
2114 * going to be very big) */
2115 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2116 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2117 TnyStream *memstream = tny_camel_mem_stream_new ();
2118 tny_stream_write_to_stream (vfssstream, memstream);
2119 g_object_unref (vfssstream);
2122 result = vfssstream;
2130 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2133 ModestMsgEditWindowPrivate *priv;
2134 GtkWidget *dialog = NULL;
2136 GSList *uris = NULL;
2137 GSList *uri_node = NULL;
2139 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2141 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2142 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2143 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2145 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2147 response = gtk_dialog_run (GTK_DIALOG (dialog));
2149 case GTK_RESPONSE_OK:
2150 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2155 gtk_widget_destroy (dialog);
2157 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2159 GnomeVFSHandle *handle = NULL;
2160 GnomeVFSResult result;
2161 GtkTextIter position;
2162 GtkTextMark *insert_mark;
2164 uri = (const gchar *) uri_node->data;
2165 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2166 if (result == GNOME_VFS_OK) {
2168 GnomeVFSFileInfo *info;
2169 gchar *filename, *basename, *escaped_filename;
2170 TnyMimePart *mime_part;
2172 const gchar *mime_type = NULL;
2173 GnomeVFSURI *vfs_uri;
2174 guint64 stream_size;
2176 gnome_vfs_close (handle);
2177 vfs_uri = gnome_vfs_uri_new (uri);
2179 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2180 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2181 g_free (escaped_filename);
2182 gnome_vfs_uri_unref (vfs_uri);
2183 info = gnome_vfs_file_info_new ();
2185 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2186 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2188 mime_type = gnome_vfs_file_info_get_mime_type (info);
2190 mime_part = tny_platform_factory_new_mime_part
2191 (modest_runtime_get_platform_factory ());
2193 TnyStream *stream = create_stream_for_uri (uri);
2195 if (stream == NULL) {
2197 modest_platform_information_banner (NULL, NULL, dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2199 g_object_unref (mime_part);
2200 gnome_vfs_file_info_unref (info);
2204 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2206 content_id = g_strdup_printf ("%d", priv->next_cid);
2207 tny_mime_part_set_content_id (mime_part, content_id);
2208 g_free (content_id);
2211 basename = g_path_get_basename (filename);
2212 tny_mime_part_set_filename (mime_part, basename);
2215 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
2217 if (pixbuf != NULL) {
2218 priv->images_size += stream_size;
2219 priv->images_count ++;
2220 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2221 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2222 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
2225 tny_list_prepend (priv->images, (GObject *) mime_part);
2226 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2228 g_object_unref (mime_part);
2229 gnome_vfs_file_info_unref (info);
2238 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2240 GtkWidget *dialog = NULL;
2242 GSList *uris = NULL;
2244 GnomeVFSFileSize total_size, allowed_size;
2245 ModestMsgEditWindowPrivate *priv;
2249 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2251 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2253 if (modest_platform_check_memory_low (MODEST_WINDOW(window)))
2256 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2257 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2258 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2259 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), GTK_WINDOW (dialog));
2261 response = gtk_dialog_run (GTK_DIALOG (dialog));
2263 case GTK_RESPONSE_OK:
2264 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2269 gtk_widget_destroy (dialog);
2271 /* allowed size is the maximum size - what's already there */
2272 modest_attachments_view_get_sizes (
2273 MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2274 &att_num, &att_size);
2275 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2278 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2280 const gchar *uri = (const gchar *) uri_node->data;
2282 total_size += modest_msg_edit_window_attach_file_one
2283 (window, uri, allowed_size);
2285 if (total_size > allowed_size) {
2286 g_warning ("%s: total size: %u",
2287 __FUNCTION__, (unsigned int)total_size);
2291 allowed_size -= total_size;
2295 g_slist_foreach (uris, (GFunc) g_free, NULL);
2296 g_slist_free (uris);
2301 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2303 GnomeVFSFileSize allowed_size)
2306 GnomeVFSHandle *handle = NULL;
2307 ModestMsgEditWindowPrivate *priv;
2308 GnomeVFSResult result;
2309 GnomeVFSFileSize size = 0;
2311 g_return_val_if_fail (window, 0);
2312 g_return_val_if_fail (uri, 0);
2314 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2316 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2317 if (result == GNOME_VFS_OK) {
2318 TnyMimePart *mime_part;
2320 const gchar *mime_type = NULL;
2322 gchar *escaped_filename;
2325 GnomeVFSFileInfo *info;
2326 GnomeVFSURI *vfs_uri;
2328 gnome_vfs_close (handle);
2329 vfs_uri = gnome_vfs_uri_new (uri);
2332 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2333 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2334 g_free (escaped_filename);
2335 gnome_vfs_uri_unref (vfs_uri);
2337 info = gnome_vfs_file_info_new ();
2339 if (gnome_vfs_get_file_info (uri,
2341 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2343 mime_type = gnome_vfs_file_info_get_mime_type (info);
2344 mime_part = tny_platform_factory_new_mime_part
2345 (modest_runtime_get_platform_factory ());
2347 /* try to get the attachment's size; this may fail for weird
2348 * file systems, like obex, upnp... */
2349 if (allowed_size != 0 &&
2350 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2352 if (size > allowed_size) {
2353 g_warning ("%s: attachment too big", __FUNCTION__);
2354 modest_platform_information_banner (NULL, NULL, dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2358 g_warning ("%s: could not get attachment size", __FUNCTION__);
2360 stream = create_stream_for_uri (uri);
2362 if (stream == NULL) {
2364 modest_platform_information_banner (NULL, NULL, dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2366 g_object_unref (mime_part);
2367 gnome_vfs_file_info_unref (info);
2371 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2372 g_object_unref (stream);
2374 content_id = g_strdup_printf ("%d", priv->next_cid);
2375 tny_mime_part_set_content_id (mime_part, content_id);
2376 g_free (content_id);
2379 basename = g_path_get_basename (filename);
2380 tny_mime_part_set_filename (mime_part, basename);
2383 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2384 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2386 info->size == 0, info->size);
2387 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2388 gtk_widget_show_all (priv->attachments_caption);
2389 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2391 g_object_unref (mime_part);
2392 gnome_vfs_file_info_unref (info);
2399 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2402 ModestMsgEditWindowPrivate *priv;
2405 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2406 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2408 if (att_list == NULL) {
2409 att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2411 g_object_ref (att_list);
2414 if (tny_list_get_length (att_list) == 0) {
2415 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2417 GtkWidget *confirmation_dialog = NULL;
2418 gboolean dialog_response;
2419 gchar *message = NULL;
2420 gchar *filename = NULL;
2422 if (tny_list_get_length (att_list) == 1) {
2424 iter = tny_list_create_iterator (att_list);
2425 part = (TnyMimePart *) tny_iterator_get_current (iter);
2426 g_object_unref (iter);
2427 if (TNY_IS_MSG (part)) {
2428 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2430 filename = tny_header_dup_subject (header);
2431 g_object_unref (header);
2433 if (filename == NULL) {
2434 filename = g_strdup (_("mail_va_no_subject"));
2437 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2439 g_object_unref (part);
2441 filename = g_strdup ("");
2443 message = g_strdup_printf (ngettext("emev_nc_delete_attachment", "emev_nc_delete_attachments",
2444 tny_list_get_length (att_list)), filename);
2446 confirmation_dialog = hildon_note_new_confirmation (GTK_WINDOW (window), message);
2448 dialog_response = (gtk_dialog_run (GTK_DIALOG (confirmation_dialog))==GTK_RESPONSE_OK);
2449 gtk_widget_destroy (confirmation_dialog);
2450 if (!dialog_response) {
2451 g_object_unref (att_list);
2454 hildon_banner_show_information (NULL, NULL, _("mcen_ib_removing_attachment"));
2456 for (iter = tny_list_create_iterator (att_list);
2457 !tny_iterator_is_done (iter);
2458 tny_iterator_next (iter)) {
2459 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2460 const gchar *att_id;
2461 tny_list_remove (priv->attachments, (GObject *) mime_part);
2463 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2465 if (tny_list_get_length (priv->attachments) == 0)
2466 gtk_widget_hide (priv->attachments_caption);
2467 att_id = tny_mime_part_get_content_id (mime_part);
2469 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2471 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2472 g_object_unref (mime_part);
2474 g_object_unref (iter);
2477 g_object_unref (att_list);
2479 /* if the last attachment has been removed, focus the Subject: field */
2480 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2481 gtk_widget_grab_focus (priv->subject_field);
2485 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2488 ModestMsgEditWindowPrivate *priv;
2489 GdkColor *new_color;
2490 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2492 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2493 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2496 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2498 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2500 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2502 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2507 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
2510 ModestMsgEditWindowPrivate *priv;
2511 gint new_size_index;
2512 ModestMsgEditWindow *window;
2515 window = MODEST_MSG_EDIT_WINDOW (userdata);
2516 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2517 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2519 if (gtk_check_menu_item_get_active (menu_item)) {
2521 WPTextBufferFormat format;
2523 memset (&format, 0, sizeof (format));
2524 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2526 label = gtk_bin_get_child (GTK_BIN (menu_item));
2528 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
2529 format.cs.font_size = TRUE;
2530 format.cs.text_position = TRUE;
2531 format.cs.font = TRUE;
2532 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
2533 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2535 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2536 GINT_TO_POINTER (wp_get_font_size_index (new_size_index, 12))))
2537 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2539 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2540 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
2541 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2547 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
2550 ModestMsgEditWindowPrivate *priv;
2551 gint new_font_index;
2552 ModestMsgEditWindow *window;
2555 window = MODEST_MSG_EDIT_WINDOW (userdata);
2556 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2557 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2559 if (gtk_check_menu_item_get_active (menu_item)) {
2562 label = gtk_bin_get_child (GTK_BIN (menu_item));
2564 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
2566 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2567 GINT_TO_POINTER(new_font_index)))
2568 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2570 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2571 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2572 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2578 modest_msg_edit_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
2580 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
2581 ModestWindowPrivate *parent_priv;
2582 ModestWindowMgr *mgr;
2583 gboolean is_fullscreen;
2584 GtkAction *fs_toggle_action;
2587 mgr = modest_runtime_get_window_mgr ();
2588 is_fullscreen = (modest_window_mgr_get_fullscreen_mode (mgr))?1:0;
2590 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
2592 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
2593 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
2594 if (is_fullscreen != active)
2595 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
2603 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2606 ModestMsgEditWindowPrivate *priv = NULL;
2607 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2609 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2610 if (!priv->update_caption_visibility)
2613 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2615 gtk_widget_show (priv->cc_caption);
2617 gtk_widget_hide (priv->cc_caption);
2619 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2623 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2626 ModestMsgEditWindowPrivate *priv = NULL;
2627 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2629 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2630 if (!priv->update_caption_visibility)
2633 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2635 gtk_widget_show (priv->bcc_caption);
2637 gtk_widget_hide (priv->bcc_caption);
2639 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2643 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2644 ModestRecptEditor *editor)
2646 ModestMsgEditWindowPrivate *priv;
2648 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2649 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2651 /* we check for low-mem; in that case, show a warning, and don't allow
2652 * for the addressbook
2654 if (modest_platform_check_memory_low (MODEST_WINDOW(window)))
2658 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2660 if (editor == NULL) {
2661 GtkWidget *view_focus;
2662 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2664 /* This code should be kept in sync with ModestRecptEditor. The
2665 textview inside the recpt editor is the one that really gets the
2666 focus. As it's inside a scrolled window, and this one inside the
2667 hbox recpt editor inherits from, we'll need to go up in the
2668 hierarchy to know if the text view is part of the recpt editor
2669 or if it's a different text entry */
2671 if (gtk_widget_get_parent (view_focus)) {
2672 GtkWidget *first_parent;
2674 first_parent = gtk_widget_get_parent (view_focus);
2675 if (gtk_widget_get_parent (first_parent) &&
2676 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2677 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2682 editor = MODEST_RECPT_EDITOR (priv->to_field);
2686 modest_address_book_select_addresses (editor);
2691 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2693 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2695 modest_msg_edit_window_open_addressbook (window, NULL);
2699 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2700 gboolean show_toolbar)
2702 ModestWindowPrivate *parent_priv;
2703 const gchar *action_name;
2706 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2707 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2709 /* We can not just use the code of
2710 modest_msg_edit_window_setup_toolbar because it has a
2711 mixture of both initialization and creation code. */
2713 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2715 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2717 /* Update also the actions (to update the toggles in the
2718 menus), we have to do it manually because some other window
2719 of the same time could have changed it (remember that the
2720 toolbar fullscreen mode is shared by all the windows of the
2722 if (modest_window_mgr_get_fullscreen_mode (modest_runtime_get_window_mgr ()))
2723 action_name = "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarFullScreenMenu";
2725 action_name = "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarNormalScreenMenu";
2727 action = gtk_ui_manager_get_action (parent_priv->ui_manager, action_name);
2728 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
2734 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2735 TnyHeaderFlags priority_flags)
2737 ModestMsgEditWindowPrivate *priv;
2738 ModestWindowPrivate *parent_priv;
2740 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2742 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2743 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2745 if (priv->priority_flags != priority_flags) {
2746 GtkAction *priority_action = NULL;
2748 priv->priority_flags = priority_flags;
2750 switch (priority_flags) {
2751 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2752 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_high", GTK_ICON_SIZE_MENU);
2753 gtk_widget_show (priv->priority_icon);
2754 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2755 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2757 case TNY_HEADER_FLAG_LOW_PRIORITY:
2758 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_low", GTK_ICON_SIZE_MENU);
2759 gtk_widget_show (priv->priority_icon);
2760 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2761 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2764 gtk_widget_hide (priv->priority_icon);
2765 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2766 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2769 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2770 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2775 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2778 ModestMsgEditWindowPrivate *priv;
2779 ModestWindowPrivate *parent_priv;
2780 gint current_format;
2782 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2784 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2785 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2787 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2788 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2790 if (current_format != file_format) {
2791 switch (file_format) {
2792 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2793 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2794 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
2796 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2800 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2801 response = gtk_dialog_run (GTK_DIALOG (dialog));
2802 gtk_widget_destroy (dialog);
2803 if (response == GTK_RESPONSE_OK) {
2804 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2806 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu"));
2807 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
2812 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2813 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2818 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2821 ModestMsgEditWindowPrivate *priv;
2822 WPTextBufferFormat oldfmt, fmt;
2823 gint old_position = 0;
2827 GdkColor *color = NULL;
2828 gboolean bold, bold_set, italic, italic_set;
2829 gboolean underline, underline_set;
2830 gboolean strikethrough, strikethrough_set;
2831 gboolean position_set;
2832 gboolean font_size_set, font_set, color_set;
2835 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2836 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2838 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2839 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
2840 GTK_WINDOW(dialog));
2842 /* First we get the currently selected font information */
2843 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2845 switch (oldfmt.text_position) {
2846 case TEXT_POSITION_NORMAL:
2849 case TEXT_POSITION_SUPERSCRIPT:
2857 g_object_set (G_OBJECT (dialog),
2858 "bold", oldfmt.bold != FALSE,
2859 "bold-set", !oldfmt.cs.bold,
2860 "underline", oldfmt.underline != FALSE,
2861 "underline-set", !oldfmt.cs.underline,
2862 "italic", oldfmt.italic != FALSE,
2863 "italic-set", !oldfmt.cs.italic,
2864 "strikethrough", oldfmt.strikethrough != FALSE,
2865 "strikethrough-set", !oldfmt.cs.strikethrough,
2866 "color", &oldfmt.color,
2867 "color-set", !oldfmt.cs.color,
2868 "size", wp_font_size[oldfmt.font_size],
2869 "size-set", !oldfmt.cs.font_size,
2870 "position", old_position,
2871 "position-set", !oldfmt.cs.text_position,
2872 "family", wp_get_font_name (oldfmt.font),
2873 "family-set", !oldfmt.cs.font,
2876 gtk_widget_show_all (dialog);
2877 response = gtk_dialog_run (GTK_DIALOG (dialog));
2878 if (response == GTK_RESPONSE_OK) {
2880 g_object_get( dialog,
2882 "bold-set", &bold_set,
2883 "underline", &underline,
2884 "underline-set", &underline_set,
2886 "italic-set", &italic_set,
2887 "strikethrough", &strikethrough,
2888 "strikethrough-set", &strikethrough_set,
2890 "color-set", &color_set,
2892 "size-set", &font_size_set,
2893 "family", &font_name,
2894 "family-set", &font_set,
2895 "position", &position,
2896 "position-set", &position_set,
2901 if (response == GTK_RESPONSE_OK) {
2902 memset(&fmt, 0, sizeof(fmt));
2908 fmt.italic = italic;
2909 fmt.cs.italic = TRUE;
2911 if (underline_set) {
2912 fmt.underline = underline;
2913 fmt.cs.underline = TRUE;
2915 if (strikethrough_set) {
2916 fmt.strikethrough = strikethrough;
2917 fmt.cs.strikethrough = TRUE;
2922 ? TEXT_POSITION_NORMAL
2923 : ( ( position == 1 )
2924 ? TEXT_POSITION_SUPERSCRIPT
2925 : TEXT_POSITION_SUBSCRIPT );
2926 fmt.cs.text_position = TRUE;
2927 fmt.font_size = oldfmt.font_size;
2931 fmt.cs.color = TRUE;
2934 fmt.font = wp_get_font_index(font_name,
2939 if (font_size_set) {
2940 fmt.cs.font_size = TRUE;
2941 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
2943 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2944 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2946 gtk_widget_destroy (dialog);
2948 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2952 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2954 ModestMsgEditWindowPrivate *priv;
2956 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2957 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2959 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2961 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2962 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2967 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
2969 ModestMsgEditWindowPrivate *priv;
2971 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2972 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2974 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
2976 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2977 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2982 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
2984 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2986 priv->can_undo = can_undo;
2990 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
2992 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2994 priv->can_redo = can_redo;
2998 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3000 ModestMsgEditWindowPrivate *priv;
3001 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3002 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3004 return priv->can_undo;
3008 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3010 ModestMsgEditWindowPrivate *priv;
3011 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3012 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3014 return priv->can_redo;
3019 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3022 GtkTextIter match_start, match_end;
3024 if (image_id == NULL)
3027 gtk_text_buffer_get_start_iter (buffer, &iter);
3029 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3030 GSList *tags = gtk_text_iter_get_tags (&match_start);
3032 for (node = tags; node != NULL; node = g_slist_next (node)) {
3033 GtkTextTag *tag = (GtkTextTag *) node->data;
3034 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3035 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3036 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3038 offset = gtk_text_iter_get_offset (&match_start);
3039 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3040 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3044 gtk_text_iter_forward_char (&iter);
3049 message_is_empty (ModestMsgEditWindow *window)
3051 ModestMsgEditWindowPrivate *priv = NULL;
3053 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3054 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3056 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3057 * so we can ignore markup.
3059 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3062 count = gtk_text_buffer_get_char_count (buf);
3068 msg_body_focus (GtkWidget *focus,
3069 GdkEventFocus *event,
3073 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3074 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3075 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3080 recpt_field_changed (GtkTextBuffer *buffer,
3081 ModestMsgEditWindow *editor)
3083 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3084 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3088 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3090 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3091 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3095 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3098 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3099 GtkTextBuffer *buffer;
3101 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3102 gtk_text_buffer_set_modified (buffer, modified);
3103 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3104 gtk_text_buffer_set_modified (buffer, modified);
3105 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3106 gtk_text_buffer_set_modified (buffer, modified);
3107 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3111 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3113 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3114 const char *account_name;
3115 GtkTextBuffer *buffer;
3117 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3118 if (gtk_text_buffer_get_modified (buffer))
3120 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3121 if (gtk_text_buffer_get_modified (buffer))
3123 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3124 if (gtk_text_buffer_get_modified (buffer))
3126 if (gtk_text_buffer_get_modified (priv->text_buffer))
3128 account_name = modest_combo_box_get_active_id (MODEST_COMBO_BOX (priv->from_field));
3129 if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3140 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3142 ModestMsgEditWindowPrivate *priv = NULL;
3144 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3145 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3147 /* check if there's no recipient added */
3148 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3149 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3150 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3151 /* no recipient contents, then select contacts */
3152 modest_msg_edit_window_open_addressbook (window, NULL);
3156 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3157 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3160 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3161 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3164 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3165 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3169 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3170 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3171 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3178 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3179 ModestMsgEditWindow *window)
3181 modest_msg_edit_window_offer_attach_file (window);
3185 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3187 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3189 return priv->clipboard_text;
3193 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3195 ModestMsgEditWindow *window)
3197 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3198 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3200 if (!GTK_WIDGET_VISIBLE (window))
3203 g_object_ref (window);
3204 text = gtk_clipboard_wait_for_text (selection_clipboard);
3206 if (priv->clipboard_text != NULL) {
3207 g_free (priv->clipboard_text);
3209 priv->clipboard_text = text;
3211 if (GTK_WIDGET_VISIBLE (window)) {
3212 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3214 g_object_unref (window);
3217 static gboolean clipboard_owner_change_idle (gpointer userdata)
3219 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3220 ModestMsgEditWindowPrivate *priv;
3222 gdk_threads_enter ();
3223 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3224 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3226 priv->clipboard_owner_idle = 0;
3227 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3228 gdk_threads_leave ();
3234 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3236 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3237 if (priv->clipboard_owner_idle == 0) {
3238 priv->clipboard_owner_idle = g_idle_add (clipboard_owner_change_idle, window);
3243 subject_field_move_cursor (GtkEntry *entry,
3244 GtkMovementStep step,
3249 if (!GTK_WIDGET_VISIBLE (window))
3252 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3256 update_window_title (ModestMsgEditWindow *window)
3258 ModestMsgEditWindowPrivate *priv = NULL;
3259 const gchar *subject;
3261 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3262 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3263 if (subject == NULL || subject[0] == '\0')
3264 subject = _("mail_va_new_email");
3266 gtk_window_set_title (GTK_WINDOW (window), subject);
3271 subject_field_changed (GtkEditable *editable,
3272 ModestMsgEditWindow *window)
3274 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3275 update_window_title (window);
3276 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3277 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3278 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3282 subject_field_insert_text (GtkEditable *editable,
3284 gint new_text_length,
3286 ModestMsgEditWindow *window)
3288 GString *result = g_string_new ("");
3290 gint result_len = 0;
3291 const gchar *entry_text = NULL;
3294 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3295 old_length = g_utf8_strlen (entry_text, -1);
3297 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3298 gunichar c = g_utf8_get_char_validated (current, 8);
3299 /* Invalid unichar, stop */
3305 result = g_string_append_unichar (result, c);
3309 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3310 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3313 /* Prevent endless recursion */
3314 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3315 g_signal_emit_by_name (editable, "insert-text",
3316 (gpointer) result->str, (gpointer) result->len,
3317 (gpointer) position, (gpointer) window);
3318 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3322 if (result_len + old_length > 1000) {
3323 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3324 dgettext("hildon-common-strings",
3325 "ckdg_ib_maximum_characters_reached"));
3328 g_string_free (result, TRUE);
3332 text_buffer_insert_text (GtkTextBuffer *buffer,
3335 gint new_text_length,
3336 ModestMsgEditWindow *window)
3338 GString *result = g_string_new ("");
3340 gint result_len = 0;
3341 gboolean changed = FALSE;
3343 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3344 gunichar c = g_utf8_get_char_validated (current, 8);
3345 /* Invalid unichar, stop */
3351 result = g_string_append_c (result, ' ');
3355 result = g_string_append_unichar (result, c);
3361 g_signal_stop_emission_by_name (G_OBJECT (buffer), "insert-text");
3362 g_signal_handlers_block_by_func(G_OBJECT(buffer), G_CALLBACK(text_buffer_insert_text), window);
3363 g_signal_emit_by_name (buffer, "insert-text",
3365 (gpointer) result->str, (gpointer) result->len,
3367 g_signal_handlers_unblock_by_func(G_OBJECT(buffer), G_CALLBACK(text_buffer_insert_text), window);
3370 g_string_free (result, TRUE);
3374 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3377 ModestMsgEditWindowPrivate *priv = NULL;
3379 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3380 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3382 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3385 gtk_widget_show_all (priv->find_toolbar);
3386 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3388 gtk_widget_hide_all (priv->find_toolbar);
3389 gtk_widget_grab_focus (priv->msg_body);
3395 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3397 GtkTextIter *match_start,
3398 GtkTextIter *match_end)
3400 GtkTextIter end_iter;
3401 gchar *str_casefold;
3404 gchar *range_casefold;
3407 gboolean result = FALSE;
3414 gtk_text_iter_forward_to_end (&end_iter);
3416 str_casefold = g_utf8_casefold (str, -1);
3417 str_chars_n = strlen (str);
3419 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3420 range_casefold = g_utf8_casefold (range_text, -1);
3421 range_chars_n = strlen (range_casefold);
3423 if (range_chars_n < str_chars_n) {
3424 g_free (str_casefold);
3425 g_free (range_text);
3426 g_free (range_casefold);
3430 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3431 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3432 if (!g_utf8_collate (range_subtext, str_casefold)) {
3433 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3435 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3436 match_start, match_end, NULL);
3437 g_free (found_text);
3439 g_free (range_subtext);
3443 g_free (str_casefold);
3444 g_free (range_text);
3445 g_free (range_casefold);
3452 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3453 ModestMsgEditWindow *window)
3455 gchar *current_search = NULL;
3456 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3458 GtkTextIter selection_start, selection_end;
3459 GtkTextIter match_start, match_end;
3460 gboolean continue_search = FALSE;
3462 if (message_is_empty (window)) {
3463 g_free (priv->last_search);
3464 priv->last_search = NULL;
3465 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3469 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3470 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3471 g_free (current_search);
3472 g_free (priv->last_search);
3473 priv->last_search = NULL;
3474 /* Information banner about empty search */
3475 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-common-strings", "ecdg_ib_find_rep_enter_text"));
3479 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3480 continue_search = TRUE;
3482 g_free (priv->last_search);
3483 priv->last_search = g_strdup (current_search);
3486 if (continue_search) {
3487 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3488 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3489 &match_start, &match_end);
3491 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_search_complete"));
3493 GtkTextIter buffer_start;
3494 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3495 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3496 &match_start, &match_end);
3498 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_no_matches"));
3501 /* Mark as selected the string found in search */
3503 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3504 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3505 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3507 g_free (priv->last_search);
3508 priv->last_search = NULL;
3510 g_free (current_search);
3514 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3515 ModestMsgEditWindow *window)
3517 GtkToggleAction *toggle;
3518 ModestWindowPrivate *parent_priv;
3519 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3521 toggle = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ToolsMenu/FindInMessageMenu"));
3522 gtk_toggle_action_set_active (toggle, FALSE);
3526 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3528 ModestMsgEditWindowPrivate *priv;
3530 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3535 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3538 ModestMsgEditWindowPrivate *priv;
3540 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3546 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3549 ModestMsgEditWindowPrivate *priv;
3550 TnyHeader *header = NULL;
3552 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3553 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3555 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3556 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3558 if (priv->draft_msg != NULL) {
3559 g_object_unref (priv->draft_msg);
3562 if (draft != NULL) {
3563 g_object_ref (draft);
3564 header = tny_msg_get_header (draft);
3565 if (priv->msg_uid) {
3566 g_free (priv->msg_uid);
3567 priv->msg_uid = NULL;
3569 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3570 if (GTK_WIDGET_REALIZED (window))
3571 modest_window_mgr_register_window (mgr, MODEST_WINDOW (window));
3574 priv->draft_msg = draft;
3578 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3579 GtkTextIter *start, GtkTextIter *end,
3582 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3583 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3586 if (tag == NULL+13) return;
3587 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3588 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3589 replace_with_images (window, priv->images);
3594 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3597 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3599 g_return_if_fail (TNY_IS_MIME_PART (part));
3600 tny_list_prepend (priv->attachments, (GObject *) part);
3601 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3602 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3603 gtk_widget_show_all (priv->attachments_caption);
3604 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3608 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3610 ModestMsgEditWindowPrivate *priv;
3612 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3613 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3615 return priv->msg_uid;
3619 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3620 ModestMsgEditWindowWidgetType widget_type)
3622 ModestMsgEditWindowPrivate *priv;
3624 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3625 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3627 switch (widget_type) {
3628 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3629 return priv->msg_body;
3631 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3632 return priv->to_field;
3634 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3635 return priv->cc_field;
3637 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3638 return priv->bcc_field;
3640 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3641 return priv->subject_field;
3643 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3644 return priv->attachments_view;
3652 remove_tags (WPTextBuffer *buffer)
3654 GtkTextIter start, end;
3656 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3657 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3659 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3663 on_account_removed (TnyAccountStore *account_store,
3664 TnyAccount *account,
3667 /* Do nothing if it's a store account, because we use the
3668 transport to send the messages */
3669 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3670 const gchar *parent_acc = NULL;
3671 const gchar *our_acc = NULL;
3673 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3674 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3675 /* Close this window if I'm showing a message of the removed account */
3676 if (strcmp (parent_acc, our_acc) == 0)
3677 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3682 on_zoom_minus_plus_not_implemented (ModestWindow *window)
3684 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3686 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
3692 set_zoom_do_nothing (ModestWindow *window,
3698 get_zoom_do_nothing (ModestWindow *window)