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, const gchar *account_name, gboolean preserve_is_rich)
1483 ModestWindowPrivate *parent_priv;
1484 ModestMsgEditWindowPrivate *priv;
1485 ModestDimmingRulesGroup *menu_rules_group = NULL;
1486 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1487 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1488 ModestWindowMgr *mgr = NULL;
1490 g_return_val_if_fail (msg, NULL);
1491 g_return_val_if_fail (account_name, NULL);
1493 mgr = modest_runtime_get_window_mgr ();
1495 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1497 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1498 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1500 /* Menubar. Update the state of some toggles */
1501 parent_priv->menubar = modest_maemo_utils_get_manager_menubar_as_menu (parent_priv->ui_manager, "/MenuBar");
1502 hildon_window_set_menu (HILDON_WINDOW (obj), GTK_MENU (parent_priv->menubar));
1503 priv->from_field_protos = get_transports ();
1504 modest_combo_box_set_pair_list (MODEST_COMBO_BOX (priv->from_field), priv->from_field_protos);
1505 modest_combo_box_set_active_id (MODEST_COMBO_BOX (priv->from_field), (gpointer) account_name);
1506 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1507 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1510 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1512 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1514 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1516 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1518 parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new ();
1519 menu_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_MENU, FALSE);
1520 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1521 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1522 /* Add common dimming rules */
1523 modest_dimming_rules_group_add_rules (menu_rules_group,
1524 modest_msg_edit_window_menu_dimming_entries,
1525 G_N_ELEMENTS (modest_msg_edit_window_menu_dimming_entries),
1526 MODEST_WINDOW (obj));
1527 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1528 modest_msg_edit_window_toolbar_dimming_entries,
1529 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1530 MODEST_WINDOW (obj));
1531 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_button,
1532 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1533 MODEST_WINDOW (obj));
1534 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
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_face_toolitem,
1538 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1539 MODEST_WINDOW (obj));
1540 modest_dimming_rules_group_add_rules (clipboard_rules_group,
1541 modest_msg_edit_window_clipboard_dimming_entries,
1542 G_N_ELEMENTS (modest_msg_edit_window_clipboard_dimming_entries),
1543 MODEST_WINDOW (obj));
1544 /* Insert dimming rules group for this window */
1545 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
1546 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1547 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1548 /* Checks the dimming rules */
1549 g_object_unref (menu_rules_group);
1550 g_object_unref (toolbar_rules_group);
1551 g_object_unref (clipboard_rules_group);
1552 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1554 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1556 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1557 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1558 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1559 priv->update_caption_visibility = TRUE;
1561 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1563 /* Track account-removed signal, this window should be closed
1564 in the case we're creating a mail associated to the account
1566 priv->account_removed_handler_id =
1567 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1569 G_CALLBACK(on_account_removed),
1572 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1574 return (ModestWindow*) obj;
1578 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1580 GString **string_buffer = (GString **) user_data;
1582 *string_buffer = g_string_append (*string_buffer, buffer);
1588 * @result: A new string which should be freed with g_free().
1591 get_formatted_data (ModestMsgEditWindow *edit_window)
1593 ModestMsgEditWindowPrivate *priv;
1594 GString *string_buffer = g_string_new ("");
1596 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1598 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1600 modest_text_utils_hyperlinkify (string_buffer);
1602 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1604 return g_string_free (string_buffer, FALSE);
1609 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1612 const gchar *account_name;
1613 ModestMsgEditWindowPrivate *priv;
1614 TnyIterator *att_iter;
1616 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1618 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1620 account_name = modest_combo_box_get_active_id (MODEST_COMBO_BOX (priv->from_field));
1621 g_return_val_if_fail (account_name, NULL);
1624 /* don't free these (except from) */
1625 data = g_slice_new0 (MsgData);
1626 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1628 data->account_name = g_strdup (account_name);
1629 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1630 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1631 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1632 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1633 data->references = g_strdup (priv->references);
1634 data->in_reply_to = g_strdup (priv->in_reply_to);
1635 if (priv->draft_msg) {
1636 data->draft_msg = g_object_ref (priv->draft_msg);
1637 } else if (priv->outbox_msg) {
1638 data->draft_msg = g_object_ref (priv->outbox_msg);
1640 data->draft_msg = NULL;
1643 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1645 gtk_text_buffer_get_bounds (buf, &b, &e);
1646 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1648 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1649 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1651 data->html_body = NULL;
1653 /* deep-copy the data */
1654 att_iter = tny_list_create_iterator (priv->attachments);
1655 data->attachments = NULL;
1656 while (!tny_iterator_is_done (att_iter)) {
1657 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1658 if (!(TNY_IS_MIME_PART(part))) {
1659 g_warning ("strange data in attachment list");
1660 g_object_unref (part);
1661 tny_iterator_next (att_iter);
1664 data->attachments = g_list_append (data->attachments,
1666 tny_iterator_next (att_iter);
1668 g_object_unref (att_iter);
1670 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1671 att_iter = tny_list_create_iterator (priv->images);
1672 data->images = NULL;
1673 while (!tny_iterator_is_done (att_iter)) {
1674 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1676 if (!(TNY_IS_MIME_PART(part))) {
1677 g_warning ("strange data in attachment list");
1678 g_object_unref (part);
1679 tny_iterator_next (att_iter);
1682 cid = tny_mime_part_get_content_id (part);
1684 gchar *image_tag_id;
1685 GtkTextTag *image_tag;
1687 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1688 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1689 g_free (image_tag_id);
1691 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1693 ((gtk_text_iter_has_tag (&iter, image_tag))||
1694 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1695 data->images = g_list_append (data->images,
1696 g_object_ref (part));
1698 g_object_unref (part);
1699 tny_iterator_next (att_iter);
1701 g_object_unref (att_iter);
1703 data->priority_flags = priv->priority_flags;
1710 unref_gobject (GObject *obj, gpointer data)
1712 if (!G_IS_OBJECT(obj))
1714 g_object_unref (obj);
1718 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1721 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1729 g_free (data->from);
1730 g_free (data->subject);
1731 g_free (data->plain_body);
1732 g_free (data->html_body);
1733 g_free (data->account_name);
1734 g_free (data->in_reply_to);
1735 g_free (data->references);
1737 if (data->draft_msg != NULL) {
1738 g_object_unref (data->draft_msg);
1739 data->draft_msg = NULL;
1742 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1743 g_list_free (data->attachments);
1744 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1745 g_list_free (data->images);
1747 g_slice_free (MsgData, data);
1751 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1753 guint64 *parts_size)
1755 ModestMsgEditWindowPrivate *priv;
1757 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1759 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1761 /* TODO: add images */
1762 *parts_size += priv->images_size;
1763 *parts_count += priv->images_count;
1768 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1771 ModestMsgEditWindowPrivate *priv = NULL;
1772 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1774 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1776 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1778 return MODEST_MSG_EDIT_FORMAT_HTML;
1780 return MODEST_MSG_EDIT_FORMAT_TEXT;
1784 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1785 ModestMsgEditFormat format)
1787 ModestMsgEditWindowPrivate *priv;
1789 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1790 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1793 case MODEST_MSG_EDIT_FORMAT_HTML:
1794 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1796 case MODEST_MSG_EDIT_FORMAT_TEXT:
1797 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1800 g_return_if_reached ();
1804 ModestMsgEditFormatState *
1805 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1807 ModestMsgEditFormatState *format_state = NULL;
1808 ModestMsgEditWindowPrivate *priv;
1809 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1811 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1812 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1814 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1816 format_state = g_new0 (ModestMsgEditFormatState, 1);
1817 format_state->bold = buffer_format->bold&0x1;
1818 format_state->italics = buffer_format->italic&0x1;
1819 format_state->bullet = buffer_format->bullet&0x1;
1820 format_state->color = buffer_format->color;
1821 format_state->font_size = buffer_format->font_size;
1822 format_state->font_family = wp_get_font_name (buffer_format->font);
1823 format_state->justification = buffer_format->justification;
1824 g_free (buffer_format);
1826 return format_state;
1831 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1832 const ModestMsgEditFormatState *format_state)
1834 ModestMsgEditWindowPrivate *priv;
1835 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1836 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1837 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1838 g_return_if_fail (format_state != NULL);
1840 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1841 gtk_widget_grab_focus (priv->msg_body);
1842 buffer_format->bold = (format_state->bold != FALSE);
1843 buffer_format->italic = (format_state->italics != FALSE);
1844 buffer_format->color = format_state->color;
1845 buffer_format->font_size = format_state->font_size;
1846 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1847 buffer_format->justification = format_state->justification;
1848 buffer_format->bullet = format_state->bullet;
1850 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1852 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1853 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1854 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1855 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1856 buffer_format->cs.font = (buffer_format->font != current_format->font);
1857 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1858 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1860 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1861 if (buffer_format->cs.bold) {
1862 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
1863 GINT_TO_POINTER (buffer_format->bold&0x1));
1865 if (buffer_format->cs.italic) {
1866 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
1867 GINT_TO_POINTER (buffer_format->italic&0x1));
1869 if (buffer_format->cs.color) {
1870 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1871 GINT_TO_POINTER (&(buffer_format->color)));
1873 if (buffer_format->cs.font_size) {
1874 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1875 GINT_TO_POINTER (buffer_format->font_size));
1877 if (buffer_format->cs.justification) {
1878 switch (buffer_format->justification) {
1879 case GTK_JUSTIFY_LEFT:
1880 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
1881 GINT_TO_POINTER(TRUE));
1883 case GTK_JUSTIFY_CENTER:
1884 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
1885 GINT_TO_POINTER(TRUE));
1887 case GTK_JUSTIFY_RIGHT:
1888 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
1889 GINT_TO_POINTER(TRUE));
1896 if (buffer_format->cs.font) {
1897 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1898 GINT_TO_POINTER (buffer_format->font));
1900 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1901 if (buffer_format->cs.bullet) {
1902 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
1903 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
1905 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1907 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
1909 g_free (buffer_format);
1910 g_free (current_format);
1912 /* Check dimming rules */
1913 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1914 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1918 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1920 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1922 ModestWindowPrivate *parent_priv;
1923 ModestMsgEditWindowPrivate *priv;
1924 GtkWidget *new_size_menuitem;
1925 GtkWidget *new_font_menuitem;
1927 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1928 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1930 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1931 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu");
1932 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1933 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1935 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatPlainTextMenu");
1936 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1937 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1940 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1942 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1943 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1945 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1946 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1948 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
1949 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
1952 switch (buffer_format->justification)
1954 case GTK_JUSTIFY_LEFT:
1955 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
1957 case GTK_JUSTIFY_CENTER:
1958 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
1960 case GTK_JUSTIFY_RIGHT:
1961 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
1968 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
1970 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1971 G_CALLBACK (modest_msg_edit_window_color_button_change),
1973 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1974 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1975 G_CALLBACK (modest_msg_edit_window_color_button_change),
1978 new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group,
1979 buffer_format->font_size))->data);
1980 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1984 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1985 markup = g_strconcat ("<span font_family='Sans'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1986 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1988 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1989 G_CALLBACK (modest_msg_edit_window_size_change),
1991 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
1992 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
1993 G_CALLBACK (modest_msg_edit_window_size_change),
1997 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
1998 buffer_format->font))->data);
1999 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
2003 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
2004 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2005 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2007 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
2008 G_CALLBACK (modest_msg_edit_window_font_change),
2010 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
2011 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
2012 G_CALLBACK (modest_msg_edit_window_font_change),
2016 g_free (buffer_format);
2020 #ifdef MODEST_HILDON_VERSION_0
2022 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2025 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2026 ModestMsgEditWindowPrivate *priv;
2027 GtkWidget *dialog = NULL;
2029 GdkColor *new_color = NULL;
2031 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2032 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2034 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2035 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
2036 g_free (buffer_format);
2038 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2039 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2040 if (new_color != NULL) {
2041 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2042 (gpointer) new_color);
2045 gtk_widget_destroy (dialog);
2050 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2053 ModestMsgEditWindowPrivate *priv;
2054 GtkWidget *dialog = NULL;
2056 GdkColor *old_color = NULL;
2057 const GdkColor *new_color = NULL;
2059 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2060 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2062 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2063 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2065 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2066 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2067 if (new_color != NULL)
2068 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2070 gtk_widget_destroy (dialog);
2076 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2079 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2080 ModestMsgEditWindowPrivate *priv;
2081 GtkWidget *dialog = NULL;
2083 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2084 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2086 dialog = hildon_color_chooser_new ();
2087 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2088 g_free (buffer_format);
2090 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2092 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2093 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2096 gtk_widget_destroy (dialog);
2101 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2104 ModestMsgEditWindowPrivate *priv;
2105 GtkWidget *dialog = NULL;
2106 GdkColor *old_color = NULL;
2108 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2109 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2111 dialog = hildon_color_chooser_new ();
2112 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2114 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2116 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2117 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2119 gtk_widget_destroy (dialog);
2122 #endif /*!MODEST_HILDON_VERSION_0*/
2127 create_stream_for_uri (const gchar* uri)
2132 TnyStream *result = NULL;
2134 GnomeVFSHandle *handle = NULL;
2135 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2136 if (test == GNOME_VFS_OK) {
2137 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2138 /* Streams over OBEX (Bluetooth) are not seekable but
2139 * we expect them to be (we might need to read them
2140 * several times). So if this is a Bluetooth URI just
2141 * read the whole file into memory (this is not a fast
2142 * protocol so we can assume that these files are not
2143 * going to be very big) */
2144 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2145 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2146 TnyStream *memstream = tny_camel_mem_stream_new ();
2147 tny_stream_write_to_stream (vfssstream, memstream);
2148 g_object_unref (vfssstream);
2151 result = vfssstream;
2159 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2162 ModestMsgEditWindowPrivate *priv;
2163 GtkWidget *dialog = NULL;
2165 GSList *uris = NULL;
2166 GSList *uri_node = NULL;
2168 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2170 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2171 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2172 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2174 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2176 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2177 GTK_WINDOW (dialog),
2178 GTK_WINDOW (window));
2180 response = gtk_dialog_run (GTK_DIALOG (dialog));
2182 case GTK_RESPONSE_OK:
2183 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2188 gtk_widget_destroy (dialog);
2190 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2192 GnomeVFSHandle *handle = NULL;
2193 GnomeVFSResult result;
2194 GtkTextIter position;
2195 GtkTextMark *insert_mark;
2197 uri = (const gchar *) uri_node->data;
2198 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2199 if (result == GNOME_VFS_OK) {
2201 GnomeVFSFileInfo *info;
2202 gchar *filename, *basename, *escaped_filename;
2203 TnyMimePart *mime_part;
2205 const gchar *mime_type = NULL;
2206 GnomeVFSURI *vfs_uri;
2207 guint64 stream_size;
2209 gnome_vfs_close (handle);
2210 vfs_uri = gnome_vfs_uri_new (uri);
2212 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2213 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2214 g_free (escaped_filename);
2215 gnome_vfs_uri_unref (vfs_uri);
2216 info = gnome_vfs_file_info_new ();
2218 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2219 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2221 mime_type = gnome_vfs_file_info_get_mime_type (info);
2223 mime_part = tny_platform_factory_new_mime_part
2224 (modest_runtime_get_platform_factory ());
2226 TnyStream *stream = create_stream_for_uri (uri);
2228 if (stream == NULL) {
2230 modest_platform_information_banner (NULL, NULL,
2231 _FM("sfil_ib_opening_not_allowed"));
2233 g_object_unref (mime_part);
2234 gnome_vfs_file_info_unref (info);
2238 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2240 content_id = g_strdup_printf ("%d", priv->next_cid);
2241 tny_mime_part_set_content_id (mime_part, content_id);
2242 g_free (content_id);
2245 basename = g_path_get_basename (filename);
2246 tny_mime_part_set_filename (mime_part, basename);
2249 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
2251 if (pixbuf != NULL) {
2252 priv->images_size += stream_size;
2253 priv->images_count ++;
2254 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2255 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2256 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
2259 tny_list_prepend (priv->images, (GObject *) mime_part);
2260 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2262 g_object_unref (mime_part);
2263 gnome_vfs_file_info_unref (info);
2272 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2274 GtkWidget *dialog = NULL;
2276 GSList *uris = NULL;
2278 GnomeVFSFileSize total_size, allowed_size;
2279 ModestMsgEditWindowPrivate *priv;
2283 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2285 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2287 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2290 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2291 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2292 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2293 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), GTK_WINDOW (dialog), GTK_WINDOW (window));
2295 response = gtk_dialog_run (GTK_DIALOG (dialog));
2297 case GTK_RESPONSE_OK:
2298 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2303 gtk_widget_destroy (dialog);
2305 /* allowed size is the maximum size - what's already there */
2306 modest_attachments_view_get_sizes (
2307 MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2308 &att_num, &att_size);
2309 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2312 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2314 const gchar *uri = (const gchar *) uri_node->data;
2316 total_size += modest_msg_edit_window_attach_file_one
2317 (window, uri, allowed_size);
2319 if (total_size > allowed_size) {
2320 g_warning ("%s: total size: %u",
2321 __FUNCTION__, (unsigned int)total_size);
2325 allowed_size -= total_size;
2329 g_slist_foreach (uris, (GFunc) g_free, NULL);
2330 g_slist_free (uris);
2335 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2337 GnomeVFSFileSize allowed_size)
2340 GnomeVFSHandle *handle = NULL;
2341 ModestMsgEditWindowPrivate *priv;
2342 GnomeVFSResult result;
2343 GnomeVFSFileSize size = 0;
2344 g_return_val_if_fail (window, 0);
2345 g_return_val_if_fail (uri, 0);
2347 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2349 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2350 if (result == GNOME_VFS_OK) {
2351 TnyMimePart *mime_part;
2353 const gchar *mime_type = NULL;
2355 gchar *escaped_filename;
2358 GnomeVFSFileInfo *info;
2359 GnomeVFSURI *vfs_uri;
2361 gnome_vfs_close (handle);
2362 vfs_uri = gnome_vfs_uri_new (uri);
2365 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2366 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2367 g_free (escaped_filename);
2368 gnome_vfs_uri_unref (vfs_uri);
2370 info = gnome_vfs_file_info_new ();
2372 if (gnome_vfs_get_file_info (uri,
2374 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2376 mime_type = gnome_vfs_file_info_get_mime_type (info);
2377 mime_part = tny_platform_factory_new_mime_part
2378 (modest_runtime_get_platform_factory ());
2380 /* try to get the attachment's size; this may fail for weird
2381 * file systems, like obex, upnp... */
2382 if (allowed_size != 0 &&
2383 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2385 if (size > allowed_size) {
2386 modest_platform_information_banner (NULL, NULL,
2387 _FM("sfil_ib_opening_not_allowed"));
2391 g_warning ("%s: could not get attachment size", __FUNCTION__);
2393 stream = create_stream_for_uri (uri);
2395 if (stream == NULL) {
2397 modest_platform_information_banner (NULL, NULL, _FM("sfil_ib_opening_not_allowed"));
2399 g_object_unref (mime_part);
2400 gnome_vfs_file_info_unref (info);
2404 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2405 g_object_unref (stream);
2407 content_id = g_strdup_printf ("%d", priv->next_cid);
2408 tny_mime_part_set_content_id (mime_part, content_id);
2409 g_free (content_id);
2412 basename = g_path_get_basename (filename);
2413 tny_mime_part_set_filename (mime_part, basename);
2416 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2417 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2419 info->size == 0, info->size);
2420 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2421 gtk_widget_show_all (priv->attachments_caption);
2422 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2424 g_object_unref (mime_part);
2425 gnome_vfs_file_info_unref (info);
2432 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2435 ModestMsgEditWindowPrivate *priv;
2438 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2439 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2441 if (att_list == NULL) {
2442 att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2444 g_object_ref (att_list);
2447 if (tny_list_get_length (att_list) == 0) {
2448 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2450 gboolean dialog_response;
2451 gchar *message = NULL;
2452 gchar *filename = NULL;
2454 if (tny_list_get_length (att_list) == 1) {
2456 iter = tny_list_create_iterator (att_list);
2457 part = (TnyMimePart *) tny_iterator_get_current (iter);
2458 g_object_unref (iter);
2459 if (TNY_IS_MSG (part)) {
2460 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2462 filename = tny_header_dup_subject (header);
2463 g_object_unref (header);
2465 if (filename == NULL) {
2466 filename = g_strdup (_("mail_va_no_subject"));
2469 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2471 g_object_unref (part);
2473 filename = g_strdup ("");
2475 message = g_strdup_printf (ngettext("emev_nc_delete_attachment", "emev_nc_delete_attachments",
2476 tny_list_get_length (att_list)), filename);
2479 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window), message);
2482 if (dialog_response != GTK_RESPONSE_OK) {
2483 g_object_unref (att_list);
2486 hildon_banner_show_information (NULL, NULL, _("mcen_ib_removing_attachment"));
2488 for (iter = tny_list_create_iterator (att_list);
2489 !tny_iterator_is_done (iter);
2490 tny_iterator_next (iter)) {
2491 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2492 const gchar *att_id;
2493 tny_list_remove (priv->attachments, (GObject *) mime_part);
2495 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2497 if (tny_list_get_length (priv->attachments) == 0)
2498 gtk_widget_hide (priv->attachments_caption);
2499 att_id = tny_mime_part_get_content_id (mime_part);
2501 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2503 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2504 g_object_unref (mime_part);
2506 g_object_unref (iter);
2509 g_object_unref (att_list);
2511 /* if the last attachment has been removed, focus the Subject: field */
2512 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2513 gtk_widget_grab_focus (priv->subject_field);
2517 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2520 ModestMsgEditWindowPrivate *priv;
2521 GdkColor *new_color;
2522 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2524 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2525 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2528 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2530 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2532 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2534 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2539 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
2542 ModestMsgEditWindowPrivate *priv;
2543 gint new_size_index;
2544 ModestMsgEditWindow *window;
2547 window = MODEST_MSG_EDIT_WINDOW (userdata);
2548 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2549 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2551 if (gtk_check_menu_item_get_active (menu_item)) {
2553 WPTextBufferFormat format;
2555 memset (&format, 0, sizeof (format));
2556 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2558 label = gtk_bin_get_child (GTK_BIN (menu_item));
2560 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
2561 format.cs.font_size = TRUE;
2562 format.cs.text_position = TRUE;
2563 format.cs.font = TRUE;
2564 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
2565 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2567 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2568 GINT_TO_POINTER (wp_get_font_size_index (new_size_index, 12))))
2569 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2571 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2572 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
2573 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2579 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
2582 ModestMsgEditWindowPrivate *priv;
2583 gint new_font_index;
2584 ModestMsgEditWindow *window;
2587 window = MODEST_MSG_EDIT_WINDOW (userdata);
2588 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2589 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2591 if (gtk_check_menu_item_get_active (menu_item)) {
2594 label = gtk_bin_get_child (GTK_BIN (menu_item));
2596 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
2598 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2599 GINT_TO_POINTER(new_font_index)))
2600 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2602 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2603 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2604 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2610 modest_msg_edit_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
2612 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
2613 ModestWindowPrivate *parent_priv;
2614 ModestWindowMgr *mgr;
2615 gboolean is_fullscreen;
2616 GtkAction *fs_toggle_action;
2619 mgr = modest_runtime_get_window_mgr ();
2620 is_fullscreen = (modest_window_mgr_get_fullscreen_mode (mgr))?1:0;
2622 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
2624 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
2625 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
2626 if (is_fullscreen != active)
2627 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
2635 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2638 ModestMsgEditWindowPrivate *priv = NULL;
2639 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2641 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2642 if (!priv->update_caption_visibility)
2645 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2647 gtk_widget_show (priv->cc_caption);
2649 gtk_widget_hide (priv->cc_caption);
2651 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2655 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2658 ModestMsgEditWindowPrivate *priv = NULL;
2659 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2661 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2662 if (!priv->update_caption_visibility)
2665 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2667 gtk_widget_show (priv->bcc_caption);
2669 gtk_widget_hide (priv->bcc_caption);
2671 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2675 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2676 ModestRecptEditor *editor)
2678 ModestMsgEditWindowPrivate *priv;
2680 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2681 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2683 /* we check for low-mem; in that case, show a warning, and don't allow
2684 * for the addressbook
2686 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2689 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2691 if (editor == NULL) {
2692 GtkWidget *view_focus;
2693 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2695 /* This code should be kept in sync with ModestRecptEditor. The
2696 textview inside the recpt editor is the one that really gets the
2697 focus. As it's inside a scrolled window, and this one inside the
2698 hbox recpt editor inherits from, we'll need to go up in the
2699 hierarchy to know if the text view is part of the recpt editor
2700 or if it's a different text entry */
2702 if (gtk_widget_get_parent (view_focus)) {
2703 GtkWidget *first_parent;
2705 first_parent = gtk_widget_get_parent (view_focus);
2706 if (gtk_widget_get_parent (first_parent) &&
2707 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2708 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2713 editor = MODEST_RECPT_EDITOR (priv->to_field);
2717 modest_address_book_select_addresses (editor);
2722 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2724 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2726 modest_msg_edit_window_open_addressbook (window, NULL);
2730 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2731 gboolean show_toolbar)
2733 ModestWindowPrivate *parent_priv;
2734 const gchar *action_name;
2737 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2738 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2740 /* We can not just use the code of
2741 modest_msg_edit_window_setup_toolbar because it has a
2742 mixture of both initialization and creation code. */
2744 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2746 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2748 /* Update also the actions (to update the toggles in the
2749 menus), we have to do it manually because some other window
2750 of the same time could have changed it (remember that the
2751 toolbar fullscreen mode is shared by all the windows of the
2753 if (modest_window_mgr_get_fullscreen_mode (modest_runtime_get_window_mgr ()))
2754 action_name = "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarFullScreenMenu";
2756 action_name = "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarNormalScreenMenu";
2758 action = gtk_ui_manager_get_action (parent_priv->ui_manager, action_name);
2759 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
2765 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2766 TnyHeaderFlags priority_flags)
2768 ModestMsgEditWindowPrivate *priv;
2769 ModestWindowPrivate *parent_priv;
2771 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2773 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2774 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2776 if (priv->priority_flags != priority_flags) {
2777 GtkAction *priority_action = NULL;
2779 priv->priority_flags = priority_flags;
2781 switch (priority_flags) {
2782 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2783 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_high", GTK_ICON_SIZE_MENU);
2784 gtk_widget_show (priv->priority_icon);
2785 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2786 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2788 case TNY_HEADER_FLAG_LOW_PRIORITY:
2789 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_low", GTK_ICON_SIZE_MENU);
2790 gtk_widget_show (priv->priority_icon);
2791 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2792 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2795 gtk_widget_hide (priv->priority_icon);
2796 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2797 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2800 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2801 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2806 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2809 ModestMsgEditWindowPrivate *priv;
2810 ModestWindowPrivate *parent_priv;
2811 gint current_format;
2813 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2815 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2816 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2818 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2819 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2821 if (current_format != file_format) {
2822 switch (file_format) {
2823 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2824 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2825 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
2827 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2831 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2832 response = gtk_dialog_run (GTK_DIALOG (dialog));
2833 gtk_widget_destroy (dialog);
2834 if (response == GTK_RESPONSE_OK) {
2835 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2837 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu"));
2838 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
2843 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2844 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2845 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2850 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2853 ModestMsgEditWindowPrivate *priv;
2854 WPTextBufferFormat oldfmt, fmt;
2855 gint old_position = 0;
2859 GdkColor *color = NULL;
2860 gboolean bold, bold_set, italic, italic_set;
2861 gboolean underline, underline_set;
2862 gboolean strikethrough, strikethrough_set;
2863 gboolean position_set;
2864 gboolean font_size_set, font_set, color_set;
2867 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2868 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2870 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2871 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
2872 GTK_WINDOW(dialog), GTK_WINDOW (window));
2874 /* First we get the currently selected font information */
2875 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2877 switch (oldfmt.text_position) {
2878 case TEXT_POSITION_NORMAL:
2881 case TEXT_POSITION_SUPERSCRIPT:
2889 g_object_set (G_OBJECT (dialog),
2890 "bold", oldfmt.bold != FALSE,
2891 "bold-set", !oldfmt.cs.bold,
2892 "underline", oldfmt.underline != FALSE,
2893 "underline-set", !oldfmt.cs.underline,
2894 "italic", oldfmt.italic != FALSE,
2895 "italic-set", !oldfmt.cs.italic,
2896 "strikethrough", oldfmt.strikethrough != FALSE,
2897 "strikethrough-set", !oldfmt.cs.strikethrough,
2898 "color", &oldfmt.color,
2899 "color-set", !oldfmt.cs.color,
2900 "size", wp_font_size[oldfmt.font_size],
2901 "size-set", !oldfmt.cs.font_size,
2902 "position", old_position,
2903 "position-set", !oldfmt.cs.text_position,
2904 "family", wp_get_font_name (oldfmt.font),
2905 "family-set", !oldfmt.cs.font,
2908 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2909 GTK_WINDOW (dialog), GTK_WINDOW (window));
2910 gtk_widget_show_all (dialog);
2911 priv->font_dialog = dialog;
2912 response = gtk_dialog_run (GTK_DIALOG (dialog));
2913 priv->font_dialog = NULL;
2914 if (response == GTK_RESPONSE_OK) {
2916 g_object_get( dialog,
2918 "bold-set", &bold_set,
2919 "underline", &underline,
2920 "underline-set", &underline_set,
2922 "italic-set", &italic_set,
2923 "strikethrough", &strikethrough,
2924 "strikethrough-set", &strikethrough_set,
2926 "color-set", &color_set,
2928 "size-set", &font_size_set,
2929 "family", &font_name,
2930 "family-set", &font_set,
2931 "position", &position,
2932 "position-set", &position_set,
2937 if (response == GTK_RESPONSE_OK) {
2938 memset(&fmt, 0, sizeof(fmt));
2944 fmt.italic = italic;
2945 fmt.cs.italic = TRUE;
2947 if (underline_set) {
2948 fmt.underline = underline;
2949 fmt.cs.underline = TRUE;
2951 if (strikethrough_set) {
2952 fmt.strikethrough = strikethrough;
2953 fmt.cs.strikethrough = TRUE;
2958 ? TEXT_POSITION_NORMAL
2959 : ( ( position == 1 )
2960 ? TEXT_POSITION_SUPERSCRIPT
2961 : TEXT_POSITION_SUBSCRIPT );
2962 fmt.cs.text_position = TRUE;
2963 fmt.font_size = oldfmt.font_size;
2967 fmt.cs.color = TRUE;
2970 fmt.font = wp_get_font_index(font_name,
2975 if (font_size_set) {
2976 fmt.cs.font_size = TRUE;
2977 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
2979 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2980 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2982 gtk_widget_destroy (dialog);
2984 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2988 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2990 ModestMsgEditWindowPrivate *priv;
2992 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2993 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2995 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2997 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2998 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3002 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
3004 ModestMsgEditWindowPrivate *priv;
3006 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3007 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3009 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
3011 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3012 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3017 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
3019 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3021 priv->can_undo = can_undo;
3025 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
3027 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3029 priv->can_redo = can_redo;
3033 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3035 ModestMsgEditWindowPrivate *priv;
3036 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3037 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3039 return priv->can_undo;
3043 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3045 ModestMsgEditWindowPrivate *priv;
3046 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3047 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3049 return priv->can_redo;
3054 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3057 GtkTextIter match_start, match_end;
3059 if (image_id == NULL)
3062 gtk_text_buffer_get_start_iter (buffer, &iter);
3064 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3065 GSList *tags = gtk_text_iter_get_tags (&match_start);
3067 for (node = tags; node != NULL; node = g_slist_next (node)) {
3068 GtkTextTag *tag = (GtkTextTag *) node->data;
3069 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3070 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3071 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3073 offset = gtk_text_iter_get_offset (&match_start);
3074 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3075 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3079 gtk_text_iter_forward_char (&iter);
3084 message_is_empty (ModestMsgEditWindow *window)
3086 ModestMsgEditWindowPrivate *priv = NULL;
3088 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3089 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3091 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3092 * so we can ignore markup.
3094 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3097 count = gtk_text_buffer_get_char_count (buf);
3103 msg_body_focus (GtkWidget *focus,
3104 GdkEventFocus *event,
3108 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3109 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3110 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3115 recpt_field_changed (GtkTextBuffer *buffer,
3116 ModestMsgEditWindow *editor)
3118 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3119 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3123 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3125 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3126 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3130 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3133 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3134 GtkTextBuffer *buffer;
3136 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3137 gtk_text_buffer_set_modified (buffer, modified);
3138 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3139 gtk_text_buffer_set_modified (buffer, modified);
3140 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3141 gtk_text_buffer_set_modified (buffer, modified);
3142 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3146 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3148 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3149 const char *account_name;
3150 GtkTextBuffer *buffer;
3152 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3153 if (gtk_text_buffer_get_modified (buffer))
3155 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3156 if (gtk_text_buffer_get_modified (buffer))
3158 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3159 if (gtk_text_buffer_get_modified (buffer))
3161 if (gtk_text_buffer_get_modified (priv->text_buffer))
3163 account_name = modest_combo_box_get_active_id (MODEST_COMBO_BOX (priv->from_field));
3164 if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3175 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3177 ModestMsgEditWindowPrivate *priv = NULL;
3179 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3180 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3182 /* check if there's no recipient added */
3183 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3184 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3185 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3186 /* no recipient contents, then select contacts */
3187 modest_msg_edit_window_open_addressbook (window, NULL);
3191 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3192 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3195 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3196 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3199 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3200 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3204 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3205 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3206 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3213 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3214 ModestMsgEditWindow *window)
3216 modest_msg_edit_window_offer_attach_file (window);
3220 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3222 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3224 return priv->clipboard_text;
3228 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3230 ModestMsgEditWindow *window)
3232 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3233 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3235 if (!GTK_WIDGET_VISIBLE (window))
3238 g_object_ref (window);
3239 text = gtk_clipboard_wait_for_text (selection_clipboard);
3241 if (priv->clipboard_text != NULL) {
3242 g_free (priv->clipboard_text);
3244 priv->clipboard_text = text;
3246 if (GTK_WIDGET_VISIBLE (window)) {
3247 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3249 g_object_unref (window);
3252 static gboolean clipboard_owner_change_idle (gpointer userdata)
3254 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3255 ModestMsgEditWindowPrivate *priv;
3257 gdk_threads_enter ();
3258 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3259 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3261 priv->clipboard_owner_idle = 0;
3262 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3263 gdk_threads_leave ();
3269 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3271 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3272 if (priv->clipboard_owner_idle == 0) {
3273 priv->clipboard_owner_idle = g_idle_add (clipboard_owner_change_idle, window);
3278 subject_field_move_cursor (GtkEntry *entry,
3279 GtkMovementStep step,
3284 if (!GTK_WIDGET_VISIBLE (window))
3287 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3291 update_window_title (ModestMsgEditWindow *window)
3293 ModestMsgEditWindowPrivate *priv = NULL;
3294 const gchar *subject;
3296 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3297 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3298 if (subject == NULL || subject[0] == '\0')
3299 subject = _("mail_va_new_email");
3301 gtk_window_set_title (GTK_WINDOW (window), subject);
3306 subject_field_changed (GtkEditable *editable,
3307 ModestMsgEditWindow *window)
3309 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3310 update_window_title (window);
3311 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3312 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3313 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3317 subject_field_insert_text (GtkEditable *editable,
3319 gint new_text_length,
3321 ModestMsgEditWindow *window)
3323 GString *result = g_string_new ("");
3325 gint result_len = 0;
3326 const gchar *entry_text = NULL;
3329 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3330 old_length = g_utf8_strlen (entry_text, -1);
3332 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3333 gunichar c = g_utf8_get_char_validated (current, 8);
3334 /* Invalid unichar, stop */
3340 result = g_string_append_unichar (result, c);
3344 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3345 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3348 /* Prevent endless recursion */
3349 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3350 g_signal_emit_by_name (editable, "insert-text",
3351 (gpointer) result->str, (gpointer) result->len,
3352 (gpointer) position, (gpointer) window);
3353 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3357 if (result_len + old_length > 1000) {
3358 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3359 _CS("ckdg_ib_maximum_characters_reached"));
3362 g_string_free (result, TRUE);
3366 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3369 ModestMsgEditWindowPrivate *priv = NULL;
3371 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3372 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3374 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3377 gtk_widget_show_all (priv->find_toolbar);
3378 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3380 gtk_widget_hide_all (priv->find_toolbar);
3381 gtk_widget_grab_focus (priv->msg_body);
3387 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3389 GtkTextIter *match_start,
3390 GtkTextIter *match_end)
3392 GtkTextIter end_iter;
3393 gchar *str_casefold;
3396 gchar *range_casefold;
3399 gboolean result = FALSE;
3406 gtk_text_iter_forward_to_end (&end_iter);
3408 str_casefold = g_utf8_casefold (str, -1);
3409 str_chars_n = strlen (str);
3411 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3412 range_casefold = g_utf8_casefold (range_text, -1);
3413 range_chars_n = strlen (range_casefold);
3415 if (range_chars_n < str_chars_n) {
3416 g_free (str_casefold);
3417 g_free (range_text);
3418 g_free (range_casefold);
3422 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3423 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3424 if (!g_utf8_collate (range_subtext, str_casefold)) {
3425 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3427 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3428 match_start, match_end, NULL);
3429 g_free (found_text);
3431 g_free (range_subtext);
3435 g_free (str_casefold);
3436 g_free (range_text);
3437 g_free (range_casefold);
3444 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3445 ModestMsgEditWindow *window)
3447 gchar *current_search = NULL;
3448 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3450 GtkTextIter selection_start, selection_end;
3451 GtkTextIter match_start, match_end;
3452 gboolean continue_search = FALSE;
3454 if (message_is_empty (window)) {
3455 g_free (priv->last_search);
3456 priv->last_search = NULL;
3457 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3461 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3462 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3463 g_free (current_search);
3464 g_free (priv->last_search);
3465 priv->last_search = NULL;
3466 /* Information banner about empty search */
3467 hildon_banner_show_information (NULL, NULL,
3468 _CS ("ecdg_ib_find_rep_enter_text"));
3472 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3473 continue_search = TRUE;
3475 g_free (priv->last_search);
3476 priv->last_search = g_strdup (current_search);
3479 if (continue_search) {
3480 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3481 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3482 &match_start, &match_end);
3484 hildon_banner_show_information (NULL, NULL,
3485 _HL ("ckct_ib_find_search_complete"));
3487 GtkTextIter buffer_start;
3488 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3489 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3490 &match_start, &match_end);
3492 hildon_banner_show_information (NULL, NULL,
3493 _HL ("ckct_ib_find_no_matches"));
3496 /* Mark as selected the string found in search */
3498 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3499 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3500 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3502 g_free (priv->last_search);
3503 priv->last_search = NULL;
3505 g_free (current_search);
3509 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3510 ModestMsgEditWindow *window)
3512 GtkToggleAction *toggle;
3513 ModestWindowPrivate *parent_priv;
3514 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3516 toggle = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ToolsMenu/FindInMessageMenu"));
3517 gtk_toggle_action_set_active (toggle, FALSE);
3521 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3523 ModestMsgEditWindowPrivate *priv;
3525 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3530 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3533 ModestMsgEditWindowPrivate *priv;
3535 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3541 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3544 ModestMsgEditWindowPrivate *priv;
3545 TnyHeader *header = NULL;
3547 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3548 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3550 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3551 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3553 if (priv->draft_msg != NULL) {
3554 g_object_unref (priv->draft_msg);
3557 if (draft != NULL) {
3558 g_object_ref (draft);
3559 header = tny_msg_get_header (draft);
3560 if (priv->msg_uid) {
3561 g_free (priv->msg_uid);
3562 priv->msg_uid = NULL;
3564 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3565 if (GTK_WIDGET_REALIZED (window))
3566 modest_window_mgr_register_window (mgr, MODEST_WINDOW (window), NULL);
3569 priv->draft_msg = draft;
3573 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3574 GtkTextIter *start, GtkTextIter *end,
3577 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3578 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3581 if (tag == NULL) return;
3582 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3583 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3584 replace_with_images (window, priv->images);
3589 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3592 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3594 g_return_if_fail (TNY_IS_MIME_PART (part));
3595 tny_list_prepend (priv->attachments, (GObject *) part);
3596 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3597 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3598 gtk_widget_show_all (priv->attachments_caption);
3599 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3603 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3605 ModestMsgEditWindowPrivate *priv;
3607 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3608 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3610 return priv->msg_uid;
3614 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3615 ModestMsgEditWindowWidgetType widget_type)
3617 ModestMsgEditWindowPrivate *priv;
3619 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3620 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3622 switch (widget_type) {
3623 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3624 return priv->msg_body;
3626 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3627 return priv->to_field;
3629 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3630 return priv->cc_field;
3632 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3633 return priv->bcc_field;
3635 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3636 return priv->subject_field;
3638 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3639 return priv->attachments_view;
3647 remove_tags (WPTextBuffer *buffer)
3649 GtkTextIter start, end;
3651 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3652 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3654 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3658 on_account_removed (TnyAccountStore *account_store,
3659 TnyAccount *account,
3662 /* Do nothing if it's a store account, because we use the
3663 transport to send the messages */
3664 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3665 const gchar *parent_acc = NULL;
3666 const gchar *our_acc = NULL;
3668 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3669 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3670 /* Close this window if I'm showing a message of the removed account */
3671 if (strcmp (parent_acc, our_acc) == 0)
3672 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3677 on_zoom_minus_plus_not_implemented (ModestWindow *window)
3679 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3681 hildon_banner_show_information (NULL, NULL,
3682 _CS("ckct_ib_cannot_zoom_here"));
3688 set_zoom_do_nothing (ModestWindow *window,
3694 get_zoom_do_nothing (ModestWindow *window)