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_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id);
109 static void subject_field_changed (GtkEditable *editable, ModestMsgEditWindow *window);
110 static void subject_field_insert_text (GtkEditable *editable,
112 gint new_text_length,
114 ModestMsgEditWindow *window);
115 static void modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
117 static void modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
119 static void modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
121 static void modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
122 static gboolean modest_msg_edit_window_window_state_event (GtkWidget *widget,
123 GdkEventWindowState *event,
125 static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
126 ModestRecptEditor *editor);
127 static void modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
128 ModestMsgEditWindow *window);
130 /* ModestWindow methods implementation */
131 static void modest_msg_edit_window_disconnect_signals (ModestWindow *window);
132 static void modest_msg_edit_window_show_toolbar (ModestWindow *window,
133 gboolean show_toolbar);
134 static void modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
136 ModestMsgEditWindow *window);
137 static void modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window);
138 static void subject_field_move_cursor (GtkEntry *entry,
139 GtkMovementStep step,
143 static void update_window_title (ModestMsgEditWindow *window);
146 static void modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
147 ModestMsgEditWindow *window);
148 static void modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
149 ModestMsgEditWindow *window);
150 static gboolean gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
152 GtkTextIter *match_start,
153 GtkTextIter *match_end);
155 static void remove_tags (WPTextBuffer *buffer);
157 static void on_account_removed (TnyAccountStore *account_store,
161 static gboolean on_zoom_minus_plus_not_implemented (ModestWindow *window);
162 static void set_zoom_do_nothing (ModestWindow *window, gdouble zoom);
163 static gdouble get_zoom_do_nothing (ModestWindow *window);
165 static void init_window (ModestMsgEditWindow *obj);
167 gboolean scroll_drag_timeout (gpointer userdata);
168 static void correct_scroll (ModestMsgEditWindow *w);
169 static void correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused);
170 static void text_buffer_end_user_action (GtkTextBuffer *buffer,
171 ModestMsgEditWindow *userdata);
172 static void text_buffer_mark_set (GtkTextBuffer *buffer,
175 ModestMsgEditWindow *userdata);
176 static void vadj_changed (GtkAdjustment *adj,
177 ModestMsgEditWindow *window);
179 static void DEBUG_BUFFER (WPTextBuffer *buffer)
183 g_message ("BEGIN BUFFER OF SIZE %d", gtk_text_buffer_get_char_count (GTK_TEXT_BUFFER (buffer)));
185 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &iter);
186 while (!gtk_text_iter_is_end (&iter)) {
187 GString *output = g_string_new ("");
188 GSList *toggled_tags;
191 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
192 g_string_append_printf (output, "%d: CLOSED [ ", gtk_text_iter_get_offset (&iter));
193 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
194 GtkTextTag *tag = (GtkTextTag *) node->data;
196 g_object_get (G_OBJECT (tag), "name", &name, NULL);
197 output = g_string_append (output, name);
198 g_string_append (output, " ");
200 output = g_string_append (output, "] OPENED [ ");
201 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
202 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
203 GtkTextTag *tag = (GtkTextTag *) node->data;
205 g_object_get (G_OBJECT (tag), "name", &name, NULL);
206 output = g_string_append (output, name);
207 g_string_append (output, " ");
209 output = g_string_append (output, "]\n");
210 g_message ("%s", output->str);
211 g_string_free (output, TRUE);
212 gtk_text_iter_forward_to_tag_toggle (&iter, NULL);
214 g_message ("END BUFFER");
219 /* static gboolean */
220 /* on_key_pressed (GtkWidget *self, */
221 /* GdkEventKey *event, */
222 /* gpointer user_data); */
224 /* list my signals */
231 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
232 struct _ModestMsgEditWindowPrivate {
235 GtkWidget *header_box;
237 ModestPairList *from_field_protos;
238 GtkWidget *from_field;
239 gchar *original_account_name;
243 GtkWidget *bcc_field;
244 GtkWidget *subject_field;
245 GtkWidget *attachments_view;
246 GtkWidget *priority_icon;
247 GtkWidget *add_attachment_button;
249 GtkWidget *cc_caption;
250 GtkWidget *bcc_caption;
251 gboolean update_caption_visibility;
252 GtkWidget *attachments_caption;
254 GtkTextBuffer *text_buffer;
256 GtkWidget *font_size_toolitem;
257 GtkWidget *font_face_toolitem;
258 GtkWidget *font_color_button;
259 GSList *font_items_group;
260 GtkWidget *font_tool_button_label;
261 GSList *size_items_group;
262 GtkWidget *size_tool_button_label;
264 GtkWidget *find_toolbar;
267 GtkWidget *font_dialog;
270 guint scroll_drag_timeout_id;
274 TnyList *attachments;
279 TnyHeaderFlags priority_flags;
281 gboolean can_undo, can_redo;
282 gulong clipboard_change_handler_id;
283 gulong default_clipboard_change_handler_id;
284 gulong account_removed_handler_id;
285 guint clipboard_owner_idle;
286 gchar *clipboard_text;
297 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
298 MODEST_TYPE_MSG_EDIT_WINDOW, \
299 ModestMsgEditWindowPrivate))
301 static GtkWindowClass *parent_class = NULL;
303 /* uncomment the following if you have defined any signals */
304 /* static guint signals[LAST_SIGNAL] = {0}; */
307 modest_msg_edit_window_get_type (void)
309 static GType my_type = 0;
311 static const GTypeInfo my_info = {
312 sizeof(ModestMsgEditWindowClass),
313 NULL, /* base init */
314 NULL, /* base finalize */
315 (GClassInitFunc) modest_msg_edit_window_class_init,
316 NULL, /* class finalize */
317 NULL, /* class data */
318 sizeof(ModestMsgEditWindow),
320 (GInstanceInitFunc) modest_msg_edit_window_init,
323 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
324 "ModestMsgEditWindow",
332 save_state (ModestWindow *self)
334 modest_widget_memory_save (modest_runtime_get_conf(),
335 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
340 restore_settings (ModestMsgEditWindow *self)
342 ModestConf *conf = NULL;
344 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
346 conf = modest_runtime_get_conf ();
347 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
348 "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarNormalScreenMenu");
349 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
350 modest_conf_get_bool (conf, MODEST_CONF_EDIT_WINDOW_SHOW_TOOLBAR, NULL));
351 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
352 "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarFullScreenMenu");
353 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
354 modest_conf_get_bool (conf, MODEST_CONF_EDIT_WINDOW_SHOW_TOOLBAR_FULLSCREEN, NULL));
356 /* set initial state of cc and bcc */
357 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewCcFieldMenu");
358 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
359 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, NULL));
360 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewBccFieldMenu");
361 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
362 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, NULL));
364 /* Dim at start clipboard actions */
365 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
366 gtk_action_set_sensitive (action, FALSE);
367 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
368 gtk_action_set_sensitive (action, FALSE);
369 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
370 gtk_action_set_sensitive (action, FALSE);
372 modest_widget_memory_restore (conf,
373 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
378 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
380 GObjectClass *gobject_class;
381 ModestWindowClass *modest_window_class;
382 gobject_class = (GObjectClass*) klass;
383 modest_window_class = (ModestWindowClass*) klass;
385 parent_class = g_type_class_peek_parent (klass);
386 gobject_class->finalize = modest_msg_edit_window_finalize;
388 modest_window_class->set_zoom_func = set_zoom_do_nothing;
389 modest_window_class->get_zoom_func = get_zoom_do_nothing;
390 modest_window_class->zoom_plus_func = on_zoom_minus_plus_not_implemented;
391 modest_window_class->zoom_minus_func = on_zoom_minus_plus_not_implemented;
392 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
393 modest_window_class->save_state_func = save_state;
394 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
396 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
400 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
402 ModestMsgEditWindowPrivate *priv;
403 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
405 priv->msg_body = NULL;
407 priv->from_field = NULL;
408 priv->to_field = NULL;
409 priv->cc_field = NULL;
410 priv->bcc_field = NULL;
411 priv->subject_field = NULL;
412 priv->attachments = TNY_LIST (tny_simple_list_new ());
413 priv->images = TNY_LIST (tny_simple_list_new ());
414 priv->images_size = 0;
415 priv->images_count = 0;
418 priv->cc_caption = NULL;
419 priv->bcc_caption = NULL;
420 priv->update_caption_visibility = FALSE;
422 priv->priority_flags = 0;
424 priv->find_toolbar = NULL;
425 priv->last_search = NULL;
427 priv->draft_msg = NULL;
428 priv->outbox_msg = NULL;
429 priv->msg_uid = NULL;
430 priv->references = NULL;
431 priv->in_reply_to = NULL;
433 priv->can_undo = FALSE;
434 priv->can_redo = FALSE;
435 priv->clipboard_change_handler_id = 0;
436 priv->default_clipboard_change_handler_id = 0;
437 priv->account_removed_handler_id = 0;
438 priv->clipboard_owner_idle = 0;
439 priv->clipboard_text = NULL;
442 priv->scroll_drag_timeout_id = 0;
443 priv->last_upper = 0.0;
445 priv->font_dialog = NULL;
447 modest_window_mgr_register_help_id (modest_runtime_get_window_mgr(),
448 GTK_WINDOW(obj),"applications_email_editor");
450 if (!is_wp_text_buffer_started) {
451 is_wp_text_buffer_started = TRUE;
452 wp_text_buffer_library_init ();
457 hildon_program_add_window (hildon_program_get_instance(),
462 /* FIXME: this is a dup from the one in gtk/ */
465 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
467 static ModestPairList*
468 get_transports (void)
470 GSList *transports = NULL;
472 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
473 GSList *accounts = modest_account_mgr_account_names (account_mgr,
474 TRUE /* only enabled accounts. */);
476 GSList *cursor = accounts;
478 gchar *account_name = cursor->data;
479 gchar *from_string = NULL;
481 from_string = modest_account_mgr_get_from_string (account_mgr,
485 if (from_string && account_name) {
486 gchar *name = account_name;
487 ModestPair *pair = modest_pair_new ((gpointer) name,
488 (gpointer) from_string , TRUE);
489 transports = g_slist_prepend (transports, pair);
492 cursor = cursor->next;
494 g_slist_free (accounts); /* only free the accounts, not the elements,
495 * because they are used in the pairlist */
499 static void window_focus (GtkWindow *window,
503 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
507 scroll_drag_timeout (gpointer userdata)
509 ModestMsgEditWindow *win = (ModestMsgEditWindow *) userdata;
510 ModestMsgEditWindowPrivate *priv;
512 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(win);
514 correct_scroll_without_drag_check (win, TRUE);
516 priv->scroll_drag_timeout_id = 0;
522 correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused)
524 ModestMsgEditWindowPrivate *priv;
527 GdkRectangle rectangle;
533 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
535 if (only_if_focused && !gtk_widget_is_focus (priv->msg_body))
538 insert = gtk_text_buffer_get_insert (priv->text_buffer);
539 gtk_text_buffer_get_iter_at_mark (priv->text_buffer, &iter, insert);
541 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &iter, &rectangle);
542 vadj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll));
543 offset = priv->msg_body->allocation.y;
545 new_value = vadj->value;
547 if ((offset + rectangle.y + rectangle.height) >
548 ((gint) (vadj->value +vadj->page_size))) {
549 new_value = (offset + rectangle.y) - vadj->page_size * 0.25;
550 if (new_value > vadj->upper - vadj->page_size)
551 new_value = vadj->upper - vadj->page_size;
552 } else if ((offset + rectangle.y) < ((gint) vadj->value)) {
553 new_value = (offset + rectangle.y - vadj->page_size * 0.75);
554 if (((gint) (new_value + vadj->page_size)) < (offset + rectangle.y + rectangle.height))
555 new_value = offset + rectangle.y + rectangle.height - (gint) vadj->page_size;
558 if (new_value > vadj->value)
559 new_value = vadj->value;
562 if (vadj->value != new_value) {
563 g_signal_emit_by_name (GTK_TEXT_VIEW(priv->msg_body)->layout,
565 vadj->value = new_value;
566 gtk_adjustment_value_changed (vadj);
567 /* invalidate body */
568 window = gtk_widget_get_parent_window (priv->msg_body);
570 gdk_window_invalidate_rect (window, NULL, TRUE);
576 correct_scroll (ModestMsgEditWindow *w)
578 ModestMsgEditWindowPrivate *priv;
580 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
581 if (gtk_grab_get_current () == priv->msg_body) {
582 if (priv->scroll_drag_timeout_id == 0) {
583 priv->scroll_drag_timeout_id = g_timeout_add (500, (GSourceFunc) scroll_drag_timeout,
589 correct_scroll_without_drag_check (w, TRUE);
593 text_buffer_end_user_action (GtkTextBuffer *buffer,
594 ModestMsgEditWindow *userdata)
597 correct_scroll (userdata);
601 text_buffer_mark_set (GtkTextBuffer *buffer,
604 ModestMsgEditWindow *userdata)
606 gtk_text_buffer_begin_user_action (buffer);
607 gtk_text_buffer_end_user_action (buffer);
611 cut_clipboard_check (GtkTextView *text_view,
614 GtkTextBuffer *buffer;
616 buffer = gtk_text_view_get_buffer (text_view);
617 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
618 g_signal_stop_emission_by_name ((gpointer )text_view, "cut-clipboard");
623 copy_clipboard_check (GtkTextView *text_view,
626 GtkTextBuffer *buffer;
628 buffer = gtk_text_view_get_buffer (text_view);
629 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
630 g_signal_stop_emission_by_name ((gpointer )text_view, "copy-clipboard");
635 vadj_changed (GtkAdjustment *adj,
636 ModestMsgEditWindow *window)
638 ModestMsgEditWindowPrivate *priv;
640 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
642 if (priv->last_upper != adj->upper) {
643 priv->last_upper = adj->upper;
644 correct_scroll (window);
649 attachment_deleted (ModestAttachmentsView *attachments_view,
652 modest_msg_edit_window_remove_attachments (MODEST_MSG_EDIT_WINDOW (user_data),
657 connect_signals (ModestMsgEditWindow *obj)
659 ModestMsgEditWindowPrivate *priv;
661 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
663 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
664 G_CALLBACK (text_buffer_refresh_attributes), obj);
665 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
666 G_CALLBACK (text_buffer_can_undo), obj);
667 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
668 G_CALLBACK (text_buffer_can_redo), obj);
669 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
670 G_CALLBACK (body_changed), obj);
671 g_signal_connect (G_OBJECT (priv->text_buffer), "modified-changed",
672 G_CALLBACK (body_changed), obj);
673 g_signal_connect (G_OBJECT (obj), "window-state-event",
674 G_CALLBACK (modest_msg_edit_window_window_state_event),
676 g_signal_connect (G_OBJECT (priv->text_buffer), "end-user-action",
677 G_CALLBACK (text_buffer_end_user_action), obj);
678 g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
679 G_CALLBACK (text_buffer_mark_set), obj);
680 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
681 G_CALLBACK (text_buffer_apply_tag), obj);
682 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
683 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
684 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
685 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
686 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
687 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
689 g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
690 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
692 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
693 G_CALLBACK (msg_body_focus), obj);
694 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
695 G_CALLBACK (msg_body_focus), obj);
696 g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
697 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
698 "changed", G_CALLBACK (recpt_field_changed), obj);
699 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
700 "changed", G_CALLBACK (recpt_field_changed), obj);
701 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
702 "changed", G_CALLBACK (recpt_field_changed), obj);
703 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
704 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
705 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
707 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
708 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
710 g_signal_connect (G_OBJECT (gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll))),
712 G_CALLBACK (vadj_changed),
715 priv->clipboard_change_handler_id =
716 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
717 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
718 priv->default_clipboard_change_handler_id =
719 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
720 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
722 g_signal_connect (G_OBJECT (priv->msg_body), "cut-clipboard", G_CALLBACK (cut_clipboard_check), NULL);
723 g_signal_connect (G_OBJECT (priv->msg_body), "copy-clipboard", G_CALLBACK (copy_clipboard_check), NULL);
724 g_signal_connect (G_OBJECT (priv->attachments_view), "delete", G_CALLBACK (attachment_deleted), obj);
728 init_window (ModestMsgEditWindow *obj)
730 GtkWidget *from_caption, *to_caption, *subject_caption;
731 GtkWidget *main_vbox;
732 ModestMsgEditWindowPrivate *priv;
733 GtkActionGroup *action_group;
734 ModestWindowPrivate *parent_priv;
735 GdkPixbuf *window_icon = NULL;
736 GError *error = NULL;
738 GtkSizeGroup *size_group;
739 GtkWidget *subject_box;
740 GtkWidget *attachment_icon;
741 GtkWidget *window_box;
742 #if (GTK_MINOR_VERSION >= 10)
743 GdkAtom deserialize_type;
745 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
746 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
748 parent_priv->ui_manager = gtk_ui_manager_new();
749 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
750 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
752 /* Add common actions */
753 gtk_action_group_add_actions (action_group,
754 modest_msg_edit_action_entries,
755 G_N_ELEMENTS (modest_msg_edit_action_entries),
757 gtk_action_group_add_toggle_actions (action_group,
758 modest_msg_edit_toggle_action_entries,
759 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
761 gtk_action_group_add_radio_actions (action_group,
762 modest_msg_edit_alignment_radio_action_entries,
763 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
765 G_CALLBACK (modest_ui_actions_on_change_justify),
767 gtk_action_group_add_radio_actions (action_group,
768 modest_msg_edit_priority_action_entries,
769 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
771 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
773 gtk_action_group_add_radio_actions (action_group,
774 modest_msg_edit_file_format_action_entries,
775 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
776 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
777 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
779 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
780 g_object_unref (action_group);
782 /* Load the UI definition */
783 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
786 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
787 g_clear_error (&error);
790 /* Add accelerators */
791 gtk_window_add_accel_group (GTK_WINDOW (obj),
792 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
794 parent_priv->menubar = NULL;
796 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
798 /* Note: This ModestPairList* must exist for as long as the combo
799 * that uses it, because the ModestComboBox uses the ID opaquely,
800 * so it can't know how to manage its memory. */
801 priv->from_field = modest_combo_box_new (NULL, g_str_equal);
803 priv->to_field = modest_recpt_editor_new ();
804 priv->cc_field = modest_recpt_editor_new ();
805 priv->bcc_field = modest_recpt_editor_new ();
806 subject_box = gtk_hbox_new (FALSE, 0);
807 priv->priority_icon = gtk_image_new ();
808 gtk_box_pack_start (GTK_BOX (subject_box), priv->priority_icon, FALSE, FALSE, 0);
809 priv->subject_field = gtk_entry_new_with_max_length (SUBJECT_MAX_LENGTH);
810 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
811 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
812 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
813 gtk_box_pack_start (GTK_BOX (subject_box), priv->subject_field, TRUE, TRUE, 0);
814 priv->add_attachment_button = gtk_button_new ();
815 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
816 gtk_button_set_relief (GTK_BUTTON (priv->add_attachment_button), GTK_RELIEF_NONE);
817 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
818 gtk_button_set_alignment (GTK_BUTTON (priv->add_attachment_button), 1.0, 1.0);
819 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, GTK_ICON_SIZE_BUTTON);
820 gtk_container_add (GTK_CONTAINER (priv->add_attachment_button), attachment_icon);
821 gtk_box_pack_start (GTK_BOX (subject_box), priv->add_attachment_button, FALSE, FALSE, 0);
822 priv->attachments_view = modest_attachments_view_new (NULL);
824 priv->header_box = gtk_vbox_new (FALSE, 0);
826 from_caption = hildon_caption_new (size_group, _("mail_va_from"), priv->from_field, NULL, 0);
827 to_caption = hildon_caption_new (size_group, _("mail_va_to"), priv->to_field, NULL, 0);
828 priv->cc_caption = hildon_caption_new (size_group, _("mail_va_cc"), priv->cc_field, NULL, 0);
829 priv->bcc_caption = hildon_caption_new (size_group, _("mail_va_hotfix1"), priv->bcc_field, NULL, 0);
830 subject_caption = hildon_caption_new (size_group, _("mail_va_subject"), subject_box, NULL, 0);
831 priv->attachments_caption = hildon_caption_new (size_group, _("mail_va_attachment"), priv->attachments_view, NULL, 0);
832 g_object_unref (size_group);
834 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
835 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), size_group);
836 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), size_group);
837 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), size_group);
838 gtk_size_group_add_widget (size_group, priv->subject_field);
839 gtk_size_group_add_widget (size_group, priv->attachments_view);
840 g_object_unref (size_group);
842 gtk_box_pack_start (GTK_BOX (priv->header_box), from_caption, FALSE, FALSE, 0);
843 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
844 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
845 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
846 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
847 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
848 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
851 priv->msg_body = wp_text_view_new ();
852 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
853 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
854 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
855 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
856 #if (GTK_MINOR_VERSION >= 10)
857 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
858 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
860 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
861 deserialize_type, TRUE);
863 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
865 priv->find_toolbar = hildon_find_toolbar_new (NULL);
866 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
868 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
870 priv->scroll = gtk_scrolled_window_new (NULL, NULL);
871 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
872 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (priv->scroll), GTK_SHADOW_NONE);
873 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->scroll), TRUE);
875 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
877 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
878 priv->frame = gtk_frame_new (NULL);
879 gtk_box_pack_start (GTK_BOX(main_vbox), priv->frame, TRUE, TRUE, 0);
881 gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (priv->scroll), main_vbox);
882 gtk_container_set_focus_vadjustment (GTK_CONTAINER (main_vbox), gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll)));
883 gtk_widget_show_all (GTK_WIDGET(priv->scroll));
885 window_box = gtk_vbox_new (FALSE, 0);
886 gtk_container_add (GTK_CONTAINER(obj), window_box);
888 gtk_box_pack_start (GTK_BOX (window_box), priv->scroll, TRUE, TRUE, 0);
890 gtk_container_add (GTK_CONTAINER (priv->frame), priv->msg_body);
892 /* Set window icon */
893 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
895 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
896 g_object_unref (window_icon);
901 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
903 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
905 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
906 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
907 priv->clipboard_change_handler_id))
908 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
909 priv->clipboard_change_handler_id);
910 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
911 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
912 priv->default_clipboard_change_handler_id))
913 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
914 priv->default_clipboard_change_handler_id);
916 if (priv->account_removed_handler_id &&
917 g_signal_handler_is_connected (modest_runtime_get_account_store (),
918 priv->account_removed_handler_id))
919 g_signal_handler_disconnect(modest_runtime_get_account_store (),
920 priv->account_removed_handler_id);
924 modest_msg_edit_window_finalize (GObject *obj)
926 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
928 /* Sanity check: shouldn't be needed, the window mgr should
929 call this function before */
930 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
932 if (priv->font_dialog != NULL) {
933 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
936 if (priv->clipboard_text != NULL) {
937 g_free (priv->clipboard_text);
938 priv->clipboard_text = NULL;
941 if (priv->draft_msg != NULL) {
942 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
943 if (TNY_IS_HEADER (header)) {
944 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
945 modest_window_mgr_unregister_header (mgr, header);
947 g_object_unref (priv->draft_msg);
948 priv->draft_msg = NULL;
950 if (priv->outbox_msg != NULL) {
951 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
952 if (TNY_IS_HEADER (header)) {
953 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
954 modest_window_mgr_unregister_header (mgr, header);
956 g_object_unref (priv->outbox_msg);
957 priv->outbox_msg = NULL;
959 if (priv->scroll_drag_timeout_id > 0) {
960 g_source_remove (priv->scroll_drag_timeout_id);
961 priv->scroll_drag_timeout_id = 0;
963 if (priv->clipboard_owner_idle > 0) {
964 g_source_remove (priv->clipboard_owner_idle);
965 priv->clipboard_owner_idle = 0;
967 if (priv->original_account_name)
968 g_free (priv->original_account_name);
969 g_free (priv->msg_uid);
970 g_free (priv->references);
971 g_free (priv->in_reply_to);
972 g_free (priv->last_search);
973 g_slist_free (priv->font_items_group);
974 g_slist_free (priv->size_items_group);
975 g_object_unref (priv->attachments);
976 g_object_unref (priv->images);
978 /* This had to stay alive for as long as the combobox that used it: */
979 modest_pair_list_free (priv->from_field_protos);
981 G_OBJECT_CLASS(parent_class)->finalize (obj);
985 pixbuf_from_stream (TnyStream *stream, const gchar *mime_type, guint64 *stream_size)
987 GdkPixbufLoader *loader;
993 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
995 if (loader == NULL) {
1001 tny_stream_reset (TNY_STREAM (stream));
1002 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
1003 GError *error = NULL;
1004 unsigned char read_buffer[128];
1006 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
1008 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
1015 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1017 g_object_ref (pixbuf);
1018 gdk_pixbuf_loader_close (loader, NULL);
1019 g_object_unref (loader);
1024 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1025 GdkPixbuf *new_pixbuf;
1027 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1028 gdk_pixbuf_get_width (pixbuf);
1029 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1030 g_object_unref (pixbuf);
1031 pixbuf = new_pixbuf;
1035 *stream_size = size;
1041 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1043 ModestMsgEditWindowPrivate *priv;
1046 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1048 for (iter = tny_list_create_iterator (attachments);
1049 !tny_iterator_is_done (iter);
1050 tny_iterator_next (iter)) {
1051 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1052 const gchar *cid = tny_mime_part_get_content_id (part);
1053 const gchar *mime_type = tny_mime_part_get_content_type (part);
1054 if ((cid != NULL)&&(mime_type != NULL)) {
1055 guint64 stream_size;
1056 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1057 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
1060 g_object_unref (stream);
1062 if (pixbuf != NULL) {
1063 priv->images_count ++;
1064 priv->images_size += stream_size;
1065 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1066 g_object_unref (pixbuf);
1069 g_object_unref (part);
1071 g_object_unref (iter);
1075 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1077 TnyMimePart *parent = NULL;
1078 const gchar *content_type = NULL;
1079 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1081 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1083 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1084 parent = g_object_ref (msg);
1085 } else if (content_type && !g_strcasecmp (content_type, "multipart/mixed")) {
1086 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1089 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1090 iter = tny_list_create_iterator (parts);
1091 while (!tny_iterator_is_done (iter)) {
1093 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1094 content_type = tny_mime_part_get_content_type (part);
1095 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1099 g_object_unref (part);
1101 tny_iterator_next (iter);
1103 g_object_unref (iter);
1104 g_object_unref (parts);
1107 if (parent != NULL) {
1108 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1111 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1112 iter = tny_list_create_iterator (parts);
1113 while (!tny_iterator_is_done (iter)) {
1115 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1116 content_type = tny_mime_part_get_content_type (part);
1117 if (content_type && g_str_has_prefix (content_type, "image/")) {
1118 tny_list_prepend (priv->images, (GObject *) part);
1120 g_object_unref (part);
1121 tny_iterator_next (iter);
1123 g_object_unref (iter);
1124 g_object_unref (parts);
1125 g_object_unref (parent);
1130 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1133 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1135 for (iter = tny_list_create_iterator (attachments) ;
1136 !tny_iterator_is_done (iter);
1137 tny_iterator_next (iter)) {
1138 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1139 const gchar *cid = tny_mime_part_get_content_id (part);
1141 char *invalid = NULL;
1142 gint int_cid = strtol (cid, &invalid, 10);
1143 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1144 priv->next_cid = int_cid + 1;
1147 g_object_unref (part);
1149 g_object_unref (iter);
1153 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1156 gchar *to, *cc, *bcc, *subject;
1158 ModestMsgEditWindowPrivate *priv;
1160 TnyHeaderFlags priority_flags;
1161 TnyFolder *msg_folder;
1162 gboolean is_html = FALSE;
1164 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1165 g_return_if_fail (TNY_IS_MSG (msg));
1167 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1169 header = tny_msg_get_header (msg);
1170 to = tny_header_dup_to (header);
1171 cc = tny_header_dup_cc (header);
1172 bcc = tny_header_dup_bcc (header);
1173 subject = tny_header_dup_subject (header);
1174 priority_flags = tny_header_get_priority (header);
1177 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
1179 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
1180 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1181 gtk_widget_show (priv->cc_caption);
1182 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1183 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1184 gtk_widget_hide (priv->cc_caption);
1187 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
1188 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1189 gtk_widget_show (priv->bcc_caption);
1190 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1191 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1192 gtk_widget_hide (priv->bcc_caption);
1195 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1196 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1198 modest_tny_msg_get_references (TNY_MSG (msg), NULL, &(priv->references), &(priv->in_reply_to));
1200 update_window_title (self);
1202 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1203 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1205 if ((body == NULL)||(body[0] == '\0')) {
1207 body = modest_text_utils_convert_to_html ("");
1210 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1211 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1214 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1217 /* Add attachments to the view */
1218 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1219 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1220 if (tny_list_get_length (priv->attachments) == 0) {
1221 gtk_widget_hide (priv->attachments_caption);
1223 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1224 gtk_widget_show_all (priv->attachments_caption);
1226 get_related_images (self, msg);
1227 update_next_cid (self, priv->attachments);
1228 update_next_cid (self, priv->images);
1229 replace_with_images (self, priv->images);
1231 if (preserve_is_rich && !is_html) {
1232 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1233 /* Get the default format required from configuration */
1234 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1235 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1238 /* Set the default focus depending on having already a To: field or not */
1239 if ((!to)||(*to == '\0')) {
1240 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1242 gtk_widget_grab_focus (priv->msg_body);
1245 /* TODO: lower priority, select in the From: combo to the
1246 value that comes from msg <- not sure, should it be
1249 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1251 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1252 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1254 modest_msg_edit_window_set_modified (self, FALSE);
1256 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1257 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1258 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1259 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1261 if (priv->msg_uid) {
1262 g_free (priv->msg_uid);
1263 priv->msg_uid = NULL;
1266 /* we should set a reference to the incoming message if it is a draft */
1267 msg_folder = tny_msg_get_folder (msg);
1269 if (modest_tny_folder_is_local_folder (msg_folder)) {
1270 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1271 if (type == TNY_FOLDER_TYPE_INVALID)
1272 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1274 if (type == TNY_FOLDER_TYPE_DRAFTS)
1275 priv->draft_msg = g_object_ref(msg);
1276 if (type == TNY_FOLDER_TYPE_OUTBOX)
1277 priv->outbox_msg = g_object_ref(msg);
1278 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1280 g_object_unref (msg_folder);
1290 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
1293 GList *item_children, *node;
1294 GtkWidget *bin_child;
1296 bin_child = gtk_bin_get_child (GTK_BIN(item));
1298 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
1300 for (node = item_children; node != NULL; node = g_list_next (node)) {
1301 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
1302 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
1305 g_list_free (item_children);
1309 menu_tool_button_dont_expand (GtkMenuToolButton *item)
1312 GList *item_children, *node;
1314 box = gtk_bin_get_child (GTK_BIN (item));
1315 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
1316 item_children = gtk_container_get_children (GTK_CONTAINER (box));
1318 for (node = item_children; node != NULL; node = g_list_next (node)) {
1319 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
1320 if (GTK_IS_TOGGLE_BUTTON (node->data))
1321 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
1322 else if (GTK_IS_BUTTON (node->data))
1323 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
1325 g_list_free (item_children);
1330 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1332 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1333 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1334 GtkWidget *placeholder;
1335 GtkWidget *tool_item;
1340 GtkWidget *sizes_menu;
1341 GtkWidget *fonts_menu;
1342 GSList *radio_group = NULL;
1343 GSList *node = NULL;
1347 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1348 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1350 /* Font color placeholder */
1351 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1352 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1355 tool_item = GTK_WIDGET (gtk_tool_item_new ());
1356 priv->font_color_button = hildon_color_button_new ();
1357 GTK_WIDGET_UNSET_FLAGS (tool_item, GTK_CAN_FOCUS);
1358 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1359 gtk_container_add (GTK_CONTAINER (tool_item), priv->font_color_button);
1360 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1361 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1362 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1363 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1365 G_CALLBACK (modest_msg_edit_window_color_button_change),
1368 /* Font size and face placeholder */
1369 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1370 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1372 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1373 priv->size_tool_button_label = gtk_label_new (NULL);
1374 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1375 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1376 size_text,"</span>", NULL);
1377 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1379 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
1380 sizes_menu = gtk_menu_new ();
1381 priv->size_items_group = NULL;
1383 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1384 GtkWidget *size_menu_item;
1386 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1387 size_menu_item = gtk_radio_menu_item_new_with_label (radio_group, size_text);
1388 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (size_menu_item));
1389 gtk_menu_shell_append (GTK_MENU_SHELL (sizes_menu), size_menu_item);
1390 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (size_menu_item), (wp_font_size[size_index] == 12));
1391 gtk_widget_show (size_menu_item);
1393 priv->size_items_group = g_slist_prepend (priv->size_items_group, size_menu_item);
1397 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1398 GtkWidget *item = (GtkWidget *) node->data;
1399 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_size_change),
1403 priv->size_items_group = g_slist_reverse (priv->size_items_group);
1404 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), sizes_menu);
1405 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1406 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1407 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1408 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1409 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1410 priv->font_size_toolitem = tool_item;
1413 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1414 priv->font_tool_button_label = gtk_label_new (NULL);
1415 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1416 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1418 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
1419 fonts_menu = gtk_menu_new ();
1420 priv->font_items_group = NULL;
1422 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1423 GtkWidget *font_menu_item;
1424 GtkWidget *child_label;
1426 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
1427 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
1428 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
1429 wp_get_font_name (font_index), "</span>", NULL);
1430 gtk_label_set_markup (GTK_LABEL (child_label), markup);
1433 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
1434 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
1435 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
1436 gtk_widget_show (font_menu_item);
1438 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
1441 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1442 GtkWidget *item = (GtkWidget *) node->data;
1443 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
1446 priv->font_items_group = g_slist_reverse (priv->font_items_group);
1447 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
1448 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1449 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1450 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1451 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1452 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1453 priv->font_face_toolitem = tool_item;
1455 /* Set expand and homogeneous for remaining items */
1456 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
1457 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1458 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1459 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1460 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1461 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1462 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1463 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1464 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1466 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1467 will not show the tool items added to the placeholders) */
1468 gtk_widget_show_all (parent_priv->toolbar);
1470 /* Set the no show all *after* showing all items. We do not
1471 want the toolbar to be shown with a show all because it
1472 could go agains the gconf setting regarding showing or not
1473 the toolbar of the editor window */
1474 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1480 modest_msg_edit_window_new (TnyMsg *msg,
1481 const gchar *account_name,
1482 const gchar *mailbox, /* ignored */
1483 gboolean preserve_is_rich)
1486 ModestWindowPrivate *parent_priv;
1487 ModestMsgEditWindowPrivate *priv;
1488 ModestDimmingRulesGroup *menu_rules_group = NULL;
1489 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1490 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1491 ModestWindowMgr *mgr = NULL;
1493 g_return_val_if_fail (msg, NULL);
1494 g_return_val_if_fail (account_name, NULL);
1496 mgr = modest_runtime_get_window_mgr ();
1498 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1500 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1501 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1503 /* Menubar. Update the state of some toggles */
1504 parent_priv->menubar = modest_maemo_utils_get_manager_menubar_as_menu (parent_priv->ui_manager, "/MenuBar");
1505 hildon_window_set_menu (HILDON_WINDOW (obj), GTK_MENU (parent_priv->menubar));
1506 priv->from_field_protos = get_transports ();
1507 modest_combo_box_set_pair_list (MODEST_COMBO_BOX (priv->from_field), priv->from_field_protos);
1508 modest_combo_box_set_active_id (MODEST_COMBO_BOX (priv->from_field), (gpointer) account_name);
1509 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1510 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1513 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1515 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1517 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1519 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1521 parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new ();
1522 menu_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_MENU, FALSE);
1523 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1524 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1525 /* Add common dimming rules */
1526 modest_dimming_rules_group_add_rules (menu_rules_group,
1527 modest_msg_edit_window_menu_dimming_entries,
1528 G_N_ELEMENTS (modest_msg_edit_window_menu_dimming_entries),
1529 MODEST_WINDOW (obj));
1530 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1531 modest_msg_edit_window_toolbar_dimming_entries,
1532 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1533 MODEST_WINDOW (obj));
1534 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_button,
1535 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1536 MODEST_WINDOW (obj));
1537 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1538 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1539 MODEST_WINDOW (obj));
1540 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1541 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1542 MODEST_WINDOW (obj));
1543 modest_dimming_rules_group_add_rules (clipboard_rules_group,
1544 modest_msg_edit_window_clipboard_dimming_entries,
1545 G_N_ELEMENTS (modest_msg_edit_window_clipboard_dimming_entries),
1546 MODEST_WINDOW (obj));
1547 /* Insert dimming rules group for this window */
1548 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
1549 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1550 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1551 /* Checks the dimming rules */
1552 g_object_unref (menu_rules_group);
1553 g_object_unref (toolbar_rules_group);
1554 g_object_unref (clipboard_rules_group);
1555 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1557 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1559 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1560 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1561 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1562 priv->update_caption_visibility = TRUE;
1564 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1566 /* Track account-removed signal, this window should be closed
1567 in the case we're creating a mail associated to the account
1569 priv->account_removed_handler_id =
1570 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1572 G_CALLBACK(on_account_removed),
1575 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1577 return (ModestWindow*) obj;
1581 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1583 GString **string_buffer = (GString **) user_data;
1585 *string_buffer = g_string_append (*string_buffer, buffer);
1591 * @result: A new string which should be freed with g_free().
1594 get_formatted_data (ModestMsgEditWindow *edit_window)
1596 ModestMsgEditWindowPrivate *priv;
1597 GString *string_buffer = g_string_new ("");
1599 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1601 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1603 modest_text_utils_hyperlinkify (string_buffer);
1605 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1607 return g_string_free (string_buffer, FALSE);
1612 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1615 const gchar *account_name;
1616 ModestMsgEditWindowPrivate *priv;
1617 TnyIterator *att_iter;
1619 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1621 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1623 account_name = modest_combo_box_get_active_id (MODEST_COMBO_BOX (priv->from_field));
1624 g_return_val_if_fail (account_name, NULL);
1627 /* don't free these (except from) */
1628 data = g_slice_new0 (MsgData);
1629 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1630 account_name, NULL);
1631 data->account_name = g_strdup (account_name);
1632 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1633 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1634 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1635 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1636 data->references = g_strdup (priv->references);
1637 data->in_reply_to = g_strdup (priv->in_reply_to);
1638 if (priv->draft_msg) {
1639 data->draft_msg = g_object_ref (priv->draft_msg);
1640 } else if (priv->outbox_msg) {
1641 data->draft_msg = g_object_ref (priv->outbox_msg);
1643 data->draft_msg = NULL;
1646 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1648 gtk_text_buffer_get_bounds (buf, &b, &e);
1649 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1651 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1652 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1654 data->html_body = NULL;
1656 /* deep-copy the data */
1657 att_iter = tny_list_create_iterator (priv->attachments);
1658 data->attachments = NULL;
1659 while (!tny_iterator_is_done (att_iter)) {
1660 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1661 if (!(TNY_IS_MIME_PART(part))) {
1662 g_warning ("strange data in attachment list");
1663 g_object_unref (part);
1664 tny_iterator_next (att_iter);
1667 data->attachments = g_list_append (data->attachments,
1669 tny_iterator_next (att_iter);
1671 g_object_unref (att_iter);
1673 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1674 att_iter = tny_list_create_iterator (priv->images);
1675 data->images = NULL;
1676 while (!tny_iterator_is_done (att_iter)) {
1677 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1679 if (!(TNY_IS_MIME_PART(part))) {
1680 g_warning ("strange data in attachment list");
1681 g_object_unref (part);
1682 tny_iterator_next (att_iter);
1685 cid = tny_mime_part_get_content_id (part);
1687 gchar *image_tag_id;
1688 GtkTextTag *image_tag;
1690 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1691 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1692 g_free (image_tag_id);
1694 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1696 ((gtk_text_iter_has_tag (&iter, image_tag))||
1697 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1698 data->images = g_list_append (data->images,
1699 g_object_ref (part));
1701 g_object_unref (part);
1702 tny_iterator_next (att_iter);
1704 g_object_unref (att_iter);
1706 data->priority_flags = priv->priority_flags;
1713 unref_gobject (GObject *obj, gpointer data)
1715 if (!G_IS_OBJECT(obj))
1717 g_object_unref (obj);
1721 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1724 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1732 g_free (data->from);
1733 g_free (data->subject);
1734 g_free (data->plain_body);
1735 g_free (data->html_body);
1736 g_free (data->account_name);
1737 g_free (data->in_reply_to);
1738 g_free (data->references);
1740 if (data->draft_msg != NULL) {
1741 g_object_unref (data->draft_msg);
1742 data->draft_msg = NULL;
1745 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1746 g_list_free (data->attachments);
1747 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1748 g_list_free (data->images);
1750 g_slice_free (MsgData, data);
1754 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1756 guint64 *parts_size)
1758 ModestMsgEditWindowPrivate *priv;
1760 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1762 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1764 /* TODO: add images */
1765 *parts_size += priv->images_size;
1766 *parts_count += priv->images_count;
1771 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1774 ModestMsgEditWindowPrivate *priv = NULL;
1775 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1777 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1779 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1781 return MODEST_MSG_EDIT_FORMAT_HTML;
1783 return MODEST_MSG_EDIT_FORMAT_TEXT;
1787 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1788 ModestMsgEditFormat format)
1790 ModestMsgEditWindowPrivate *priv;
1792 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1793 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1796 case MODEST_MSG_EDIT_FORMAT_HTML:
1797 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1799 case MODEST_MSG_EDIT_FORMAT_TEXT:
1800 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1803 g_return_if_reached ();
1807 ModestMsgEditFormatState *
1808 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1810 ModestMsgEditFormatState *format_state = NULL;
1811 ModestMsgEditWindowPrivate *priv;
1812 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1814 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1815 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1817 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1819 format_state = g_new0 (ModestMsgEditFormatState, 1);
1820 format_state->bold = buffer_format->bold&0x1;
1821 format_state->italics = buffer_format->italic&0x1;
1822 format_state->bullet = buffer_format->bullet&0x1;
1823 format_state->color = buffer_format->color;
1824 format_state->font_size = buffer_format->font_size;
1825 format_state->font_family = wp_get_font_name (buffer_format->font);
1826 format_state->justification = buffer_format->justification;
1827 g_free (buffer_format);
1829 return format_state;
1834 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1835 const ModestMsgEditFormatState *format_state)
1837 ModestMsgEditWindowPrivate *priv;
1838 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1839 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1840 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1841 g_return_if_fail (format_state != NULL);
1843 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1844 gtk_widget_grab_focus (priv->msg_body);
1845 buffer_format->bold = (format_state->bold != FALSE);
1846 buffer_format->italic = (format_state->italics != FALSE);
1847 buffer_format->color = format_state->color;
1848 buffer_format->font_size = format_state->font_size;
1849 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1850 buffer_format->justification = format_state->justification;
1851 buffer_format->bullet = format_state->bullet;
1853 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1855 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1856 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1857 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1858 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1859 buffer_format->cs.font = (buffer_format->font != current_format->font);
1860 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1861 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1863 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1864 if (buffer_format->cs.bold) {
1865 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
1866 GINT_TO_POINTER (buffer_format->bold&0x1));
1868 if (buffer_format->cs.italic) {
1869 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
1870 GINT_TO_POINTER (buffer_format->italic&0x1));
1872 if (buffer_format->cs.color) {
1873 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1874 GINT_TO_POINTER (&(buffer_format->color)));
1876 if (buffer_format->cs.font_size) {
1877 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1878 GINT_TO_POINTER (buffer_format->font_size));
1880 if (buffer_format->cs.justification) {
1881 switch (buffer_format->justification) {
1882 case GTK_JUSTIFY_LEFT:
1883 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
1884 GINT_TO_POINTER(TRUE));
1886 case GTK_JUSTIFY_CENTER:
1887 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
1888 GINT_TO_POINTER(TRUE));
1890 case GTK_JUSTIFY_RIGHT:
1891 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
1892 GINT_TO_POINTER(TRUE));
1899 if (buffer_format->cs.font) {
1900 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1901 GINT_TO_POINTER (buffer_format->font));
1903 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1904 if (buffer_format->cs.bullet) {
1905 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
1906 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
1908 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1910 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
1912 g_free (buffer_format);
1913 g_free (current_format);
1915 /* Check dimming rules */
1916 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1917 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1921 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1923 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1925 ModestWindowPrivate *parent_priv;
1926 ModestMsgEditWindowPrivate *priv;
1927 GtkWidget *new_size_menuitem;
1928 GtkWidget *new_font_menuitem;
1930 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1931 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1933 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1934 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu");
1935 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1936 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1938 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatPlainTextMenu");
1939 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1940 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1943 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1945 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1946 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1948 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1949 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1951 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
1952 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
1955 switch (buffer_format->justification)
1957 case GTK_JUSTIFY_LEFT:
1958 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
1960 case GTK_JUSTIFY_CENTER:
1961 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
1963 case GTK_JUSTIFY_RIGHT:
1964 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
1971 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
1973 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1974 G_CALLBACK (modest_msg_edit_window_color_button_change),
1976 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1977 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1978 G_CALLBACK (modest_msg_edit_window_color_button_change),
1981 new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group,
1982 buffer_format->font_size))->data);
1983 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1987 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1988 markup = g_strconcat ("<span font_family='Sans'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1989 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1991 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1992 G_CALLBACK (modest_msg_edit_window_size_change),
1994 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
1995 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
1996 G_CALLBACK (modest_msg_edit_window_size_change),
2000 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
2001 buffer_format->font))->data);
2002 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
2006 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
2007 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2008 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2010 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
2011 G_CALLBACK (modest_msg_edit_window_font_change),
2013 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
2014 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
2015 G_CALLBACK (modest_msg_edit_window_font_change),
2019 g_free (buffer_format);
2023 #ifdef MODEST_HILDON_VERSION_0
2025 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2028 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2029 ModestMsgEditWindowPrivate *priv;
2030 GtkWidget *dialog = NULL;
2032 GdkColor *new_color = NULL;
2034 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2035 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2037 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2038 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
2039 g_free (buffer_format);
2041 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2042 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2043 if (new_color != NULL) {
2044 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2045 (gpointer) new_color);
2048 gtk_widget_destroy (dialog);
2053 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2056 ModestMsgEditWindowPrivate *priv;
2057 GtkWidget *dialog = NULL;
2059 GdkColor *old_color = NULL;
2060 const GdkColor *new_color = NULL;
2062 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2063 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2065 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2066 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2068 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2069 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2070 if (new_color != NULL)
2071 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2073 gtk_widget_destroy (dialog);
2079 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2082 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2083 ModestMsgEditWindowPrivate *priv;
2084 GtkWidget *dialog = NULL;
2086 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2087 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2089 dialog = hildon_color_chooser_new ();
2090 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2091 g_free (buffer_format);
2093 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2095 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2096 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2099 gtk_widget_destroy (dialog);
2104 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2107 ModestMsgEditWindowPrivate *priv;
2108 GtkWidget *dialog = NULL;
2109 GdkColor *old_color = NULL;
2111 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2112 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2114 dialog = hildon_color_chooser_new ();
2115 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2117 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2119 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2120 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2122 gtk_widget_destroy (dialog);
2125 #endif /*!MODEST_HILDON_VERSION_0*/
2130 create_stream_for_uri (const gchar* uri)
2135 TnyStream *result = NULL;
2137 GnomeVFSHandle *handle = NULL;
2138 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2139 if (test == GNOME_VFS_OK) {
2140 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2141 /* Streams over OBEX (Bluetooth) are not seekable but
2142 * we expect them to be (we might need to read them
2143 * several times). So if this is a Bluetooth URI just
2144 * read the whole file into memory (this is not a fast
2145 * protocol so we can assume that these files are not
2146 * going to be very big) */
2147 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2148 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2149 TnyStream *memstream = tny_camel_mem_stream_new ();
2150 tny_stream_write_to_stream (vfssstream, memstream);
2151 g_object_unref (vfssstream);
2154 result = vfssstream;
2162 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2165 ModestMsgEditWindowPrivate *priv;
2166 GtkWidget *dialog = NULL;
2168 GSList *uris = NULL;
2169 GSList *uri_node = NULL;
2171 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2173 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2174 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2175 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2177 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2179 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2180 GTK_WINDOW (dialog),
2181 GTK_WINDOW (window));
2183 response = gtk_dialog_run (GTK_DIALOG (dialog));
2185 case GTK_RESPONSE_OK:
2186 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2191 gtk_widget_destroy (dialog);
2193 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2195 GnomeVFSHandle *handle = NULL;
2196 GnomeVFSResult result;
2197 GtkTextIter position;
2198 GtkTextMark *insert_mark;
2200 uri = (const gchar *) uri_node->data;
2201 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2202 if (result == GNOME_VFS_OK) {
2204 GnomeVFSFileInfo *info;
2205 gchar *filename, *basename, *escaped_filename;
2206 TnyMimePart *mime_part;
2208 const gchar *mime_type = NULL;
2209 GnomeVFSURI *vfs_uri;
2210 guint64 stream_size;
2212 gnome_vfs_close (handle);
2213 vfs_uri = gnome_vfs_uri_new (uri);
2215 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2216 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2217 g_free (escaped_filename);
2218 gnome_vfs_uri_unref (vfs_uri);
2219 info = gnome_vfs_file_info_new ();
2221 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2222 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2224 mime_type = gnome_vfs_file_info_get_mime_type (info);
2226 mime_part = tny_platform_factory_new_mime_part
2227 (modest_runtime_get_platform_factory ());
2229 TnyStream *stream = create_stream_for_uri (uri);
2231 if (stream == NULL) {
2233 modest_platform_information_banner (NULL, NULL,
2234 _FM("sfil_ib_opening_not_allowed"));
2236 g_object_unref (mime_part);
2237 gnome_vfs_file_info_unref (info);
2241 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2243 content_id = g_strdup_printf ("%d", priv->next_cid);
2244 tny_mime_part_set_content_id (mime_part, content_id);
2245 g_free (content_id);
2248 basename = g_path_get_basename (filename);
2249 tny_mime_part_set_filename (mime_part, basename);
2252 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
2254 if (pixbuf != NULL) {
2255 priv->images_size += stream_size;
2256 priv->images_count ++;
2257 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2258 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2259 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
2262 tny_list_prepend (priv->images, (GObject *) mime_part);
2263 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2265 g_object_unref (mime_part);
2266 gnome_vfs_file_info_unref (info);
2275 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2277 GtkWidget *dialog = NULL;
2279 GSList *uris = NULL;
2281 GnomeVFSFileSize total_size, allowed_size;
2282 ModestMsgEditWindowPrivate *priv;
2286 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2288 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2290 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2293 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2294 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2295 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2296 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), GTK_WINDOW (dialog), GTK_WINDOW (window));
2298 response = gtk_dialog_run (GTK_DIALOG (dialog));
2300 case GTK_RESPONSE_OK:
2301 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2306 gtk_widget_destroy (dialog);
2308 /* allowed size is the maximum size - what's already there */
2309 modest_attachments_view_get_sizes (
2310 MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2311 &att_num, &att_size);
2312 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2315 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2317 const gchar *uri = (const gchar *) uri_node->data;
2319 total_size += modest_msg_edit_window_attach_file_one
2320 (window, uri, allowed_size);
2322 if (total_size > allowed_size) {
2323 g_warning ("%s: total size: %u",
2324 __FUNCTION__, (unsigned int)total_size);
2328 allowed_size -= total_size;
2332 g_slist_foreach (uris, (GFunc) g_free, NULL);
2333 g_slist_free (uris);
2338 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2340 GnomeVFSFileSize allowed_size)
2343 GnomeVFSHandle *handle = NULL;
2344 ModestMsgEditWindowPrivate *priv;
2345 GnomeVFSResult result;
2346 GnomeVFSFileSize size = 0;
2347 g_return_val_if_fail (window, 0);
2348 g_return_val_if_fail (uri, 0);
2350 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2352 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2353 if (result == GNOME_VFS_OK) {
2354 TnyMimePart *mime_part;
2356 const gchar *mime_type = NULL;
2358 gchar *escaped_filename;
2361 GnomeVFSFileInfo *info;
2362 GnomeVFSURI *vfs_uri;
2364 gnome_vfs_close (handle);
2365 vfs_uri = gnome_vfs_uri_new (uri);
2368 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2369 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2370 g_free (escaped_filename);
2371 gnome_vfs_uri_unref (vfs_uri);
2373 info = gnome_vfs_file_info_new ();
2375 if (gnome_vfs_get_file_info (uri,
2377 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2379 mime_type = gnome_vfs_file_info_get_mime_type (info);
2380 mime_part = tny_platform_factory_new_mime_part
2381 (modest_runtime_get_platform_factory ());
2383 /* try to get the attachment's size; this may fail for weird
2384 * file systems, like obex, upnp... */
2385 if (allowed_size != 0 &&
2386 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2388 if (size > allowed_size) {
2389 modest_platform_information_banner (NULL, NULL,
2390 _FM("sfil_ib_opening_not_allowed"));
2394 g_warning ("%s: could not get attachment size", __FUNCTION__);
2396 stream = create_stream_for_uri (uri);
2398 if (stream == NULL) {
2400 modest_platform_information_banner (NULL, NULL, _FM("sfil_ib_opening_not_allowed"));
2402 g_object_unref (mime_part);
2403 gnome_vfs_file_info_unref (info);
2407 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2408 g_object_unref (stream);
2410 content_id = g_strdup_printf ("%d", priv->next_cid);
2411 tny_mime_part_set_content_id (mime_part, content_id);
2412 g_free (content_id);
2415 basename = g_path_get_basename (filename);
2416 tny_mime_part_set_filename (mime_part, basename);
2419 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2420 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2422 info->size == 0, info->size);
2423 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2424 gtk_widget_show_all (priv->attachments_caption);
2425 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2427 g_object_unref (mime_part);
2428 gnome_vfs_file_info_unref (info);
2435 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2438 ModestMsgEditWindowPrivate *priv;
2441 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2442 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2444 if (att_list == NULL) {
2445 att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2447 g_object_ref (att_list);
2450 if (tny_list_get_length (att_list) == 0) {
2451 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2453 gboolean dialog_response;
2454 gchar *message = NULL;
2455 gchar *filename = NULL;
2457 if (tny_list_get_length (att_list) == 1) {
2459 iter = tny_list_create_iterator (att_list);
2460 part = (TnyMimePart *) tny_iterator_get_current (iter);
2461 g_object_unref (iter);
2462 if (TNY_IS_MSG (part)) {
2463 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2465 filename = tny_header_dup_subject (header);
2466 g_object_unref (header);
2468 if (filename == NULL) {
2469 filename = g_strdup (_("mail_va_no_subject"));
2472 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2474 g_object_unref (part);
2476 filename = g_strdup ("");
2478 message = g_strdup_printf (ngettext("emev_nc_delete_attachment", "emev_nc_delete_attachments",
2479 tny_list_get_length (att_list)), filename);
2482 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window), message);
2485 if (dialog_response != GTK_RESPONSE_OK) {
2486 g_object_unref (att_list);
2489 hildon_banner_show_information (NULL, NULL, _("mcen_ib_removing_attachment"));
2491 for (iter = tny_list_create_iterator (att_list);
2492 !tny_iterator_is_done (iter);
2493 tny_iterator_next (iter)) {
2494 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2495 const gchar *att_id;
2496 tny_list_remove (priv->attachments, (GObject *) mime_part);
2498 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2500 if (tny_list_get_length (priv->attachments) == 0)
2501 gtk_widget_hide (priv->attachments_caption);
2502 att_id = tny_mime_part_get_content_id (mime_part);
2504 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2506 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2507 g_object_unref (mime_part);
2509 g_object_unref (iter);
2512 g_object_unref (att_list);
2514 /* if the last attachment has been removed, focus the Subject: field */
2515 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2516 gtk_widget_grab_focus (priv->subject_field);
2520 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2523 ModestMsgEditWindowPrivate *priv;
2524 GdkColor *new_color;
2525 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2527 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2528 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2531 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2533 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2535 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2537 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2542 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
2545 ModestMsgEditWindowPrivate *priv;
2546 gint new_size_index;
2547 ModestMsgEditWindow *window;
2550 window = MODEST_MSG_EDIT_WINDOW (userdata);
2551 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2552 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2554 if (gtk_check_menu_item_get_active (menu_item)) {
2556 WPTextBufferFormat format;
2558 memset (&format, 0, sizeof (format));
2559 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2561 label = gtk_bin_get_child (GTK_BIN (menu_item));
2563 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
2564 format.cs.font_size = TRUE;
2565 format.cs.text_position = TRUE;
2566 format.cs.font = TRUE;
2567 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
2568 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2570 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2571 GINT_TO_POINTER (wp_get_font_size_index (new_size_index, 12))))
2572 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2574 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2575 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
2576 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2582 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
2585 ModestMsgEditWindowPrivate *priv;
2586 gint new_font_index;
2587 ModestMsgEditWindow *window;
2590 window = MODEST_MSG_EDIT_WINDOW (userdata);
2591 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2592 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2594 if (gtk_check_menu_item_get_active (menu_item)) {
2597 label = gtk_bin_get_child (GTK_BIN (menu_item));
2599 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
2601 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2602 GINT_TO_POINTER(new_font_index)))
2603 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2605 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2606 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2607 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2613 modest_msg_edit_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
2615 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
2616 ModestWindowPrivate *parent_priv;
2617 ModestWindowMgr *mgr;
2618 gboolean is_fullscreen;
2619 GtkAction *fs_toggle_action;
2622 mgr = modest_runtime_get_window_mgr ();
2623 is_fullscreen = (modest_window_mgr_get_fullscreen_mode (mgr))?1:0;
2625 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
2627 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
2628 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
2629 if (is_fullscreen != active)
2630 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
2638 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2641 ModestMsgEditWindowPrivate *priv = NULL;
2642 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2644 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2645 if (!priv->update_caption_visibility)
2648 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2650 gtk_widget_show (priv->cc_caption);
2652 gtk_widget_hide (priv->cc_caption);
2654 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2658 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2661 ModestMsgEditWindowPrivate *priv = NULL;
2662 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2664 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2665 if (!priv->update_caption_visibility)
2668 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2670 gtk_widget_show (priv->bcc_caption);
2672 gtk_widget_hide (priv->bcc_caption);
2674 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2678 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2679 ModestRecptEditor *editor)
2681 ModestMsgEditWindowPrivate *priv;
2683 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2684 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2686 /* we check for low-mem; in that case, show a warning, and don't allow
2687 * for the addressbook
2689 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2692 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2694 if (editor == NULL) {
2695 GtkWidget *view_focus;
2696 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2698 /* This code should be kept in sync with ModestRecptEditor. The
2699 textview inside the recpt editor is the one that really gets the
2700 focus. As it's inside a scrolled window, and this one inside the
2701 hbox recpt editor inherits from, we'll need to go up in the
2702 hierarchy to know if the text view is part of the recpt editor
2703 or if it's a different text entry */
2705 if (gtk_widget_get_parent (view_focus)) {
2706 GtkWidget *first_parent;
2708 first_parent = gtk_widget_get_parent (view_focus);
2709 if (gtk_widget_get_parent (first_parent) &&
2710 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2711 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2716 editor = MODEST_RECPT_EDITOR (priv->to_field);
2720 modest_address_book_select_addresses (editor);
2725 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2727 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2729 modest_msg_edit_window_open_addressbook (window, NULL);
2733 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2734 gboolean show_toolbar)
2736 ModestWindowPrivate *parent_priv;
2737 const gchar *action_name;
2740 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2741 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2743 /* We can not just use the code of
2744 modest_msg_edit_window_setup_toolbar because it has a
2745 mixture of both initialization and creation code. */
2747 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2749 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2751 /* Update also the actions (to update the toggles in the
2752 menus), we have to do it manually because some other window
2753 of the same time could have changed it (remember that the
2754 toolbar fullscreen mode is shared by all the windows of the
2756 if (modest_window_mgr_get_fullscreen_mode (modest_runtime_get_window_mgr ()))
2757 action_name = "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarFullScreenMenu";
2759 action_name = "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarNormalScreenMenu";
2761 action = gtk_ui_manager_get_action (parent_priv->ui_manager, action_name);
2762 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
2768 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2769 TnyHeaderFlags priority_flags)
2771 ModestMsgEditWindowPrivate *priv;
2772 ModestWindowPrivate *parent_priv;
2774 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2776 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2777 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2779 if (priv->priority_flags != priority_flags) {
2780 GtkAction *priority_action = NULL;
2782 priv->priority_flags = priority_flags;
2784 switch (priority_flags) {
2785 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2786 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_high", GTK_ICON_SIZE_MENU);
2787 gtk_widget_show (priv->priority_icon);
2788 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2789 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2791 case TNY_HEADER_FLAG_LOW_PRIORITY:
2792 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_low", GTK_ICON_SIZE_MENU);
2793 gtk_widget_show (priv->priority_icon);
2794 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2795 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2798 gtk_widget_hide (priv->priority_icon);
2799 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2800 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2803 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2804 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2809 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2812 ModestMsgEditWindowPrivate *priv;
2813 ModestWindowPrivate *parent_priv;
2814 gint current_format;
2816 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2818 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2819 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2821 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2822 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2824 if (current_format != file_format) {
2825 switch (file_format) {
2826 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2827 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2828 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
2830 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2834 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2835 response = gtk_dialog_run (GTK_DIALOG (dialog));
2836 gtk_widget_destroy (dialog);
2837 if (response == GTK_RESPONSE_OK) {
2838 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2840 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu"));
2841 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
2846 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2847 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2848 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2853 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2856 ModestMsgEditWindowPrivate *priv;
2857 WPTextBufferFormat oldfmt, fmt;
2858 gint old_position = 0;
2862 GdkColor *color = NULL;
2863 gboolean bold, bold_set, italic, italic_set;
2864 gboolean underline, underline_set;
2865 gboolean strikethrough, strikethrough_set;
2866 gboolean position_set;
2867 gboolean font_size_set, font_set, color_set;
2870 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2871 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2873 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2874 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
2875 GTK_WINDOW(dialog), GTK_WINDOW (window));
2877 /* First we get the currently selected font information */
2878 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2880 switch (oldfmt.text_position) {
2881 case TEXT_POSITION_NORMAL:
2884 case TEXT_POSITION_SUPERSCRIPT:
2892 g_object_set (G_OBJECT (dialog),
2893 "bold", oldfmt.bold != FALSE,
2894 "bold-set", !oldfmt.cs.bold,
2895 "underline", oldfmt.underline != FALSE,
2896 "underline-set", !oldfmt.cs.underline,
2897 "italic", oldfmt.italic != FALSE,
2898 "italic-set", !oldfmt.cs.italic,
2899 "strikethrough", oldfmt.strikethrough != FALSE,
2900 "strikethrough-set", !oldfmt.cs.strikethrough,
2901 "color", &oldfmt.color,
2902 "color-set", !oldfmt.cs.color,
2903 "size", wp_font_size[oldfmt.font_size],
2904 "size-set", !oldfmt.cs.font_size,
2905 "position", old_position,
2906 "position-set", !oldfmt.cs.text_position,
2907 "family", wp_get_font_name (oldfmt.font),
2908 "family-set", !oldfmt.cs.font,
2911 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2912 GTK_WINDOW (dialog), GTK_WINDOW (window));
2913 gtk_widget_show_all (dialog);
2914 priv->font_dialog = dialog;
2915 response = gtk_dialog_run (GTK_DIALOG (dialog));
2916 priv->font_dialog = NULL;
2917 if (response == GTK_RESPONSE_OK) {
2919 g_object_get( dialog,
2921 "bold-set", &bold_set,
2922 "underline", &underline,
2923 "underline-set", &underline_set,
2925 "italic-set", &italic_set,
2926 "strikethrough", &strikethrough,
2927 "strikethrough-set", &strikethrough_set,
2929 "color-set", &color_set,
2931 "size-set", &font_size_set,
2932 "family", &font_name,
2933 "family-set", &font_set,
2934 "position", &position,
2935 "position-set", &position_set,
2940 if (response == GTK_RESPONSE_OK) {
2941 memset(&fmt, 0, sizeof(fmt));
2947 fmt.italic = italic;
2948 fmt.cs.italic = TRUE;
2950 if (underline_set) {
2951 fmt.underline = underline;
2952 fmt.cs.underline = TRUE;
2954 if (strikethrough_set) {
2955 fmt.strikethrough = strikethrough;
2956 fmt.cs.strikethrough = TRUE;
2961 ? TEXT_POSITION_NORMAL
2962 : ( ( position == 1 )
2963 ? TEXT_POSITION_SUPERSCRIPT
2964 : TEXT_POSITION_SUBSCRIPT );
2965 fmt.cs.text_position = TRUE;
2966 fmt.font_size = oldfmt.font_size;
2970 fmt.cs.color = TRUE;
2973 fmt.font = wp_get_font_index(font_name,
2978 if (font_size_set) {
2979 fmt.cs.font_size = TRUE;
2980 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
2982 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2983 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2985 gtk_widget_destroy (dialog);
2987 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2991 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2993 ModestMsgEditWindowPrivate *priv;
2995 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2996 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2998 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
3000 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3001 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3005 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
3007 ModestMsgEditWindowPrivate *priv;
3009 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3010 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3012 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
3014 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3015 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3020 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
3022 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3024 priv->can_undo = can_undo;
3028 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
3030 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3032 priv->can_redo = can_redo;
3036 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3038 ModestMsgEditWindowPrivate *priv;
3039 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3040 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3042 return priv->can_undo;
3046 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3048 ModestMsgEditWindowPrivate *priv;
3049 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3050 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3052 return priv->can_redo;
3057 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3060 GtkTextIter match_start, match_end;
3062 if (image_id == NULL)
3065 gtk_text_buffer_get_start_iter (buffer, &iter);
3067 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3068 GSList *tags = gtk_text_iter_get_tags (&match_start);
3070 for (node = tags; node != NULL; node = g_slist_next (node)) {
3071 GtkTextTag *tag = (GtkTextTag *) node->data;
3072 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3073 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3074 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3076 offset = gtk_text_iter_get_offset (&match_start);
3077 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3078 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3082 gtk_text_iter_forward_char (&iter);
3087 message_is_empty (ModestMsgEditWindow *window)
3089 ModestMsgEditWindowPrivate *priv = NULL;
3091 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3092 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3094 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3095 * so we can ignore markup.
3097 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3100 count = gtk_text_buffer_get_char_count (buf);
3106 msg_body_focus (GtkWidget *focus,
3107 GdkEventFocus *event,
3111 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3112 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3113 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3118 recpt_field_changed (GtkTextBuffer *buffer,
3119 ModestMsgEditWindow *editor)
3121 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3122 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3126 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3128 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3129 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3133 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3136 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3137 GtkTextBuffer *buffer;
3139 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3140 gtk_text_buffer_set_modified (buffer, modified);
3141 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3142 gtk_text_buffer_set_modified (buffer, modified);
3143 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3144 gtk_text_buffer_set_modified (buffer, modified);
3145 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3149 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3151 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3152 const char *account_name;
3153 GtkTextBuffer *buffer;
3155 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3156 if (gtk_text_buffer_get_modified (buffer))
3158 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3159 if (gtk_text_buffer_get_modified (buffer))
3161 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3162 if (gtk_text_buffer_get_modified (buffer))
3164 if (gtk_text_buffer_get_modified (priv->text_buffer))
3166 account_name = modest_combo_box_get_active_id (MODEST_COMBO_BOX (priv->from_field));
3167 if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3178 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3180 ModestMsgEditWindowPrivate *priv = NULL;
3182 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3183 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3185 /* check if there's no recipient added */
3186 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3187 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3188 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3189 /* no recipient contents, then select contacts */
3190 modest_msg_edit_window_open_addressbook (window, NULL);
3194 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3195 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3198 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3199 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3202 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3203 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3207 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3208 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3209 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3216 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3217 ModestMsgEditWindow *window)
3219 modest_msg_edit_window_offer_attach_file (window);
3223 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3225 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3227 return priv->clipboard_text;
3231 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3233 ModestMsgEditWindow *window)
3235 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3236 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3238 if (!GTK_WIDGET_VISIBLE (window))
3241 g_object_ref (window);
3242 text = gtk_clipboard_wait_for_text (selection_clipboard);
3244 if (priv->clipboard_text != NULL) {
3245 g_free (priv->clipboard_text);
3247 priv->clipboard_text = text;
3249 if (GTK_WIDGET_VISIBLE (window)) {
3250 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3252 g_object_unref (window);
3255 static gboolean clipboard_owner_change_idle (gpointer userdata)
3257 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3258 ModestMsgEditWindowPrivate *priv;
3260 gdk_threads_enter ();
3261 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3262 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3264 priv->clipboard_owner_idle = 0;
3265 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3266 gdk_threads_leave ();
3272 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3274 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3275 if (priv->clipboard_owner_idle == 0) {
3276 priv->clipboard_owner_idle = g_idle_add (clipboard_owner_change_idle, window);
3281 subject_field_move_cursor (GtkEntry *entry,
3282 GtkMovementStep step,
3287 if (!GTK_WIDGET_VISIBLE (window))
3290 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3294 update_window_title (ModestMsgEditWindow *window)
3296 ModestMsgEditWindowPrivate *priv = NULL;
3297 const gchar *subject;
3299 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3300 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3301 if (subject == NULL || subject[0] == '\0')
3302 subject = _("mail_va_new_email");
3304 gtk_window_set_title (GTK_WINDOW (window), subject);
3309 subject_field_changed (GtkEditable *editable,
3310 ModestMsgEditWindow *window)
3312 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3313 update_window_title (window);
3314 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3315 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3316 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3320 subject_field_insert_text (GtkEditable *editable,
3322 gint new_text_length,
3324 ModestMsgEditWindow *window)
3326 GString *result = g_string_new ("");
3328 gint result_len = 0;
3329 const gchar *entry_text = NULL;
3332 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3333 old_length = g_utf8_strlen (entry_text, -1);
3335 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3336 gunichar c = g_utf8_get_char_validated (current, 8);
3337 /* Invalid unichar, stop */
3343 result = g_string_append_unichar (result, c);
3347 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3348 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3351 /* Prevent endless recursion */
3352 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3353 g_signal_emit_by_name (editable, "insert-text",
3354 (gpointer) result->str, (gpointer) result->len,
3355 (gpointer) position, (gpointer) window);
3356 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3360 if (result_len + old_length > 1000) {
3361 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3362 _CS("ckdg_ib_maximum_characters_reached"));
3365 g_string_free (result, TRUE);
3369 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3372 ModestMsgEditWindowPrivate *priv = NULL;
3374 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3375 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3377 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3380 gtk_widget_show_all (priv->find_toolbar);
3381 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3383 gtk_widget_hide_all (priv->find_toolbar);
3384 gtk_widget_grab_focus (priv->msg_body);
3390 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3392 GtkTextIter *match_start,
3393 GtkTextIter *match_end)
3395 GtkTextIter end_iter;
3396 gchar *str_casefold;
3399 gchar *range_casefold;
3402 gboolean result = FALSE;
3409 gtk_text_iter_forward_to_end (&end_iter);
3411 str_casefold = g_utf8_casefold (str, -1);
3412 str_chars_n = strlen (str);
3414 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3415 range_casefold = g_utf8_casefold (range_text, -1);
3416 range_chars_n = strlen (range_casefold);
3418 if (range_chars_n < str_chars_n) {
3419 g_free (str_casefold);
3420 g_free (range_text);
3421 g_free (range_casefold);
3425 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3426 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3427 if (!g_utf8_collate (range_subtext, str_casefold)) {
3428 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3430 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3431 match_start, match_end, NULL);
3432 g_free (found_text);
3434 g_free (range_subtext);
3438 g_free (str_casefold);
3439 g_free (range_text);
3440 g_free (range_casefold);
3447 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3448 ModestMsgEditWindow *window)
3450 gchar *current_search = NULL;
3451 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3453 GtkTextIter selection_start, selection_end;
3454 GtkTextIter match_start, match_end;
3455 gboolean continue_search = FALSE;
3457 if (message_is_empty (window)) {
3458 g_free (priv->last_search);
3459 priv->last_search = NULL;
3460 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3464 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3465 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3466 g_free (current_search);
3467 g_free (priv->last_search);
3468 priv->last_search = NULL;
3469 /* Information banner about empty search */
3470 hildon_banner_show_information (NULL, NULL,
3471 _CS ("ecdg_ib_find_rep_enter_text"));
3475 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3476 continue_search = TRUE;
3478 g_free (priv->last_search);
3479 priv->last_search = g_strdup (current_search);
3482 if (continue_search) {
3483 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3484 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3485 &match_start, &match_end);
3487 hildon_banner_show_information (NULL, NULL,
3488 _HL ("ckct_ib_find_search_complete"));
3490 GtkTextIter buffer_start;
3491 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3492 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3493 &match_start, &match_end);
3495 hildon_banner_show_information (NULL, NULL,
3496 _HL ("ckct_ib_find_no_matches"));
3499 /* Mark as selected the string found in search */
3501 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3502 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3503 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3505 g_free (priv->last_search);
3506 priv->last_search = NULL;
3508 g_free (current_search);
3512 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3513 ModestMsgEditWindow *window)
3515 GtkToggleAction *toggle;
3516 ModestWindowPrivate *parent_priv;
3517 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3519 toggle = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ToolsMenu/FindInMessageMenu"));
3520 gtk_toggle_action_set_active (toggle, FALSE);
3524 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3526 ModestMsgEditWindowPrivate *priv;
3528 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3533 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3536 ModestMsgEditWindowPrivate *priv;
3538 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3544 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3547 ModestMsgEditWindowPrivate *priv;
3548 TnyHeader *header = NULL;
3550 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3551 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3553 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3554 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3556 if (priv->draft_msg != NULL) {
3557 g_object_unref (priv->draft_msg);
3560 if (draft != NULL) {
3561 g_object_ref (draft);
3562 header = tny_msg_get_header (draft);
3563 if (priv->msg_uid) {
3564 g_free (priv->msg_uid);
3565 priv->msg_uid = NULL;
3567 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3568 if (GTK_WIDGET_REALIZED (window))
3569 modest_window_mgr_register_window (mgr, MODEST_WINDOW (window), NULL);
3572 priv->draft_msg = draft;
3576 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3577 GtkTextIter *start, GtkTextIter *end,
3580 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3581 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3584 if (tag == NULL) return;
3585 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3586 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3587 replace_with_images (window, priv->images);
3592 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3595 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3597 g_return_if_fail (TNY_IS_MIME_PART (part));
3598 tny_list_prepend (priv->attachments, (GObject *) part);
3599 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3600 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3601 gtk_widget_show_all (priv->attachments_caption);
3602 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3606 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3608 ModestMsgEditWindowPrivate *priv;
3610 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3611 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3613 return priv->msg_uid;
3617 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3618 ModestMsgEditWindowWidgetType widget_type)
3620 ModestMsgEditWindowPrivate *priv;
3622 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3623 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3625 switch (widget_type) {
3626 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3627 return priv->msg_body;
3629 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3630 return priv->to_field;
3632 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3633 return priv->cc_field;
3635 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3636 return priv->bcc_field;
3638 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3639 return priv->subject_field;
3641 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3642 return priv->attachments_view;
3650 remove_tags (WPTextBuffer *buffer)
3652 GtkTextIter start, end;
3654 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3655 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3657 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3661 on_account_removed (TnyAccountStore *account_store,
3662 TnyAccount *account,
3665 /* Do nothing if it's a store account, because we use the
3666 transport to send the messages */
3667 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3668 const gchar *parent_acc = NULL;
3669 const gchar *our_acc = NULL;
3671 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3672 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3673 /* Close this window if I'm showing a message of the removed account */
3674 if (strcmp (parent_acc, our_acc) == 0)
3675 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3680 on_zoom_minus_plus_not_implemented (ModestWindow *window)
3682 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3684 hildon_banner_show_information (NULL, NULL,
3685 _CS("ckct_ib_cannot_zoom_here"));
3691 set_zoom_do_nothing (ModestWindow *window,
3697 get_zoom_do_nothing (ModestWindow *window)