1 /* Copyright (c) 2006, Nokia Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of the Nokia Corporation nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include <glib/gi18n.h>
33 #include <glib/gstdio.h>
35 #include <tny-account-store.h>
36 #include <tny-fs-stream.h>
37 #include <tny-vfs-stream.h>
38 #include <tny-camel-mem-stream.h>
42 #include <modest-account-mgr.h>
43 #include <modest-account-mgr-helpers.h>
45 #include <widgets/modest-msg-edit-window.h>
46 #include <modest-selector-picker.h>
47 #include <widgets/modest-recpt-editor.h>
48 #include <widgets/modest-attachments-view.h>
50 #include <modest-runtime.h>
52 #include "modest-platform.h"
53 #include "modest-icon-names.h"
54 #include "modest-widget-memory.h"
55 #include "modest-window-priv.h"
56 #include "modest-mail-operation.h"
57 #include "modest-tny-platform-factory.h"
58 #include "modest-tny-msg.h"
59 #include "modest-tny-folder.h"
60 #include "modest-tny-account.h"
61 #include "modest-address-book.h"
62 #include "modest-text-utils.h"
63 #include <tny-simple-list.h>
64 #include <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"
81 #include <modest-ui-constants.h>
84 #define DEFAULT_FONT_SIZE 3
85 #define DEFAULT_FONT 2
86 #define DEFAULT_SIZE_BUTTON_FONT_FAMILY "Sans"
87 #define DEFAULT_MAIN_VBOX_SPACING 6
88 #define SUBJECT_MAX_LENGTH 1000
89 #define IMAGE_MAX_WIDTH 560
90 #define DEFAULT_FONT_SCALE 1.5
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;
295 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
296 MODEST_TYPE_MSG_EDIT_WINDOW, \
297 ModestMsgEditWindowPrivate))
299 static GtkWindowClass *parent_class = NULL;
301 /* uncomment the following if you have defined any signals */
302 /* static guint signals[LAST_SIGNAL] = {0}; */
305 modest_msg_edit_window_get_type (void)
307 static GType my_type = 0;
309 static const GTypeInfo my_info = {
310 sizeof(ModestMsgEditWindowClass),
311 NULL, /* base init */
312 NULL, /* base finalize */
313 (GClassInitFunc) modest_msg_edit_window_class_init,
314 NULL, /* class finalize */
315 NULL, /* class data */
316 sizeof(ModestMsgEditWindow),
318 (GInstanceInitFunc) modest_msg_edit_window_init,
321 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
322 "ModestMsgEditWindow",
330 save_state (ModestWindow *self)
332 modest_widget_memory_save (modest_runtime_get_conf(),
333 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
338 restore_settings (ModestMsgEditWindow *self)
340 ModestConf *conf = NULL;
342 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
344 conf = modest_runtime_get_conf ();
345 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
346 "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarNormalScreenMenu");
347 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
348 modest_conf_get_bool (conf, MODEST_CONF_EDIT_WINDOW_SHOW_TOOLBAR, NULL));
349 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
350 "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarFullScreenMenu");
351 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
352 modest_conf_get_bool (conf, MODEST_CONF_EDIT_WINDOW_SHOW_TOOLBAR_FULLSCREEN, NULL));
354 /* set initial state of cc and bcc */
355 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewCcFieldMenu");
356 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
357 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, NULL));
358 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewBccFieldMenu");
359 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
360 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, NULL));
362 /* Dim at start clipboard actions */
363 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
364 gtk_action_set_sensitive (action, FALSE);
365 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
366 gtk_action_set_sensitive (action, FALSE);
367 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
368 gtk_action_set_sensitive (action, FALSE);
370 modest_widget_memory_restore (conf,
371 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
376 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
378 GObjectClass *gobject_class;
379 ModestWindowClass *modest_window_class;
380 gobject_class = (GObjectClass*) klass;
381 modest_window_class = (ModestWindowClass*) klass;
383 parent_class = g_type_class_peek_parent (klass);
384 gobject_class->finalize = modest_msg_edit_window_finalize;
386 modest_window_class->set_zoom_func = set_zoom_do_nothing;
387 modest_window_class->get_zoom_func = get_zoom_do_nothing;
388 modest_window_class->zoom_plus_func = on_zoom_minus_plus_not_implemented;
389 modest_window_class->zoom_minus_func = on_zoom_minus_plus_not_implemented;
390 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
391 modest_window_class->save_state_func = save_state;
392 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
394 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
398 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
400 ModestMsgEditWindowPrivate *priv;
401 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
403 priv->msg_body = NULL;
405 priv->from_field = NULL;
406 priv->to_field = NULL;
407 priv->cc_field = NULL;
408 priv->bcc_field = NULL;
409 priv->subject_field = NULL;
410 priv->attachments = TNY_LIST (tny_simple_list_new ());
411 priv->images = TNY_LIST (tny_simple_list_new ());
412 priv->images_size = 0;
413 priv->images_count = 0;
416 priv->cc_caption = NULL;
417 priv->bcc_caption = NULL;
418 priv->update_caption_visibility = FALSE;
420 priv->priority_flags = 0;
422 priv->find_toolbar = NULL;
423 priv->last_search = NULL;
425 priv->draft_msg = NULL;
426 priv->outbox_msg = NULL;
427 priv->msg_uid = NULL;
429 priv->can_undo = FALSE;
430 priv->can_redo = FALSE;
431 priv->clipboard_change_handler_id = 0;
432 priv->default_clipboard_change_handler_id = 0;
433 priv->account_removed_handler_id = 0;
434 priv->clipboard_owner_idle = 0;
435 priv->clipboard_text = NULL;
438 priv->scroll_drag_timeout_id = 0;
439 priv->last_upper = 0.0;
441 priv->font_dialog = NULL;
443 modest_window_mgr_register_help_id (modest_runtime_get_window_mgr(),
444 GTK_WINDOW(obj),"applications_email_editor");
446 if (!is_wp_text_buffer_started) {
447 is_wp_text_buffer_started = TRUE;
448 wp_text_buffer_library_init ();
453 hildon_program_add_window (hildon_program_get_instance(),
459 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
461 static ModestPairList*
462 get_transports (void)
464 GSList *transports = NULL;
466 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
467 GSList *accounts = modest_account_mgr_account_names (account_mgr,
468 TRUE /* only enabled accounts. */);
470 GSList *cursor = accounts;
472 gchar *account_name = cursor->data;
473 gchar *from_string = NULL;
475 from_string = modest_account_mgr_get_from_string (account_mgr,
479 if (from_string && account_name) {
480 gchar *name = account_name;
481 ModestPair *pair = modest_pair_new ((gpointer) name,
482 (gpointer) from_string , TRUE);
483 transports = g_slist_prepend (transports, pair);
486 cursor = cursor->next;
488 g_slist_free (accounts); /* only free the accounts, not the elements,
489 * because they are used in the pairlist */
493 static void window_focus (GtkWindow *window,
497 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
501 scroll_drag_timeout (gpointer userdata)
503 ModestMsgEditWindow *win = (ModestMsgEditWindow *) userdata;
504 ModestMsgEditWindowPrivate *priv;
506 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(win);
508 correct_scroll_without_drag_check (win, TRUE);
510 priv->scroll_drag_timeout_id = 0;
516 correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused)
518 ModestMsgEditWindowPrivate *priv;
521 GdkRectangle rectangle;
527 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
529 if (only_if_focused && !gtk_widget_is_focus (priv->msg_body))
532 insert = gtk_text_buffer_get_insert (priv->text_buffer);
533 gtk_text_buffer_get_iter_at_mark (priv->text_buffer, &iter, insert);
535 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &iter, &rectangle);
536 vadj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll));
537 offset = priv->msg_body->allocation.y;
539 new_value = vadj->value;
541 if ((offset + rectangle.y + rectangle.height) >
542 ((gint) (vadj->value +vadj->page_size))) {
543 new_value = (offset + rectangle.y) - vadj->page_size * 0.25;
544 if (new_value > vadj->upper - vadj->page_size)
545 new_value = vadj->upper - vadj->page_size;
546 } else if ((offset + rectangle.y) < ((gint) vadj->value)) {
547 new_value = (offset + rectangle.y - vadj->page_size * 0.75);
548 if (((gint) (new_value + vadj->page_size)) < (offset + rectangle.y + rectangle.height))
549 new_value = offset + rectangle.y + rectangle.height - (gint) vadj->page_size;
552 if (new_value > vadj->value)
553 new_value = vadj->value;
556 if (vadj->value != new_value) {
557 g_signal_emit_by_name (GTK_TEXT_VIEW(priv->msg_body)->layout,
559 vadj->value = new_value;
560 gtk_adjustment_value_changed (vadj);
561 /* invalidate body */
562 window = gtk_widget_get_parent_window (priv->msg_body);
564 gdk_window_invalidate_rect (window, NULL, TRUE);
570 correct_scroll (ModestMsgEditWindow *w)
572 ModestMsgEditWindowPrivate *priv;
574 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
575 if (gtk_grab_get_current () == priv->msg_body) {
576 if (priv->scroll_drag_timeout_id == 0) {
577 priv->scroll_drag_timeout_id = g_timeout_add (500, (GSourceFunc) scroll_drag_timeout,
583 correct_scroll_without_drag_check (w, TRUE);
587 text_buffer_end_user_action (GtkTextBuffer *buffer,
588 ModestMsgEditWindow *userdata)
591 correct_scroll (userdata);
595 text_buffer_mark_set (GtkTextBuffer *buffer,
598 ModestMsgEditWindow *userdata)
600 gtk_text_buffer_begin_user_action (buffer);
601 gtk_text_buffer_end_user_action (buffer);
605 cut_clipboard_check (GtkTextView *text_view,
608 GtkTextBuffer *buffer;
610 buffer = gtk_text_view_get_buffer (text_view);
611 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
612 g_signal_stop_emission_by_name ((gpointer )text_view, "cut-clipboard");
617 copy_clipboard_check (GtkTextView *text_view,
620 GtkTextBuffer *buffer;
622 buffer = gtk_text_view_get_buffer (text_view);
623 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
624 g_signal_stop_emission_by_name ((gpointer )text_view, "copy-clipboard");
629 vadj_changed (GtkAdjustment *adj,
630 ModestMsgEditWindow *window)
632 ModestMsgEditWindowPrivate *priv;
634 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
636 if (priv->last_upper != adj->upper) {
637 priv->last_upper = adj->upper;
638 correct_scroll (window);
643 attachment_deleted (ModestAttachmentsView *attachments_view,
646 modest_msg_edit_window_remove_attachments (MODEST_MSG_EDIT_WINDOW (user_data),
651 connect_signals (ModestMsgEditWindow *obj)
653 ModestMsgEditWindowPrivate *priv;
655 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
657 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
658 G_CALLBACK (text_buffer_refresh_attributes), obj);
659 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
660 G_CALLBACK (text_buffer_can_undo), obj);
661 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
662 G_CALLBACK (text_buffer_can_redo), obj);
663 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
664 G_CALLBACK (body_changed), obj);
665 g_signal_connect (G_OBJECT (priv->text_buffer), "modified-changed",
666 G_CALLBACK (body_changed), obj);
667 g_signal_connect (G_OBJECT (obj), "window-state-event",
668 G_CALLBACK (modest_msg_edit_window_window_state_event),
670 g_signal_connect (G_OBJECT (priv->text_buffer), "end-user-action",
671 G_CALLBACK (text_buffer_end_user_action), obj);
672 g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
673 G_CALLBACK (text_buffer_mark_set), obj);
674 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
675 G_CALLBACK (text_buffer_apply_tag), obj);
676 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
677 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
678 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
679 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
680 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
681 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
683 g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
684 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
686 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
687 G_CALLBACK (msg_body_focus), obj);
688 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
689 G_CALLBACK (msg_body_focus), obj);
690 g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
691 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
692 "changed", G_CALLBACK (recpt_field_changed), obj);
693 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
694 "changed", G_CALLBACK (recpt_field_changed), obj);
695 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
696 "changed", G_CALLBACK (recpt_field_changed), obj);
697 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
698 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
699 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
701 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
702 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
704 g_signal_connect (G_OBJECT (gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll))),
706 G_CALLBACK (vadj_changed),
709 priv->clipboard_change_handler_id =
710 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
711 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
712 priv->default_clipboard_change_handler_id =
713 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
714 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
716 g_signal_connect (G_OBJECT (priv->msg_body), "cut-clipboard", G_CALLBACK (cut_clipboard_check), NULL);
717 g_signal_connect (G_OBJECT (priv->msg_body), "copy-clipboard", G_CALLBACK (copy_clipboard_check), NULL);
718 g_signal_connect (G_OBJECT (priv->attachments_view), "delete", G_CALLBACK (attachment_deleted), obj);
722 init_window (ModestMsgEditWindow *obj)
724 GtkWidget *to_caption, *subject_caption;
725 GtkWidget *main_vbox;
726 ModestMsgEditWindowPrivate *priv;
727 GtkActionGroup *action_group;
728 ModestWindowPrivate *parent_priv;
729 GdkPixbuf *window_icon = NULL;
730 GError *error = NULL;
732 GtkSizeGroup *size_group;
733 GtkWidget *subject_box;
734 GtkWidget *attachment_icon;
735 GtkWidget *window_box;
736 #if (GTK_MINOR_VERSION >= 10)
737 GdkAtom deserialize_type;
740 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
741 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
743 parent_priv->ui_manager = gtk_ui_manager_new();
744 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
745 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
747 /* Add common actions */
748 gtk_action_group_add_actions (action_group,
749 modest_msg_edit_action_entries,
750 G_N_ELEMENTS (modest_msg_edit_action_entries),
752 gtk_action_group_add_toggle_actions (action_group,
753 modest_msg_edit_toggle_action_entries,
754 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
756 gtk_action_group_add_radio_actions (action_group,
757 modest_msg_edit_alignment_radio_action_entries,
758 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
760 G_CALLBACK (modest_ui_actions_on_change_justify),
762 gtk_action_group_add_radio_actions (action_group,
763 modest_msg_edit_priority_action_entries,
764 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
766 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
768 gtk_action_group_add_radio_actions (action_group,
769 modest_msg_edit_file_format_action_entries,
770 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
771 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
772 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
774 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
775 g_object_unref (action_group);
777 /* Load the UI definition */
778 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
781 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
782 g_clear_error (&error);
785 /* Add accelerators */
786 gtk_window_add_accel_group (GTK_WINDOW (obj),
787 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
789 parent_priv->menubar = NULL;
791 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
793 /* Note: This ModestPairList* must exist for as long as the picker
794 * that uses it, because the ModestSelectorPicker uses the ID opaquely,
795 * so it can't know how to manage its memory. */
796 priv->from_field = modest_selector_picker_new (MODEST_EDITABLE_SIZE,
797 MODEST_EDITABLE_ARRANGEMENT,
799 hildon_button_set_alignment (HILDON_BUTTON (priv->from_field), 0.0, 0.5, 1.0, 0.0);
800 hildon_button_set_title_alignment (HILDON_BUTTON (priv->from_field), 0.0, 0.5);
801 hildon_button_set_value_alignment (HILDON_BUTTON (priv->from_field), 0.0, 0.5);
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 = hildon_entry_new (MODEST_EDITABLE_SIZE);
810 gtk_entry_set_max_length (GTK_ENTRY (priv->subject_field) ,SUBJECT_MAX_LENGTH);
811 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
812 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
813 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
814 gtk_box_pack_start (GTK_BOX (subject_box), priv->subject_field, TRUE, TRUE, 0);
815 priv->add_attachment_button = gtk_button_new ();
816 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
817 gtk_button_set_relief (GTK_BUTTON (priv->add_attachment_button), GTK_RELIEF_NONE);
818 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
819 gtk_button_set_alignment (GTK_BUTTON (priv->add_attachment_button), 1.0, 0.5);
820 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, GTK_ICON_SIZE_BUTTON);
821 gtk_container_add (GTK_CONTAINER (priv->add_attachment_button), attachment_icon);
822 gtk_box_pack_start (GTK_BOX (subject_box), priv->add_attachment_button, FALSE, FALSE, 0);
823 priv->attachments_view = modest_attachments_view_new (NULL);
825 priv->header_box = gtk_vbox_new (FALSE, 0);
827 hildon_button_add_title_size_group (HILDON_BUTTON (priv->from_field), size_group);
828 to_caption = modest_maemo_utils_create_captioned (size_group, _("mail_va_to"), priv->to_field);
829 priv->cc_caption = modest_maemo_utils_create_captioned (size_group, _("mail_va_cc"), priv->cc_field);
830 priv->bcc_caption = modest_maemo_utils_create_captioned (size_group, _("mail_va_hotfix1"), priv->bcc_field);
831 subject_caption = modest_maemo_utils_create_captioned (size_group, _("mail_va_subject"), subject_box);
832 priv->attachments_caption = modest_maemo_utils_create_captioned (size_group, _("mail_va_attachment"), priv->attachments_view);
833 g_object_unref (size_group);
835 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
836 hildon_button_add_value_size_group (HILDON_BUTTON (priv->from_field), size_group);
837 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), size_group);
838 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), size_group);
839 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), size_group);
840 gtk_size_group_add_widget (size_group, priv->subject_field);
841 gtk_size_group_add_widget (size_group, priv->attachments_view);
842 g_object_unref (size_group);
844 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->from_field, FALSE, FALSE, 0);
845 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
846 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
847 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
848 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
849 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
850 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
853 priv->msg_body = wp_text_view_new ();
854 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
855 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
856 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
857 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
858 #if (GTK_MINOR_VERSION >= 10)
859 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
860 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
862 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
863 deserialize_type, TRUE);
865 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
867 priv->find_toolbar = hildon_find_toolbar_new (NULL);
868 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
870 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
872 priv->scroll = gtk_scrolled_window_new (NULL, NULL);
873 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
874 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (priv->scroll), GTK_SHADOW_NONE);
875 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->scroll), TRUE);
877 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
879 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
880 priv->frame = gtk_frame_new (NULL);
881 gtk_box_pack_start (GTK_BOX(main_vbox), priv->frame, TRUE, TRUE, 0);
883 gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (priv->scroll), main_vbox);
884 gtk_container_set_focus_vadjustment (GTK_CONTAINER (main_vbox), gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll)));
885 gtk_widget_show_all (GTK_WIDGET(priv->scroll));
887 window_box = gtk_vbox_new (FALSE, 0);
888 gtk_container_add (GTK_CONTAINER(obj), window_box);
890 gtk_box_pack_start (GTK_BOX (window_box), priv->scroll, TRUE, TRUE, 0);
892 gtk_container_add (GTK_CONTAINER (priv->frame), priv->msg_body);
894 /* Set window icon */
895 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
897 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
898 g_object_unref (window_icon);
903 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
905 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
907 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
908 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
909 priv->clipboard_change_handler_id))
910 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
911 priv->clipboard_change_handler_id);
912 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
913 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
914 priv->default_clipboard_change_handler_id))
915 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
916 priv->default_clipboard_change_handler_id);
918 if (priv->account_removed_handler_id &&
919 g_signal_handler_is_connected (modest_runtime_get_account_store (),
920 priv->account_removed_handler_id))
921 g_signal_handler_disconnect(modest_runtime_get_account_store (),
922 priv->account_removed_handler_id);
926 modest_msg_edit_window_finalize (GObject *obj)
928 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
930 /* Sanity check: shouldn't be needed, the window mgr should
931 call this function before */
932 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
934 if (priv->font_dialog != NULL) {
935 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
938 if (priv->clipboard_text != NULL) {
939 g_free (priv->clipboard_text);
940 priv->clipboard_text = NULL;
943 if (priv->draft_msg != NULL) {
944 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
945 if (TNY_IS_HEADER (header)) {
946 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
947 modest_window_mgr_unregister_header (mgr, header);
949 g_object_unref (priv->draft_msg);
950 priv->draft_msg = NULL;
952 if (priv->outbox_msg != NULL) {
953 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
954 if (TNY_IS_HEADER (header)) {
955 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
956 modest_window_mgr_unregister_header (mgr, header);
958 g_object_unref (priv->outbox_msg);
959 priv->outbox_msg = NULL;
961 if (priv->scroll_drag_timeout_id > 0) {
962 g_source_remove (priv->scroll_drag_timeout_id);
963 priv->scroll_drag_timeout_id = 0;
965 if (priv->clipboard_owner_idle > 0) {
966 g_source_remove (priv->clipboard_owner_idle);
967 priv->clipboard_owner_idle = 0;
969 if (priv->original_account_name)
970 g_free (priv->original_account_name);
971 g_free (priv->msg_uid);
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 picker 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)) {
1010 g_error_free (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),
1199 update_window_title (self);
1201 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1202 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1204 if ((body == NULL)||(body[0] == '\0')) {
1206 body = modest_text_utils_convert_to_html ("");
1209 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1210 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1213 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1216 /* Add attachments to the view */
1217 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1218 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1219 if (tny_list_get_length (priv->attachments) == 0) {
1220 gtk_widget_hide (priv->attachments_caption);
1222 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1223 gtk_widget_show_all (priv->attachments_caption);
1225 get_related_images (self, msg);
1226 update_next_cid (self, priv->attachments);
1227 update_next_cid (self, priv->images);
1228 replace_with_images (self, priv->images);
1230 if (preserve_is_rich && !is_html) {
1231 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1232 /* Get the default format required from configuration */
1233 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1234 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1237 /* Set the default focus depending on having already a To: field or not */
1238 if ((!to)||(*to == '\0')) {
1239 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1241 gtk_widget_grab_focus (priv->msg_body);
1244 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1246 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1247 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1249 modest_msg_edit_window_set_modified (self, FALSE);
1251 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1252 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1253 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1254 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1256 if (priv->msg_uid) {
1257 g_free (priv->msg_uid);
1258 priv->msg_uid = NULL;
1261 /* we should set a reference to the incoming message if it is a draft */
1262 msg_folder = tny_msg_get_folder (msg);
1264 if (modest_tny_folder_is_local_folder (msg_folder)) {
1265 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1266 if (type == TNY_FOLDER_TYPE_INVALID)
1267 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1269 if (type == TNY_FOLDER_TYPE_DRAFTS)
1270 priv->draft_msg = g_object_ref(msg);
1271 if (type == TNY_FOLDER_TYPE_OUTBOX)
1272 priv->outbox_msg = g_object_ref(msg);
1273 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1275 g_object_unref (msg_folder);
1285 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
1288 GList *item_children, *node;
1289 GtkWidget *bin_child;
1291 bin_child = gtk_bin_get_child (GTK_BIN(item));
1293 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
1295 for (node = item_children; node != NULL; node = g_list_next (node)) {
1296 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
1297 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
1300 g_list_free (item_children);
1304 menu_tool_button_dont_expand (GtkMenuToolButton *item)
1307 GList *item_children, *node;
1309 box = gtk_bin_get_child (GTK_BIN (item));
1310 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
1311 item_children = gtk_container_get_children (GTK_CONTAINER (box));
1313 for (node = item_children; node != NULL; node = g_list_next (node)) {
1314 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
1315 if (GTK_IS_TOGGLE_BUTTON (node->data))
1316 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
1317 else if (GTK_IS_BUTTON (node->data))
1318 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
1320 g_list_free (item_children);
1325 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1327 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1328 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1329 GtkWidget *placeholder;
1330 GtkWidget *tool_item;
1335 GtkWidget *sizes_menu;
1336 GtkWidget *fonts_menu;
1337 GSList *radio_group = NULL;
1338 GSList *node = NULL;
1342 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1343 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1345 /* Font color placeholder */
1346 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1347 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1350 tool_item = GTK_WIDGET (gtk_tool_item_new ());
1351 priv->font_color_button = hildon_color_button_new ();
1352 GTK_WIDGET_UNSET_FLAGS (tool_item, GTK_CAN_FOCUS);
1353 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1354 gtk_container_add (GTK_CONTAINER (tool_item), priv->font_color_button);
1355 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1356 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1357 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1358 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1360 G_CALLBACK (modest_msg_edit_window_color_button_change),
1363 /* Font size and face placeholder */
1364 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1365 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1367 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1368 priv->size_tool_button_label = gtk_label_new (NULL);
1369 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1370 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1371 size_text,"</span>", NULL);
1372 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1374 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
1375 sizes_menu = gtk_menu_new ();
1376 priv->size_items_group = NULL;
1378 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1379 GtkWidget *size_menu_item;
1381 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1382 size_menu_item = gtk_radio_menu_item_new_with_label (radio_group, size_text);
1383 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (size_menu_item));
1384 gtk_menu_shell_append (GTK_MENU_SHELL (sizes_menu), size_menu_item);
1385 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (size_menu_item), (wp_font_size[size_index] == 12));
1386 gtk_widget_show (size_menu_item);
1388 priv->size_items_group = g_slist_prepend (priv->size_items_group, size_menu_item);
1392 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1393 GtkWidget *item = (GtkWidget *) node->data;
1394 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_size_change),
1398 priv->size_items_group = g_slist_reverse (priv->size_items_group);
1399 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), sizes_menu);
1400 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1401 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1402 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1403 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1404 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1405 priv->font_size_toolitem = tool_item;
1408 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1409 priv->font_tool_button_label = gtk_label_new (NULL);
1410 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1411 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1413 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
1414 fonts_menu = gtk_menu_new ();
1415 priv->font_items_group = NULL;
1417 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1418 GtkWidget *font_menu_item;
1419 GtkWidget *child_label;
1421 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
1422 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
1423 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
1424 wp_get_font_name (font_index), "</span>", NULL);
1425 gtk_label_set_markup (GTK_LABEL (child_label), markup);
1428 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
1429 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
1430 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
1431 gtk_widget_show (font_menu_item);
1433 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
1436 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1437 GtkWidget *item = (GtkWidget *) node->data;
1438 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
1441 priv->font_items_group = g_slist_reverse (priv->font_items_group);
1442 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
1443 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1444 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1445 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1446 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1447 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1448 priv->font_face_toolitem = tool_item;
1450 /* Set expand and homogeneous for remaining items */
1451 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
1452 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1453 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1454 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1455 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1456 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1457 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1458 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1459 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1461 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1462 will not show the tool items added to the placeholders) */
1463 gtk_widget_show_all (parent_priv->toolbar);
1465 /* Set the no show all *after* showing all items. We do not
1466 want the toolbar to be shown with a show all because it
1467 could go agains the gconf setting regarding showing or not
1468 the toolbar of the editor window */
1469 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1475 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, gboolean preserve_is_rich)
1478 ModestWindowPrivate *parent_priv;
1479 ModestMsgEditWindowPrivate *priv;
1480 ModestDimmingRulesGroup *menu_rules_group = NULL;
1481 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1482 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1483 ModestWindowMgr *mgr = NULL;
1485 g_return_val_if_fail (msg, NULL);
1486 g_return_val_if_fail (account_name, NULL);
1488 mgr = modest_runtime_get_window_mgr ();
1490 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1492 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1493 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1495 /* Menubar. Update the state of some toggles */
1496 parent_priv->menubar = modest_maemo_utils_get_manager_menubar_as_menu (parent_priv->ui_manager, "/MenuBar");
1497 hildon_window_set_menu (HILDON_WINDOW (obj), GTK_MENU (parent_priv->menubar));
1498 priv->from_field_protos = get_transports ();
1499 modest_selector_picker_set_pair_list (MODEST_SELECTOR_PICKER (priv->from_field), priv->from_field_protos);
1500 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1501 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1503 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1504 hildon_touch_selector_get_current_text
1505 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
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_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (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 if (priv->draft_msg) {
1634 data->draft_msg = g_object_ref (priv->draft_msg);
1635 } else if (priv->outbox_msg) {
1636 data->draft_msg = g_object_ref (priv->outbox_msg);
1638 data->draft_msg = NULL;
1641 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1643 gtk_text_buffer_get_bounds (buf, &b, &e);
1644 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1646 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1647 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1649 data->html_body = NULL;
1651 /* deep-copy the data */
1652 att_iter = tny_list_create_iterator (priv->attachments);
1653 data->attachments = NULL;
1654 while (!tny_iterator_is_done (att_iter)) {
1655 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1656 if (!(TNY_IS_MIME_PART(part))) {
1657 g_warning ("strange data in attachment list");
1658 g_object_unref (part);
1659 tny_iterator_next (att_iter);
1662 data->attachments = g_list_append (data->attachments,
1664 tny_iterator_next (att_iter);
1666 g_object_unref (att_iter);
1668 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1669 att_iter = tny_list_create_iterator (priv->images);
1670 data->images = NULL;
1671 while (!tny_iterator_is_done (att_iter)) {
1672 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1674 if (!(TNY_IS_MIME_PART(part))) {
1675 g_warning ("strange data in attachment list");
1676 g_object_unref (part);
1677 tny_iterator_next (att_iter);
1680 cid = tny_mime_part_get_content_id (part);
1682 gchar *image_tag_id;
1683 GtkTextTag *image_tag;
1685 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1686 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1687 g_free (image_tag_id);
1689 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1691 ((gtk_text_iter_has_tag (&iter, image_tag))||
1692 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1693 data->images = g_list_append (data->images,
1694 g_object_ref (part));
1696 g_object_unref (part);
1697 tny_iterator_next (att_iter);
1699 g_object_unref (att_iter);
1701 data->priority_flags = priv->priority_flags;
1708 unref_gobject (GObject *obj, gpointer data)
1710 if (!G_IS_OBJECT(obj))
1712 g_object_unref (obj);
1716 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1719 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1727 g_free (data->from);
1728 g_free (data->subject);
1729 g_free (data->plain_body);
1730 g_free (data->html_body);
1731 g_free (data->account_name);
1733 if (data->draft_msg != NULL) {
1734 g_object_unref (data->draft_msg);
1735 data->draft_msg = NULL;
1738 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1739 g_list_free (data->attachments);
1740 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1741 g_list_free (data->images);
1743 g_slice_free (MsgData, data);
1747 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1749 guint64 *parts_size)
1751 ModestMsgEditWindowPrivate *priv;
1753 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1755 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1757 /* TODO: add images */
1758 *parts_size += priv->images_size;
1759 *parts_count += priv->images_count;
1764 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1767 ModestMsgEditWindowPrivate *priv = NULL;
1768 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1770 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1772 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1774 return MODEST_MSG_EDIT_FORMAT_HTML;
1776 return MODEST_MSG_EDIT_FORMAT_TEXT;
1780 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1781 ModestMsgEditFormat format)
1783 ModestMsgEditWindowPrivate *priv;
1785 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1786 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1789 case MODEST_MSG_EDIT_FORMAT_HTML:
1790 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1792 case MODEST_MSG_EDIT_FORMAT_TEXT:
1793 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1796 g_return_if_reached ();
1800 ModestMsgEditFormatState *
1801 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1803 ModestMsgEditFormatState *format_state = NULL;
1804 ModestMsgEditWindowPrivate *priv;
1805 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1807 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1808 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1810 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1812 format_state = g_new0 (ModestMsgEditFormatState, 1);
1813 format_state->bold = buffer_format->bold&0x1;
1814 format_state->italics = buffer_format->italic&0x1;
1815 format_state->bullet = buffer_format->bullet&0x1;
1816 format_state->color = buffer_format->color;
1817 format_state->font_size = buffer_format->font_size;
1818 format_state->font_family = wp_get_font_name (buffer_format->font);
1819 format_state->justification = buffer_format->justification;
1820 g_free (buffer_format);
1822 return format_state;
1827 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1828 const ModestMsgEditFormatState *format_state)
1830 ModestMsgEditWindowPrivate *priv;
1831 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1832 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1833 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1834 g_return_if_fail (format_state != NULL);
1836 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1837 gtk_widget_grab_focus (priv->msg_body);
1838 buffer_format->bold = (format_state->bold != FALSE);
1839 buffer_format->italic = (format_state->italics != FALSE);
1840 buffer_format->color = format_state->color;
1841 buffer_format->font_size = format_state->font_size;
1842 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1843 buffer_format->justification = format_state->justification;
1844 buffer_format->bullet = format_state->bullet;
1846 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1848 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1849 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1850 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1851 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1852 buffer_format->cs.font = (buffer_format->font != current_format->font);
1853 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1854 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1856 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1857 if (buffer_format->cs.bold) {
1858 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
1859 GINT_TO_POINTER (buffer_format->bold&0x1));
1861 if (buffer_format->cs.italic) {
1862 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
1863 GINT_TO_POINTER (buffer_format->italic&0x1));
1865 if (buffer_format->cs.color) {
1866 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1867 GINT_TO_POINTER (&(buffer_format->color)));
1869 if (buffer_format->cs.font_size) {
1870 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1871 GINT_TO_POINTER (buffer_format->font_size));
1873 if (buffer_format->cs.justification) {
1874 switch (buffer_format->justification) {
1875 case GTK_JUSTIFY_LEFT:
1876 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
1877 GINT_TO_POINTER(TRUE));
1879 case GTK_JUSTIFY_CENTER:
1880 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
1881 GINT_TO_POINTER(TRUE));
1883 case GTK_JUSTIFY_RIGHT:
1884 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
1885 GINT_TO_POINTER(TRUE));
1892 if (buffer_format->cs.font) {
1893 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1894 GINT_TO_POINTER (buffer_format->font));
1896 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1897 if (buffer_format->cs.bullet) {
1898 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
1899 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
1901 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1903 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
1905 g_free (buffer_format);
1906 g_free (current_format);
1908 /* Check dimming rules */
1909 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1910 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1914 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1916 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1918 ModestWindowPrivate *parent_priv;
1919 ModestMsgEditWindowPrivate *priv;
1920 GtkWidget *new_size_menuitem;
1921 GtkWidget *new_font_menuitem;
1923 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1924 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1926 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1927 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu");
1928 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1929 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1931 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatPlainTextMenu");
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);
1936 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1938 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1939 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1941 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1942 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1944 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
1945 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
1948 switch (buffer_format->justification)
1950 case GTK_JUSTIFY_LEFT:
1951 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
1953 case GTK_JUSTIFY_CENTER:
1954 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
1956 case GTK_JUSTIFY_RIGHT:
1957 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
1964 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
1966 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1967 G_CALLBACK (modest_msg_edit_window_color_button_change),
1969 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1970 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1971 G_CALLBACK (modest_msg_edit_window_color_button_change),
1974 new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group,
1975 buffer_format->font_size))->data);
1976 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1980 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1981 markup = g_strconcat ("<span font_family='Sans'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1982 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1984 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1985 G_CALLBACK (modest_msg_edit_window_size_change),
1987 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
1988 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
1989 G_CALLBACK (modest_msg_edit_window_size_change),
1993 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
1994 buffer_format->font))->data);
1995 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
1999 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
2000 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2001 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2003 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
2004 G_CALLBACK (modest_msg_edit_window_font_change),
2006 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
2007 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
2008 G_CALLBACK (modest_msg_edit_window_font_change),
2012 g_free (buffer_format);
2016 #ifdef MODEST_HILDON_VERSION_0
2018 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2021 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2022 ModestMsgEditWindowPrivate *priv;
2023 GtkWidget *dialog = NULL;
2025 GdkColor *new_color = NULL;
2027 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2028 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2030 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2031 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
2032 g_free (buffer_format);
2034 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2035 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2036 if (new_color != NULL) {
2037 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2038 (gpointer) new_color);
2041 gtk_widget_destroy (dialog);
2046 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2049 ModestMsgEditWindowPrivate *priv;
2050 GtkWidget *dialog = NULL;
2052 GdkColor *old_color = NULL;
2053 const GdkColor *new_color = NULL;
2055 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2056 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2058 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2059 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2061 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2062 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2063 if (new_color != NULL)
2064 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2066 gtk_widget_destroy (dialog);
2072 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2075 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2076 ModestMsgEditWindowPrivate *priv;
2077 GtkWidget *dialog = NULL;
2079 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2080 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2082 dialog = hildon_color_chooser_new ();
2083 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2084 g_free (buffer_format);
2086 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2088 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2089 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2092 gtk_widget_destroy (dialog);
2097 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2100 ModestMsgEditWindowPrivate *priv;
2101 GtkWidget *dialog = NULL;
2102 GdkColor *old_color = NULL;
2104 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2105 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2107 dialog = hildon_color_chooser_new ();
2108 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2110 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2112 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2113 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2115 gtk_widget_destroy (dialog);
2118 #endif /*!MODEST_HILDON_VERSION_0*/
2123 create_stream_for_uri (const gchar* uri)
2128 TnyStream *result = NULL;
2130 GnomeVFSHandle *handle = NULL;
2131 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2132 if (test == GNOME_VFS_OK) {
2133 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2134 /* Streams over OBEX (Bluetooth) are not seekable but
2135 * we expect them to be (we might need to read them
2136 * several times). So if this is a Bluetooth URI just
2137 * read the whole file into memory (this is not a fast
2138 * protocol so we can assume that these files are not
2139 * going to be very big) */
2140 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2141 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2142 TnyStream *memstream = tny_camel_mem_stream_new ();
2143 tny_stream_write_to_stream (vfssstream, memstream);
2144 g_object_unref (vfssstream);
2147 result = vfssstream;
2155 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2158 ModestMsgEditWindowPrivate *priv;
2159 GtkWidget *dialog = NULL;
2161 GSList *uris = NULL;
2162 GSList *uri_node = NULL;
2164 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2166 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2167 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2168 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2170 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2172 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2173 GTK_WINDOW (dialog), GTK_WINDOW (window));
2175 response = gtk_dialog_run (GTK_DIALOG (dialog));
2177 case GTK_RESPONSE_OK:
2178 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2183 gtk_widget_destroy (dialog);
2185 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2187 GnomeVFSHandle *handle = NULL;
2188 GnomeVFSResult result;
2189 GtkTextIter position;
2190 GtkTextMark *insert_mark;
2192 uri = (const gchar *) uri_node->data;
2193 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2194 if (result == GNOME_VFS_OK) {
2196 GnomeVFSFileInfo *info;
2197 gchar *filename, *basename, *escaped_filename;
2198 TnyMimePart *mime_part;
2200 const gchar *mime_type = NULL;
2201 GnomeVFSURI *vfs_uri;
2202 guint64 stream_size;
2204 gnome_vfs_close (handle);
2205 vfs_uri = gnome_vfs_uri_new (uri);
2207 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2208 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2209 g_free (escaped_filename);
2210 gnome_vfs_uri_unref (vfs_uri);
2211 info = gnome_vfs_file_info_new ();
2213 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2214 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2216 mime_type = gnome_vfs_file_info_get_mime_type (info);
2218 mime_part = tny_platform_factory_new_mime_part
2219 (modest_runtime_get_platform_factory ());
2221 TnyStream *stream = create_stream_for_uri (uri);
2223 if (stream == NULL) {
2225 modest_platform_information_banner (NULL, NULL, dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2227 g_object_unref (mime_part);
2228 gnome_vfs_file_info_unref (info);
2232 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2234 content_id = g_strdup_printf ("%d", priv->next_cid);
2235 tny_mime_part_set_content_id (mime_part, content_id);
2236 g_free (content_id);
2239 basename = g_path_get_basename (filename);
2240 tny_mime_part_set_filename (mime_part, basename);
2243 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
2245 if (pixbuf != NULL) {
2246 priv->images_size += stream_size;
2247 priv->images_count ++;
2248 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2249 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2250 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
2251 g_object_unref (pixbuf);
2254 tny_list_prepend (priv->images, (GObject *) mime_part);
2255 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2257 g_object_unref (mime_part);
2258 gnome_vfs_file_info_unref (info);
2267 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2269 GtkWidget *dialog = NULL;
2271 GSList *uris = NULL;
2273 GnomeVFSFileSize total_size, allowed_size;
2274 ModestMsgEditWindowPrivate *priv;
2278 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2280 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2282 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2285 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2286 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2287 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2288 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), GTK_WINDOW (dialog), GTK_WINDOW (window));
2290 response = gtk_dialog_run (GTK_DIALOG (dialog));
2292 case GTK_RESPONSE_OK:
2293 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2298 gtk_widget_destroy (dialog);
2300 /* allowed size is the maximum size - what's already there */
2301 modest_attachments_view_get_sizes (
2302 MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2303 &att_num, &att_size);
2304 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2307 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2309 const gchar *uri = (const gchar *) uri_node->data;
2311 total_size += modest_msg_edit_window_attach_file_one
2312 (window, uri, allowed_size);
2314 if (total_size > allowed_size) {
2315 g_warning ("%s: total size: %u",
2316 __FUNCTION__, (unsigned int)total_size);
2320 allowed_size -= total_size;
2324 g_slist_foreach (uris, (GFunc) g_free, NULL);
2325 g_slist_free (uris);
2330 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2332 GnomeVFSFileSize allowed_size)
2335 GnomeVFSHandle *handle = NULL;
2336 ModestMsgEditWindowPrivate *priv;
2337 GnomeVFSResult result;
2338 GnomeVFSFileSize size = 0;
2339 g_return_val_if_fail (window, 0);
2340 g_return_val_if_fail (uri, 0);
2342 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2344 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2345 if (result == GNOME_VFS_OK) {
2346 TnyMimePart *mime_part;
2348 const gchar *mime_type = NULL;
2350 gchar *escaped_filename;
2353 GnomeVFSFileInfo *info;
2354 GnomeVFSURI *vfs_uri;
2356 gnome_vfs_close (handle);
2357 vfs_uri = gnome_vfs_uri_new (uri);
2360 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2361 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2362 g_free (escaped_filename);
2363 gnome_vfs_uri_unref (vfs_uri);
2365 info = gnome_vfs_file_info_new ();
2367 if (gnome_vfs_get_file_info (uri,
2369 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2371 mime_type = gnome_vfs_file_info_get_mime_type (info);
2372 mime_part = tny_platform_factory_new_mime_part
2373 (modest_runtime_get_platform_factory ());
2375 /* try to get the attachment's size; this may fail for weird
2376 * file systems, like obex, upnp... */
2377 if (allowed_size != 0 &&
2378 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2380 if (size > allowed_size) {
2381 modest_platform_information_banner (NULL, NULL,
2382 dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2386 g_warning ("%s: could not get attachment size", __FUNCTION__);
2388 stream = create_stream_for_uri (uri);
2390 if (stream == NULL) {
2392 modest_platform_information_banner (NULL, NULL, dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2394 g_object_unref (mime_part);
2395 gnome_vfs_file_info_unref (info);
2399 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2400 g_object_unref (stream);
2402 content_id = g_strdup_printf ("%d", priv->next_cid);
2403 tny_mime_part_set_content_id (mime_part, content_id);
2404 g_free (content_id);
2407 basename = g_path_get_basename (filename);
2408 tny_mime_part_set_filename (mime_part, basename);
2411 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2412 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2414 info->size == 0, info->size);
2415 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2416 gtk_widget_show_all (priv->attachments_caption);
2417 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2419 g_object_unref (mime_part);
2420 gnome_vfs_file_info_unref (info);
2427 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2430 ModestMsgEditWindowPrivate *priv;
2433 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2434 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2436 if (att_list == NULL) {
2437 att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2439 g_object_ref (att_list);
2442 if (tny_list_get_length (att_list) == 0) {
2443 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2445 gboolean dialog_response;
2446 gchar *message = NULL;
2447 gchar *filename = NULL;
2449 if (tny_list_get_length (att_list) == 1) {
2451 iter = tny_list_create_iterator (att_list);
2452 part = (TnyMimePart *) tny_iterator_get_current (iter);
2453 g_object_unref (iter);
2454 if (TNY_IS_MSG (part)) {
2455 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2457 filename = tny_header_dup_subject (header);
2458 g_object_unref (header);
2460 if (filename == NULL) {
2461 filename = g_strdup (_("mail_va_no_subject"));
2464 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2466 g_object_unref (part);
2468 filename = g_strdup ("");
2470 message = g_strdup_printf (ngettext("emev_nc_delete_attachment", "emev_nc_delete_attachments",
2471 tny_list_get_length (att_list)), filename);
2474 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window), message);
2477 if (dialog_response != GTK_RESPONSE_OK) {
2478 g_object_unref (att_list);
2481 hildon_banner_show_information (NULL, NULL, _("mcen_ib_removing_attachment"));
2483 for (iter = tny_list_create_iterator (att_list);
2484 !tny_iterator_is_done (iter);
2485 tny_iterator_next (iter)) {
2486 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2487 const gchar *att_id;
2488 tny_list_remove (priv->attachments, (GObject *) mime_part);
2490 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2492 if (tny_list_get_length (priv->attachments) == 0)
2493 gtk_widget_hide (priv->attachments_caption);
2494 att_id = tny_mime_part_get_content_id (mime_part);
2496 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2498 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2499 g_object_unref (mime_part);
2501 g_object_unref (iter);
2504 g_object_unref (att_list);
2506 /* if the last attachment has been removed, focus the Subject: field */
2507 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2508 gtk_widget_grab_focus (priv->subject_field);
2512 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2515 ModestMsgEditWindowPrivate *priv;
2516 GdkColor *new_color;
2517 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2519 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2520 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2523 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2525 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2527 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2529 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2534 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
2537 ModestMsgEditWindowPrivate *priv;
2538 gint new_size_index;
2539 ModestMsgEditWindow *window;
2542 window = MODEST_MSG_EDIT_WINDOW (userdata);
2543 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2544 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2546 if (gtk_check_menu_item_get_active (menu_item)) {
2548 WPTextBufferFormat format;
2550 memset (&format, 0, sizeof (format));
2551 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2553 label = gtk_bin_get_child (GTK_BIN (menu_item));
2555 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
2556 format.cs.font_size = TRUE;
2557 format.cs.text_position = TRUE;
2558 format.cs.font = TRUE;
2559 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
2560 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2562 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2563 GINT_TO_POINTER (wp_get_font_size_index (new_size_index, 12))))
2564 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2566 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2567 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
2568 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2574 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
2577 ModestMsgEditWindowPrivate *priv;
2578 gint new_font_index;
2579 ModestMsgEditWindow *window;
2582 window = MODEST_MSG_EDIT_WINDOW (userdata);
2583 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2584 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2586 if (gtk_check_menu_item_get_active (menu_item)) {
2589 label = gtk_bin_get_child (GTK_BIN (menu_item));
2591 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
2593 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2594 GINT_TO_POINTER(new_font_index)))
2595 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2597 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2598 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2599 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2605 modest_msg_edit_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
2607 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
2608 ModestWindowPrivate *parent_priv;
2609 ModestWindowMgr *mgr;
2610 gboolean is_fullscreen;
2611 GtkAction *fs_toggle_action;
2614 mgr = modest_runtime_get_window_mgr ();
2615 is_fullscreen = (modest_window_mgr_get_fullscreen_mode (mgr))?1:0;
2617 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
2619 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
2620 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
2621 if (is_fullscreen != active)
2622 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
2630 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2633 ModestMsgEditWindowPrivate *priv = NULL;
2634 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2636 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2637 if (!priv->update_caption_visibility)
2640 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2642 gtk_widget_show (priv->cc_caption);
2644 gtk_widget_hide (priv->cc_caption);
2646 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2650 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2653 ModestMsgEditWindowPrivate *priv = NULL;
2654 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2656 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2657 if (!priv->update_caption_visibility)
2660 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2662 gtk_widget_show (priv->bcc_caption);
2664 gtk_widget_hide (priv->bcc_caption);
2666 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2670 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2671 ModestRecptEditor *editor)
2673 ModestMsgEditWindowPrivate *priv;
2675 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2676 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2678 /* we check for low-mem; in that case, show a warning, and don't allow
2679 * for the addressbook
2681 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2684 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2686 if (editor == NULL) {
2687 GtkWidget *view_focus;
2688 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2690 /* This code should be kept in sync with ModestRecptEditor. The
2691 textview inside the recpt editor is the one that really gets the
2692 focus. As it's inside a scrolled window, and this one inside the
2693 hbox recpt editor inherits from, we'll need to go up in the
2694 hierarchy to know if the text view is part of the recpt editor
2695 or if it's a different text entry */
2697 if (gtk_widget_get_parent (view_focus)) {
2698 GtkWidget *first_parent;
2700 first_parent = gtk_widget_get_parent (view_focus);
2701 if (gtk_widget_get_parent (first_parent) &&
2702 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2703 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2708 editor = MODEST_RECPT_EDITOR (priv->to_field);
2712 modest_address_book_select_addresses (editor);
2717 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2719 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2721 modest_msg_edit_window_open_addressbook (window, NULL);
2725 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2726 gboolean show_toolbar)
2728 ModestWindowPrivate *parent_priv;
2729 const gchar *action_name;
2732 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2733 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2735 /* We can not just use the code of
2736 modest_msg_edit_window_setup_toolbar because it has a
2737 mixture of both initialization and creation code. */
2739 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2741 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2743 /* Update also the actions (to update the toggles in the
2744 menus), we have to do it manually because some other window
2745 of the same time could have changed it (remember that the
2746 toolbar fullscreen mode is shared by all the windows of the
2748 if (modest_window_mgr_get_fullscreen_mode (modest_runtime_get_window_mgr ()))
2749 action_name = "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarFullScreenMenu";
2751 action_name = "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarNormalScreenMenu";
2753 action = gtk_ui_manager_get_action (parent_priv->ui_manager, action_name);
2754 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
2760 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2761 TnyHeaderFlags priority_flags)
2763 ModestMsgEditWindowPrivate *priv;
2764 ModestWindowPrivate *parent_priv;
2766 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2768 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2769 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2771 if (priv->priority_flags != priority_flags) {
2772 GtkAction *priority_action = NULL;
2774 priv->priority_flags = priority_flags;
2776 switch (priority_flags) {
2777 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2778 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_high", GTK_ICON_SIZE_MENU);
2779 gtk_widget_show (priv->priority_icon);
2780 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2781 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2783 case TNY_HEADER_FLAG_LOW_PRIORITY:
2784 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_low", GTK_ICON_SIZE_MENU);
2785 gtk_widget_show (priv->priority_icon);
2786 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2787 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2790 gtk_widget_hide (priv->priority_icon);
2791 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2792 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2795 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2796 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2801 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2804 ModestMsgEditWindowPrivate *priv;
2805 ModestWindowPrivate *parent_priv;
2806 gint current_format;
2808 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2810 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2811 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2813 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2814 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2816 if (current_format != file_format) {
2817 switch (file_format) {
2818 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2819 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2820 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
2822 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2826 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2827 response = gtk_dialog_run (GTK_DIALOG (dialog));
2828 gtk_widget_destroy (dialog);
2829 if (response == GTK_RESPONSE_OK) {
2830 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2832 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu"));
2833 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
2838 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2839 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2840 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2845 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2848 ModestMsgEditWindowPrivate *priv;
2849 WPTextBufferFormat oldfmt, fmt;
2850 gint old_position = 0;
2854 GdkColor *color = NULL;
2855 gboolean bold, bold_set, italic, italic_set;
2856 gboolean underline, underline_set;
2857 gboolean strikethrough, strikethrough_set;
2858 gboolean position_set;
2859 gboolean font_size_set, font_set, color_set;
2862 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2863 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2865 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2866 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
2867 GTK_WINDOW(dialog), GTK_WINDOW (window));
2869 /* First we get the currently selected font information */
2870 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2872 switch (oldfmt.text_position) {
2873 case TEXT_POSITION_NORMAL:
2876 case TEXT_POSITION_SUPERSCRIPT:
2884 g_object_set (G_OBJECT (dialog),
2885 "bold", oldfmt.bold != FALSE,
2886 "bold-set", !oldfmt.cs.bold,
2887 "underline", oldfmt.underline != FALSE,
2888 "underline-set", !oldfmt.cs.underline,
2889 "italic", oldfmt.italic != FALSE,
2890 "italic-set", !oldfmt.cs.italic,
2891 "strikethrough", oldfmt.strikethrough != FALSE,
2892 "strikethrough-set", !oldfmt.cs.strikethrough,
2893 "color", &oldfmt.color,
2894 "color-set", !oldfmt.cs.color,
2895 "size", wp_font_size[oldfmt.font_size],
2896 "size-set", !oldfmt.cs.font_size,
2897 "position", old_position,
2898 "position-set", !oldfmt.cs.text_position,
2899 "family", wp_get_font_name (oldfmt.font),
2900 "family-set", !oldfmt.cs.font,
2903 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2904 GTK_WINDOW (dialog), GTK_WINDOW (window));
2905 gtk_widget_show_all (dialog);
2906 priv->font_dialog = dialog;
2907 response = gtk_dialog_run (GTK_DIALOG (dialog));
2908 priv->font_dialog = NULL;
2909 if (response == GTK_RESPONSE_OK) {
2911 g_object_get( dialog,
2913 "bold-set", &bold_set,
2914 "underline", &underline,
2915 "underline-set", &underline_set,
2917 "italic-set", &italic_set,
2918 "strikethrough", &strikethrough,
2919 "strikethrough-set", &strikethrough_set,
2921 "color-set", &color_set,
2923 "size-set", &font_size_set,
2924 "family", &font_name,
2925 "family-set", &font_set,
2926 "position", &position,
2927 "position-set", &position_set,
2932 if (response == GTK_RESPONSE_OK) {
2933 memset(&fmt, 0, sizeof(fmt));
2939 fmt.italic = italic;
2940 fmt.cs.italic = TRUE;
2942 if (underline_set) {
2943 fmt.underline = underline;
2944 fmt.cs.underline = TRUE;
2946 if (strikethrough_set) {
2947 fmt.strikethrough = strikethrough;
2948 fmt.cs.strikethrough = TRUE;
2953 ? TEXT_POSITION_NORMAL
2954 : ( ( position == 1 )
2955 ? TEXT_POSITION_SUPERSCRIPT
2956 : TEXT_POSITION_SUBSCRIPT );
2957 fmt.cs.text_position = TRUE;
2958 fmt.font_size = oldfmt.font_size;
2962 fmt.cs.color = TRUE;
2965 fmt.font = wp_get_font_index(font_name,
2970 if (font_size_set) {
2971 fmt.cs.font_size = TRUE;
2972 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
2974 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2975 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2977 gtk_widget_destroy (dialog);
2979 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2983 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2985 ModestMsgEditWindowPrivate *priv;
2987 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2988 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2990 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2992 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2993 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2997 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
2999 ModestMsgEditWindowPrivate *priv;
3001 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3002 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3004 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
3006 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3007 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3012 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
3014 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3016 priv->can_undo = can_undo;
3020 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
3022 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3024 priv->can_redo = can_redo;
3028 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3030 ModestMsgEditWindowPrivate *priv;
3031 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3032 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3034 return priv->can_undo;
3038 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3040 ModestMsgEditWindowPrivate *priv;
3041 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3042 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3044 return priv->can_redo;
3049 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3052 GtkTextIter match_start, match_end;
3054 if (image_id == NULL)
3057 gtk_text_buffer_get_start_iter (buffer, &iter);
3059 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3060 GSList *tags = gtk_text_iter_get_tags (&match_start);
3062 for (node = tags; node != NULL; node = g_slist_next (node)) {
3063 GtkTextTag *tag = (GtkTextTag *) node->data;
3064 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3065 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3066 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3068 offset = gtk_text_iter_get_offset (&match_start);
3069 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3070 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3074 gtk_text_iter_forward_char (&iter);
3079 message_is_empty (ModestMsgEditWindow *window)
3081 ModestMsgEditWindowPrivate *priv = NULL;
3083 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3084 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3086 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3087 * so we can ignore markup.
3089 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3092 count = gtk_text_buffer_get_char_count (buf);
3098 msg_body_focus (GtkWidget *focus,
3099 GdkEventFocus *event,
3103 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3104 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3105 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3110 recpt_field_changed (GtkTextBuffer *buffer,
3111 ModestMsgEditWindow *editor)
3113 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3114 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3118 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3120 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3121 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3125 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3128 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3129 GtkTextBuffer *buffer;
3131 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3132 gtk_text_buffer_set_modified (buffer, modified);
3133 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3134 gtk_text_buffer_set_modified (buffer, modified);
3135 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3136 gtk_text_buffer_set_modified (buffer, modified);
3137 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3141 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3143 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3144 const char *account_name;
3145 GtkTextBuffer *buffer;
3147 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3148 if (gtk_text_buffer_get_modified (buffer))
3150 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3151 if (gtk_text_buffer_get_modified (buffer))
3153 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3154 if (gtk_text_buffer_get_modified (buffer))
3156 if (gtk_text_buffer_get_modified (priv->text_buffer))
3158 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3159 if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3170 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3172 ModestMsgEditWindowPrivate *priv = NULL;
3174 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3175 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3177 /* check if there's no recipient added */
3178 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3179 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3180 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3181 /* no recipient contents, then select contacts */
3182 modest_msg_edit_window_open_addressbook (window, NULL);
3186 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3187 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3190 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3191 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3194 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3195 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3199 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3200 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3201 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3208 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3209 ModestMsgEditWindow *window)
3211 modest_msg_edit_window_offer_attach_file (window);
3215 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3217 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3219 return priv->clipboard_text;
3223 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3225 ModestMsgEditWindow *window)
3227 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3228 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3230 if (!GTK_WIDGET_VISIBLE (window))
3233 g_object_ref (window);
3234 text = gtk_clipboard_wait_for_text (selection_clipboard);
3236 if (priv->clipboard_text != NULL) {
3237 g_free (priv->clipboard_text);
3239 priv->clipboard_text = text;
3241 if (GTK_WIDGET_VISIBLE (window)) {
3242 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3244 g_object_unref (window);
3247 static gboolean clipboard_owner_change_idle (gpointer userdata)
3249 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3250 ModestMsgEditWindowPrivate *priv;
3252 gdk_threads_enter ();
3253 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3254 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3256 priv->clipboard_owner_idle = 0;
3257 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3258 gdk_threads_leave ();
3264 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3266 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3267 if (priv->clipboard_owner_idle == 0) {
3268 priv->clipboard_owner_idle = g_idle_add (clipboard_owner_change_idle, window);
3273 subject_field_move_cursor (GtkEntry *entry,
3274 GtkMovementStep step,
3279 if (!GTK_WIDGET_VISIBLE (window))
3282 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3286 update_window_title (ModestMsgEditWindow *window)
3288 ModestMsgEditWindowPrivate *priv = NULL;
3289 const gchar *subject;
3291 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3292 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3293 if (subject == NULL || subject[0] == '\0')
3294 subject = _("mail_va_new_email");
3296 gtk_window_set_title (GTK_WINDOW (window), subject);
3301 subject_field_changed (GtkEditable *editable,
3302 ModestMsgEditWindow *window)
3304 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3305 update_window_title (window);
3306 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3307 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3308 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3312 subject_field_insert_text (GtkEditable *editable,
3314 gint new_text_length,
3316 ModestMsgEditWindow *window)
3318 GString *result = g_string_new ("");
3320 gint result_len = 0;
3321 const gchar *entry_text = NULL;
3324 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3325 old_length = g_utf8_strlen (entry_text, -1);
3327 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3328 gunichar c = g_utf8_get_char_validated (current, 8);
3329 /* Invalid unichar, stop */
3335 result = g_string_append_unichar (result, c);
3339 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3340 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3343 /* Prevent endless recursion */
3344 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3345 g_signal_emit_by_name (editable, "insert-text",
3346 (gpointer) result->str, (gpointer) result->len,
3347 (gpointer) position, (gpointer) window);
3348 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3352 if (result_len + old_length > 1000) {
3353 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3354 dgettext("hildon-common-strings",
3355 "ckdg_ib_maximum_characters_reached"));
3358 g_string_free (result, TRUE);
3362 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3365 ModestMsgEditWindowPrivate *priv = NULL;
3367 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3368 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3370 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3373 gtk_widget_show_all (priv->find_toolbar);
3374 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3376 gtk_widget_hide_all (priv->find_toolbar);
3377 gtk_widget_grab_focus (priv->msg_body);
3383 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3385 GtkTextIter *match_start,
3386 GtkTextIter *match_end)
3388 GtkTextIter end_iter;
3389 gchar *str_casefold;
3392 gchar *range_casefold;
3395 gboolean result = FALSE;
3402 gtk_text_iter_forward_to_end (&end_iter);
3404 str_casefold = g_utf8_casefold (str, -1);
3405 str_chars_n = strlen (str);
3407 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3408 range_casefold = g_utf8_casefold (range_text, -1);
3409 range_chars_n = strlen (range_casefold);
3411 if (range_chars_n < str_chars_n) {
3412 g_free (str_casefold);
3413 g_free (range_text);
3414 g_free (range_casefold);
3418 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3419 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3420 if (!g_utf8_collate (range_subtext, str_casefold)) {
3421 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3423 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3424 match_start, match_end, NULL);
3425 g_free (found_text);
3427 g_free (range_subtext);
3431 g_free (str_casefold);
3432 g_free (range_text);
3433 g_free (range_casefold);
3440 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3441 ModestMsgEditWindow *window)
3443 gchar *current_search = NULL;
3444 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3446 GtkTextIter selection_start, selection_end;
3447 GtkTextIter match_start, match_end;
3448 gboolean continue_search = FALSE;
3450 if (message_is_empty (window)) {
3451 g_free (priv->last_search);
3452 priv->last_search = NULL;
3453 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3457 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3458 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3459 g_free (current_search);
3460 g_free (priv->last_search);
3461 priv->last_search = NULL;
3462 /* Information banner about empty search */
3463 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-common-strings", "ecdg_ib_find_rep_enter_text"));
3467 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3468 continue_search = TRUE;
3470 g_free (priv->last_search);
3471 priv->last_search = g_strdup (current_search);
3474 if (continue_search) {
3475 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3476 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3477 &match_start, &match_end);
3479 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_search_complete"));
3481 GtkTextIter buffer_start;
3482 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3483 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3484 &match_start, &match_end);
3486 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_no_matches"));
3489 /* Mark as selected the string found in search */
3491 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3492 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3493 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3495 g_free (priv->last_search);
3496 priv->last_search = NULL;
3498 g_free (current_search);
3502 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3503 ModestMsgEditWindow *window)
3505 GtkToggleAction *toggle;
3506 ModestWindowPrivate *parent_priv;
3507 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3509 toggle = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ToolsMenu/FindInMessageMenu"));
3510 gtk_toggle_action_set_active (toggle, FALSE);
3514 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3516 ModestMsgEditWindowPrivate *priv;
3518 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3523 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3526 ModestMsgEditWindowPrivate *priv;
3528 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3534 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3537 ModestMsgEditWindowPrivate *priv;
3538 TnyHeader *header = NULL;
3540 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3541 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3543 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3544 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3546 if (priv->draft_msg != NULL) {
3547 g_object_unref (priv->draft_msg);
3550 if (draft != NULL) {
3551 g_object_ref (draft);
3552 header = tny_msg_get_header (draft);
3553 if (priv->msg_uid) {
3554 g_free (priv->msg_uid);
3555 priv->msg_uid = NULL;
3557 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3558 if (GTK_WIDGET_REALIZED (window)) {
3559 if (!modest_window_mgr_register_window (mgr, MODEST_WINDOW (window), NULL)) {
3560 gtk_widget_destroy (GTK_WIDGET (window));
3566 priv->draft_msg = draft;
3570 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3571 GtkTextIter *start, GtkTextIter *end,
3574 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3575 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3578 if (tag == NULL) return;
3579 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3580 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3581 replace_with_images (window, priv->images);
3586 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3589 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3591 g_return_if_fail (TNY_IS_MIME_PART (part));
3592 tny_list_prepend (priv->attachments, (GObject *) part);
3593 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3594 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3595 gtk_widget_show_all (priv->attachments_caption);
3596 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3600 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3602 ModestMsgEditWindowPrivate *priv;
3604 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3605 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3607 return priv->msg_uid;
3611 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3612 ModestMsgEditWindowWidgetType widget_type)
3614 ModestMsgEditWindowPrivate *priv;
3616 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3617 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3619 switch (widget_type) {
3620 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3621 return priv->msg_body;
3623 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3624 return priv->to_field;
3626 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3627 return priv->cc_field;
3629 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3630 return priv->bcc_field;
3632 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3633 return priv->subject_field;
3635 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3636 return priv->attachments_view;
3644 remove_tags (WPTextBuffer *buffer)
3646 GtkTextIter start, end;
3648 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3649 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3651 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3655 on_account_removed (TnyAccountStore *account_store,
3656 TnyAccount *account,
3659 /* Do nothing if it's a store account, because we use the
3660 transport to send the messages */
3661 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3662 const gchar *parent_acc = NULL;
3663 const gchar *our_acc = NULL;
3665 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3666 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3667 /* Close this window if I'm showing a message of the removed account */
3668 if (strcmp (parent_acc, our_acc) == 0)
3669 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3674 on_zoom_minus_plus_not_implemented (ModestWindow *window)
3676 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3678 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
3684 set_zoom_do_nothing (ModestWindow *window,
3690 get_zoom_do_nothing (ModestWindow *window)